An easy way to double check your SQLlite syntax

While in the Android Developer Course, I am finding a little problem with using SQLlite. In Android Studio, when writing Java, Android Studio knows when the code you typed has an error, and it underlines it in red, showing you something you should fix.

However, when you are using SQLlite in your java code. Android Studio has no idea what you are talking about. This causes me a bit of heartburn as I run my apps only to find that something is wrong with my SQL code, but no idea of what to fix.

Thus enter https://sqliteonline.com/ ! I can copy and paste syntax into the web gui and give it a quick run to see if it even works. It has been most helpful to say the least. If you are just starting out with SQLlite, I highly recommend it over other web gui interfaces for testing, because it has a simple display on the left side, showing you all of your tables, views, indexes, and triggers. For a simpleton like me, that is really helpful to have a visual representation.

Linux – keep it simple.

Using SQLlite in your Android app

So, as part of my Android Developer Course by Rob Percival (which is excellent, and I highly recommend every computer/Android geek take), he showed us how to make use of SQLlite in our Android app. In the demonstration and challenge, he was using static inputs, like this:
// And add some information to that table.
firstDatabaseEver.execSQL(“INSERT INTO events (name, year) VALUES (‘Birth’, 1985)”);

Which is great. He was just showing us how SQLlite worked. With that said, in a really useful app, I figured I would need a way to take a user’s input and put it into the table, so I fiddled around a bit, and here is what I came up with.

MainActivity.java:
/* Copyright 2017 by AlaskaLinuxUser (https://thealaskalinuxuser.wordpress.com)
*
* Licensed under the Apache License, Version 2.0 (the “License”);
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an “AS IS” BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.alaskalinuxuser.sqllitedemo;

import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;

public class MainActivity extends AppCompatActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

// Let’s make some variables to use later.
String nameVar = “Joined the Navy”;
int yearVar = 2004;

try {

// First, make a database, open or create will open if exist, create if not.
SQLiteDatabase firstDatabaseEver = this.openOrCreateDatabase(“events”, MODE_PRIVATE, null);

// Now, let’s ceate a table.
firstDatabaseEver.execSQL(“CREATE TABLE IF NOT EXISTS events (name VARCHAR, year INT(4))”);

// And add some information to that table.
firstDatabaseEver.execSQL(“INSERT INTO events (name, year) VALUES (‘Birth’, 1985)”);

// And a second one for fun, this time, we will use our variable we created, you can see
// how this would be useful for an app, so you could have the user’s input dumped into a
// table.
firstDatabaseEver.execSQL(“INSERT INTO events (name, year) VALUES (‘” + nameVar + “‘, ” + yearVar + “)”);

// Now we need a cursor to retreive the data with a query.
Cursor myCursor = firstDatabaseEver.rawQuery(“SELECT * FROM events”, null);

// Now that we have the data, we need a way to index them, or grab the parts we need.
int nameIndex = myCursor.getColumnIndex(“name”);
int yearIndex = myCursor.getColumnIndex(“year”);

// Let’s start from the top of the table, by moving to the first position.
myCursor.moveToFirst();

// And if it is not null, let’s use it.
while (myCursor != null){

// Logging for posterity….
Log.i(“WJH”, myCursor.getString(nameIndex));
Log.i(“WJH”, Integer.toString(myCursor.getInt(yearIndex)));

// And move on to the next result in the table.
myCursor.moveToNext();
}
} catch (Exception e) {

e.printStackTrace();

}
}
}

Note that I don’t actually have user’s input into the table here, but I did use variables to input the data into the table, like so:

// Let’s make some variables to use later.
String nameVar = “Joined the Navy”;
int yearVar = 2004;

// And a second one for fun, this time, we will use our variable we created, you can see
// how this would be useful for an app, so you could have the user’s input dumped into a
// table.
firstDatabaseEver.execSQL(“INSERT INTO events (name, year) VALUES (‘” + nameVar + “‘, ” + yearVar + “)”);

As we can see, the input into the table of “events” is based on the output of the variables “nameVar and yearVar, which I previously defined. It is really easy to see that we could use something like getText from an editText field and input those variables into the tables. Which I think is the best use of it.

Linux – keep it simple.

Using your Open Weather Map API key

If you are reading this, you are probably trying to figure out how to use your api key from openweathermap.org. If you are reading this and don’t know what that is, don’t feel bad. I didn’t either until I started my Android Developer Course. In a nutshell, when your phone app tells you the weather, it gets it from a server somewhere in a special format, called an API, which returns a JSON object. At least, that’s how I understand it.

The problem is, that server will not just tell anyone the data. All of these servers want you to have a key. Most sites offer some sort of free plan for a very limited number of calls, particularly for developers or for personal use. This requires an account. So I got one at openweathermap, and then was given a key.

One of the principle things you need to get the api data from a provider is an api key. This is where I was having big trouble. After registering and getting the key, I then went to the guide on how to use it. It is located here if you are interested, but it didn’t work.

http://openweathermap.org/appid#get

In the guide it told me to use this call method:

http://api.openweathermap.org/data/2.5/forecast/city?id=524901&APPID=1111111111

Except with my key after APPID=, instead of the 111111111’s. The problem was, it would return this error when I made the call:

{“cod”:401, “message”: “Invalid API key. Please see http://openweathermap.org/faq#error401 for more info.”}

or sometimes this one:

“This site can’t be reached

api.openweathermap.org refused to connect.”

I was getting a little bit frustrated. I reread the documentation, and I still got bad results. I waited until the next day to make sure my calls per day were reset. Still no luck. I googled, I searched, and eventually, I got to this thread:

https://github.com/cmfcmf/OpenWeatherMap-PHP-Api/issues/46

Where I learned two really important things that made it all work:

#1. Don’t use https:// in the call, use http:// instead.

#2. Instead of APPID in the call, use appid (lowercase) in the call to get the results.

Once I did these two things, it immediately started working for me. So if you are having trouble, you should give that a try. Hopefully this will save you hours of frustration.

Linux – keep it simple.

Downloading internet content and apps about the worlds richest celebrities

In the continuing saga of my Android Developer Course with Rob Percival, I needed to make an app that would show a picture of a famous celebrity, and give the user a multiple choice quiz on who it was. Once clicked, it should tell you if you pass or fail, and load the next picture and names.

I decided to be different. Instead, I chose to have one name and four pictures. You can download the app here:

http://www.mediafire.com/file/srrey66ma3hxe5i/guesstherichcelebrity.apk

device-2017-03-13-131637

But be warned, when you click on your celebrity choice, you have to wait until it puts up a right/wrong toast before clicking again. Oh, you can click again, and it will not crash, but then you will only prolong the wait, which is a bit lengthy, due to my fledgling Java skills. Or maybe it is just my slow internet. Either way, be patient.

The way I went about doing this in my app was actually quite a bit different than that of my instructors. His way was much more streamlined and worked faster. I was happy that mine did work, though, Praise God!

Here’s what I did:

MainActivity.java

[CODE]
/* Copyright 2017 by AlaskaLinuxUser (https://thealaskalinuxuser.wordpress.com)
*
* Licensed under the Apache License, Version 2.0 (the “License”);
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an “AS IS” BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.alaskalinuxuser.guessthatceleb;

// Import some libraries….
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.os.AsyncTask;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Random;
import java.util.concurrent.ExecutionException;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class MainActivity extends AppCompatActivity {

// Declare our strings, integers, imageviews, bitmaps, and textviews.
String result;
int celebNum;
int aCeleb;
int rightAnswer;
String foundString;
String whosWho;
String whosName;
String whoWins;
ImageView picOne;
ImageView picTwo;
ImageView picThree;
ImageView picFour;
TextView nameText;
Bitmap winningPic;
Bitmap myBit;

// Our new class to download the page html data to parse for info.
public class DownloadPage extends AsyncTask<String, Void, String> {

// Do this in the background.
@Override
protected String doInBackground(String… urls) {

// A few declared items.
result = “”;
URL url;
HttpURLConnection urlConnection = null;
//Log.i(“WJH”, urls[0]); // To log that the URL arrived in the class when called.

// Try this.
try {

// Make our URL based on our given url to lookup.
url = new URL(urls[0]);

// Make a connection for that URL and open it.
urlConnection = (HttpURLConnection) url.openConnection();

// Start an input stream to get the bits.
InputStream in = urlConnection.getInputStream();

// Buffer it to reader.
BufferedReader reader = new BufferedReader(new InputStreamReader(in, “iso-8859-1”), 8);

// Build it string by string.
StringBuilder sb = new StringBuilder();
String line = null;
while ((line = reader.readLine()) != null) // Read line by line
sb.append(line + “\n”);

// Here is the result.
String resString = sb.toString();

// Close the stream.
in.close();

// Tie the result to our variable that is known outside of this class.
result = resString;

// return that variable.
return result;

// Have an exception clause so you don’t crash.
} catch (Exception e) {

e.printStackTrace();

return “Failed”;

}

}

}

// Our new class to download the picture in the background.
public class DownloadPic extends AsyncTask<String, Void, Bitmap> {

@Override
protected Bitmap doInBackground(String… urls) {

String result = “”;
URL url;
HttpURLConnection urlConnection;

try {

url = new URL(urls[0]);

urlConnection = (HttpURLConnection) url.openConnection();

// To download in one “go” as Rob says.
urlConnection.connect();

// To grab the whole thing at once.
InputStream inStream = urlConnection.getInputStream();

// Turn that data into a bitmap.
myBit = BitmapFactory.decodeStream(inStream);

// Return that bitmap.
return myBit;

// Have an exception if there is a failure.
} catch (Exception e) {

e.printStackTrace();

//Log.i(“WJH”, “Failed”); // You can log this to see the failure if needed.

// Since it fails, return nothing.
return null;

}

}
}

// Our random number generator.
public void randomIzer() {

// The random number generator itself.
Random ranGen = new Random();

// The random number of richest celebrities.
celebNum = ranGen.nextInt(20);

// The random number of the right answer.
rightAnswer = ranGen.nextInt(4);

//Log.i(“WJH”, Integer.toString(rightAnswer)); // Log this to test the random number answer.

}

// Our method to get the name of the celebrity.
public void getCelebname(){

// Call the class to download the page.
DownloadPage task = new DownloadPage();
String result = null;

// my trick number we will use later.
aCeleb=0;

try {

// execute, or go on and do that task.
result = task.execute(“http://www.therichest.com/top-lists/top-100-richest-celebrities&#8221;).get();

// A fail clause.
} catch (Exception e) {

e.printStackTrace();

}

// Now regex the data with this pattern.
Pattern pat = Pattern.compile(“<span>(.*?)</span>”);

// And search for matches in the results.
Matcher mat = pat.matcher(result);

// For every one you find, do this.
while (mat.find() && aCeleb <= celebNum) {

// Add to my magic number.
aCeleb++;

// The search results.
String foundNameString = (mat.group(1));

// Tie the search results to a public variable we can use outside of this method.
whosName = foundNameString;

//Log.i(“WJH”, whosName); // Log to see if this is working.

}

}

// And a method to figure out which picture we need. Same as above method, just a different
// search pattern.
public void getCelebpic(){

DownloadPage task = new DownloadPage();
String result = null;
aCeleb=0;

try {

result = task.execute(“http://www.therichest.com/top-lists/top-100-richest-celebrities&#8221;).get();

} catch (Exception e) {

e.printStackTrace();

}

Pattern pat = Pattern.compile(“0px\\)\” sizes=\”70px\” srcset=\”(.*?)\””);

Matcher mat = pat.matcher(result);

while (mat.find() && aCeleb <= celebNum – 1) {

aCeleb++;

foundString = (mat.group(1));

whosWho = foundString;

//Log.i(“WJH”, foundString); // Log to see if this is working.

}

}

// Ok, now we need to download that picture.
public void downloadPics(){

// Call the class to download the picture.
DownloadPic task = new DownloadPic();

try {

// Let’s get the picture.
Bitmap myImage = task.execute(whosWho).get();

} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}

}

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

// Define a few objects.
picOne = (ImageView)findViewById(R.id.imageViewZero);
picTwo = (ImageView)findViewById(R.id.imageViewOne);
picThree = (ImageView)findViewById(R.id.imageViewTwo);
picFour = (ImageView)findViewById(R.id.imageViewThree);
nameText = (TextView)findViewById(R.id.nameView);

// Set up our first round.
setupGame();

}

// The method to set up each round of choices.
public void setupGame() {

// Call the randomizer method.
randomIzer();

// Okay, so the real winner is:
// Get the winner name.
getCelebname();
// Set the winner name to the text field.
nameText.setText(whosName);
// Get the URL for the celeb pic.
getCelebpic();
// Tie in our winning variable, since we will overwrite it later.
whoWins = whosWho;
// Call the method to download the pic.
downloadPics();
// Tie in our winning pic to our downloaded pic, since we will overwrite it later.
winningPic = myBit;

// if/then. if you are the right answer, set your pic to the winning pic.
if (rightAnswer == 0) {

picOne.setImageBitmap(winningPic);

} else {

// If not, then plus one on the celebNum and call for a random picture.
celebNum++;
getCelebpic();
downloadPics();
picOne.setImageBitmap(myBit);

}

if (rightAnswer == 1) {

picTwo.setImageBitmap(winningPic);

} else {

celebNum++;
getCelebpic();
downloadPics();
picTwo.setImageBitmap(myBit);

}

if (rightAnswer == 2) {

picThree.setImageBitmap(winningPic);

} else {

celebNum++;
getCelebpic();
downloadPics();
picThree.setImageBitmap(myBit);

}

if (rightAnswer == 3) {

picFour.setImageBitmap(winningPic);

} else {

celebNum++;
getCelebpic();
downloadPics();
picFour.setImageBitmap(myBit);

}
}

// Well, am I right? This is called through onClick of each imageview.
public void amIRight(View view){

// Make a tag number string with get tag for the clicked object.
String tagNum = (String) view.getTag();
//Log.i(“WJH”, Integer.toString(rightAnswer)); // Log to see if this is working.
//Log.i(“WJH”, tagNum); // Log to see if this is working.
// Parse the integer from the string.
int taggedNum = Integer.parseInt(tagNum);
// Define a toast text for later.
String toastText;

// If the tagged number of the clicked square is the right answer….
if (taggedNum == rightAnswer) {

// Set the text to correct.
toastText = “Correct!”;

// If not….
} else {

// Set the text to incorrect.
toastText = “Incorrect.”;

}

// Set up the next round.
setupGame();

// And tell the user if they were right or not.
Toast.makeText(getApplicationContext(), toastText, Toast.LENGTH_LONG).show();

/* This may seem a bit odd. Logic would dictate we toast first, then set up the
* next round. But, if I toast first, the toast does not display because the phone
* is working too hard to get the new pictures. This way, we wait until the new pictures
* are in, then display the toast, which works, but seems sloppy.
*/
}
}
[/CODE]

And the activity_main.xml

[CODE]
<?xml version=”1.0″ encoding=”utf-8″?>
<LinearLayout
xmlns:android=”http://schemas.android.com/apk/res/android&#8221;
xmlns:app=”http://schemas.android.com/apk/res-auto&#8221;
xmlns:tools=”http://schemas.android.com/tools&#8221;
android:id=”@+id/activity_main”
android:layout_width=”match_parent”
android:layout_height=”match_parent”
android:orientation=”vertical”
android:paddingLeft=”@dimen/activity_horizontal_margin”
android:paddingRight=”@dimen/activity_horizontal_margin”
android:paddingTop=”@dimen/activity_vertical_margin”
android:paddingBottom=”@dimen/activity_vertical_margin”
tools:context=”com.alaskalinuxuser.guessthatceleb.MainActivity”
android:gravity=”top|center_horizontal”>

<TextView
android:text=”TextView”
android:layout_width=”wrap_content”
android:layout_height=”wrap_content”
android:layout_alignParentTop=”true”
android:layout_centerHorizontal=”true”
android:id=”@+id/nameView”
android:textSize=”40sp”
android:layout_margin=”25dp” />

<GridLayout
android:layout_width=”wrap_content”
android:layout_height=”wrap_content”
android:layout_centerVertical=”true”
android:layout_centerHorizontal=”true”
android:rowCount=”2″
android:columnCount=”2″>

<ImageView
android:layout_height=”150dp”
android:layout_width=”150dp”
android:src=”@mipmap/ic_launcher”
android:layout_row=”0″
android:layout_column=”0″
android:tag=”0″
android:onClick=”amIRight”
android:id=”@+id/imageViewZero” />

<ImageView
android:layout_height=”150dp”
android:layout_width=”150dp”
android:src=”@mipmap/ic_launcher”
android:layout_row=”0″
android:layout_column=”1″
android:tag=”1″
android:onClick=”amIRight”
android:id=”@+id/imageViewOne” />

<ImageView
android:layout_height=”150dp”
android:layout_width=”150dp”
android:src=”@mipmap/ic_launcher”
android:layout_row=”1″
android:layout_column=”0″
android:tag=”2″
android:onClick=”amIRight”
android:id=”@+id/imageViewTwo” />

<ImageView
android:layout_height=”150dp”
android:layout_width=”150dp”
android:src=”@mipmap/ic_launcher”
android:layout_row=”1″
android:layout_column=”1″
android:tag=”3″
android:onClick=”amIRight”
android:id=”@+id/imageViewThree” />

</GridLayout>
</LinearLayout>
[/CODE]

Of course, don’t forget to add internet permission in the AndroidManifest.xml:

[CODE]
<?xml version=”1.0″ encoding=”utf-8″?>
<manifest xmlns:android=”http://schemas.android.com/apk/res/android&#8221;
package=”com.alaskalinuxuser.guessthatceleb” >

<uses-permission android:name=”android.permission.INTERNET”/>

<application
android:allowBackup=”true”
android:icon=”@mipmap/ic_launcher”
android:label=”@string/app_name”
android:supportsRtl=”true”
android:theme=”@style/AppTheme” >
<activity android:name=”.MainActivity” >
<intent-filter>
<action android:name=”android.intent.action.MAIN” />

<category android:name=”android.intent.category.LAUNCHER” />
</intent-filter>
</activity>
</application>

</manifest>
[/CODE]

All of the java has notes sprinkled throughout for definitions of what I am trying to attempt. Be sure to check it out, and if you find it useful, be sure to use it! You can always check my github for these small apps if you want to download it and test out some other methods or use it in your own projects.

Linux – keep it simple.

 

A brain teaser app!

For my continued education, I was required to make a brain teaser app which had several elements. Here is a download link if you want to try the finished product:

http://www.mediafire.com/file/xgmsnxqy58gdq8f/brain_test.apk

device-2017-03-06-083331

The whole thing hinged on this random number generator. I particularly struggled with this. I needed to have a question (x + y) and then have four random answers to pick from, only having one of which as the answer. At first I was working it from the beginning to the end: coming up with random x, and then adding random y, and then putting that into the text boxes randomly and making some new numbers. But, I eventually realized that I was working the problem the “long way around”.

Instead, I decided to make just one random answer, and split that into my question instead. This became much simpler. There are probably better ways to do this, but here is what I put together:

[CODE]
// And we need a random number generator.
public void randomNumber() {

// The actual number generator.
Random smallGen = new Random();

// To pick the tile threat is the answer.
// Remember: 0 is a number.
answerNum = smallGen.nextInt(4);

// Now to pick a number between 1 and 20.
// And assign that number to each tile.
randNumZero = smallGen.nextInt(19) + 1;
p0.setText(String.valueOf(randNumZero));

randNumOne = randNumZero + 6;
p1.setText(String.valueOf(randNumOne));

randNumTwo = randNumZero – 1;
p2.setText(String.valueOf(randNumTwo));

randNumThree = randNumZero + 3;
p3.setText(String.valueOf(randNumThree));

// And our random first number of our question.
// A number between 1 and 20. We will minus this from
// the answer to get the second number.
firstNum = smallGen.nextInt(19) + 1;

// Now to get the question.
if (answerNum == 0) {

secondNum = randNumZero – firstNum;

} else if (answerNum == 1) {

secondNum = randNumOne – firstNum;

} else if (answerNum == 2) {

secondNum = randNumTwo – firstNum;

} else {

secondNum = randNumThree – firstNum;

}

String fN = String.valueOf(firstNum);
String sN = String.valueOf(secondNum);

questionView.setText(fN + ” + ” + sN);

}
[/CODE]

Which worked great. Originally, I had created four random possible answers and then chose one at random as THE answer. However, I came to realize that sometimes the random possible answers could be the same as the random answer itself. That is when I changed randNumZero to be the only truly random number, the other randomNum objects are set additives and detraction from the actual random number. That makes them random to a point, since they are based from the random number.

After these possible answers are made, I then randomly choose one of them to be the answer, and from that minus a random number to get my two numbers for the question (the small minus random number and the derivative). Praise God! It even worked! This had an added benefit of allowing negative numbers, which really challenges the user’s math skills, since you only have 30 seconds to answer as many questions as possible.

Enjoy the math game!

Linux – keep it simple

Apache bouncy castles….

So, another day, and another error. While building SlimRoms 7 for the Note Edge, I ran into this error:

[CODE]
[ 0% 60/15886] Docs droiddoc: /home/a…rget/common/docs/apache-http-stubs-gen
external/apache-http/../../frameworks/base/core/java/android/net/http/SslCertificate.java:19: error: cannot find symbol
import com.android.internal.util.HexDump;
^
symbol: class HexDump
location: package com.android.internal.util
external/apache-http/../../frameworks/base/core/java/android/net/http/SslCertificate.java:42: error: package com.android.org.bouncycastle.asn1.x509 does not exist
import com.android.org.bouncycastle.asn1.x509.X509Name;
^
external/apache-http/../../frameworks/base/core/java/android/net/http/HttpResponseCache.java:19: error: package com.android.okhttp does not exist
import com.android.okhttp.Cache;
^
external/apache-http/../../frameworks/base/core/java/android/net/http/HttpResponseCache.java:20: error: package com.android.okhttp does not exist
import com.android.okhttp.AndroidShimResponseCache;
[/CODE]

Hours of online surfing and scrounging, and trying different things led me to this Google issue:
https://code.google.com/p/android/issues/detail?id=230820

That perfectly detailed the same problem I had, as well as providing a viable solution. So I implemented it by opening build_slim7/external/apache-http/Android.mk, which read (among other things) :

[CODE]
LOCAL_JAVA_LIBRARIES := $(apache_http_java_libs)
LOCAL_MODULE_CLASS := JAVA_LIBRARIES
LOCAL_DROIDDOC_SOURCE_PATH := $(LOCAL_PATH)/src \
$(LOCAL_PATH)/android \
$(LOCAL_PATH)/../../frameworks/base/core/java/org/apache
[/CODE]

And exchanged it with this:

[CODE]
# WJH LOCAL_JAVA_LIBRARIES := $(apache_http_java_libs)
LOCAL_JAVA_LIBRARIES := $(apache_http_java_libs) okhttp bouncycastle framework
LOCAL_MODULE_CLASS := JAVA_LIBRARIES
LOCAL_DROIDDOC_SOURCE_PATH := $(LOCAL_PATH)/src \
$(LOCAL_PATH)/android \
$(LOCAL_PATH)/../../frameworks/base/core/java/org/apache
[/CODE]

And the problem went away! So, I thought I’d share in case any of my readers had a similar issue.

Linux – keep it simple.

The Super Dimensional Fortress

A title like that suggests something between a B17 bomber (the “flying fortress”) and Superman’s hideout (” fortress of solitude “). Well this isn’t either, but it is pretty cool none the less. In talking about sdf.org, a group of 8+ enterprise servers running Unix that collectively make a super computing center that is freely available to the public for use.

There are some paid perks as well, but any user can sign up for a free account and get an ssh login to a private online account, complete with storage space, an email address, your own website URL (you have to create the website yourself, but they host it for you) and access to online games, old school “bboard” bulletin board coms, irc, and more!

With very reasonable one time or annual rates, you can also get DNS, server hosting, mailbox hosting, and other cool goodies. They also service dial up internet for a really reasonable rate (I think it is around $10/month). Certainly worth taking a look if you are at all geeky.

They boast around 40000 active users, so it looks like there are plenty of folks to chat or online game with. It is focused on sharing knowledge and generally helping educate people about technical things, as well as provide a means of access to services that might not be available elsewhere based on a users remote location. Most everything is designed around the terminal, since you log in via ssh, but paid memberships can also use some x11 services, which is pretty neat.

Their mission statement and a brief summary:

[01] WHAT IS SDF?  (QUICK SUMMARY)

Welcome to the only all 64bit public access supercomputing center!

The Super Dimension Fortress is a networked community of free software
authors, teachers, students, researchers, hobbyists, enthusiasts and
the blind. It is operated as a federally recognised non-profit 501(c)7
and is supported by its members.

Our mission is to provide remotely accessible computing facilities for
the advancement of public education, cultural enrichment, scientific
research and recreation. Members can interact electronically with each
other regardless of their location using passive or interactive forums.
Further purposes include the recreational exchange of information
concerning the Liberal and Fine Arts.

Members have access to games, email, usenet, chat, bboard, gopherspace,
webspace, programming utilities, archivers, browsers, and more. The SDF
community is made up of caring, highly skilled people who operate behind
the scenes and in the underground to maintain a non-commercial INTERNET.

While we did initially start out on a single computer in 1987, the
SDF is now a network of 8 64bit enterprise class servers running
NetBSD realising a combined processing power of over 21.1 GFLOPS!

Our mass storage configuration is comprised of 60 spindles of mostly
36.4gb and a few 9.1gb SCA LVD SCSI drives using DIGITAL Storage Works
hotswap disk arrays. We have roughly 2 terabytes of storage online.

We are networked via two sprintlink T1s and a T1 to savvis. We do BGP
peering and try out best to load balance between the links via a CISCO
7xxx router/switch. We are using a 'swamp' class C 192.94.73 which has
basically been assigned to our site admin along with his class C back
when you could request one from the INTERNIC without much fuss.

The userbase is comprised of two major user groups: USERS and ARPA

'user' accounts are free and offer many features.
'arpa' accounts are permanent members and can vote on SDF features.

Supplemental ARPA privilidges include:

MetaARPA ('trusted' member privs (cron, tcp port forwarding))
TWEAK (tweakable and additional disk quota)
VPM (Virtual POP3 mailboxes)
DNS (Domain Name Service)
DBA (MySQL database access)
VHOST (Virtual Web hosting - includes VPM, DNS and DBA)
SERVER (Server process (mud, nameserver, et cetera))
MDNS (Dynamic DNS)
MLIST (Mailing List service)
DIALUP (over 10,000 numbers in the USA + Canada)

Sponsorship information can be found on our website or in the FAQ.

Bottom line: a super geek club that is super fun, even for those who are not super technically savvy. However, an above average computer skilset is required to make use of this system, one should at a minimum know how to use ssh. So head over to sdf.org and check it out!

Linux – keep it simple.

Countdown or Runnable and Handler, what’s the difference?

Today in class, we learned about different types of timers. Specifically, we learned the difference between a countdown timer, and a runnable and handler. Here’s the app that I put together based on the class:

http://www.mediafire.com/file/0xgqkkbqjaztjmw/thefinalcountdown.apk

It’s not very exciting, hense no screenshot. It has three different toast messages going on at the same time. The first is a toast every seven seconds to tell you it has been seven seconds. The second is a toast every ten seconds telling you how much time is left on the countdown timer, and the third tells you that the countdown is complete.

Here is the Handler and runnable:

[CODE]

// Up first, the Handler and runnable!

// Create the handler, give it a name.
final Handler firstHandler = new Handler();

// Now create a runnable, give it a name.
Runnable firstRun = new Runnable() {

// Now, have that runnable override and run some code.
@Override
public void run() {

// In this case, make a toast.
Toast myToast = Toast.makeText(getApplicationContext(), “It’s been 7 seconds.”, Toast.LENGTH_SHORT);
myToast.setGravity(Gravity.CENTER, 0, 0);
myToast.show();

// And call itself again in 7 seconds….
firstHandler.postDelayed(this, 7000);

}

};

// Be sure to initiate the handler the first time, or nothing will happen.
// You could just use firstHandler.post(firstRun); but I wanted to wait seven seconds first.
firstHandler.postDelayed(firstRun, 7000);
[/CODE]

And here is the countdown timer:

[CODE]

// Up next, the countdown timer! Give it a lenght and an amount to count down in milliseconds.
new CountDownTimer(121000, 10000) {

// Implement code to happen every tick of the countdown.
public void onTick (long myTimer) {

// In this case a toast.
Toast.makeText(
getApplicationContext(), “Ten seconds passed, ” + String.valueOf(myTimer / 1000) + ” seconds left!”, Toast.LENGTH_SHORT).show();

}

// Implement code to happen when it is done counting down.
public void onFinish() {

// Again, I used a toast.
Toast.makeText(getApplicationContext(), “Countdown is complete!”, Toast.LENGTH_SHORT).show();

}

// Tell the countdown timer to start!
}.start();

}
[/CODE]

So, what’s the difference? Well, from what Rob was saying, the key difference is that the Countdown timer and Handler/Runnable can do the exact same thing. However, the Countdown timer has a way of destroying itself when it is done.

At first I thought, “oh, the countdown timer will stop eventually, and the handler/runnable will not”. However, that is an error, because we could make the handler/runnable only display x number of times, by using a variable and minus 1 from it every time.
Like this:

[CODE]
…..

public int a = 10;

…..

// Create the handler, give it a name.
final Handler firstHandler = new Handler();

// Now create a runnable, give it a name.
Runnable firstRun = new Runnable() {

// Now, have that runnable override and run some code.
@Override
public void run() {

// In this case, make a toast.
Toast myToast = Toast.makeText(getApplicationContext(), “It’s been 7 seconds.”, Toast.LENGTH_SHORT);
myToast.setGravity(Gravity.CENTER, 0, 0);
myToast.show();

a = a-1;

if (a >= 0) {

// And call itself again in 7 seconds….
firstHandler.postDelayed(this, 7000);

} else {
// do nothing, or a toast that says “I’m done.”
}

}

};

// Be sure to initiate the handler the first time, or nothing will happen.
// You could just use firstHandler.post(firstRun); but I wanted to wait seven seconds first.
firstHandler.postDelayed(firstRun, 7000);
[/CODE]

Once it reaches 0, it could use an if/then statement to not call itself to run again. So, the two can litterally function the same, it is just a matter of being “left over” after you are done with it. Interesting.

So, the pros to using a handler/runnable is that you can call it from other functions, and it can run on indefinately.
And, a pro for using the countdown timer is that you can easily get the remaining time for display or use as a variable.

Perhaps I will learn new differences that may make one more prominent than the other. Only time will tell. Okay, bad pun, bad pun….

Linux – keep it simple.

 

AOKP 7.1.1 for the Galaxy Note Edge!

To God be the glory, my AOKP NOUGAT project finally works!

My fellow T-Mobile-ians, (N915T) you have been left out of AOSP development long enough! By God’s grace I was able to use mickey387’s great tbltexx work, and completely adapt it to our tbltetmo after extracting all of the needed firmware from our 6.0.1 stock roms! No data zips are required here! It is all built in!

I also have made an international version (N915G/F/FY) as well!
This is not a dirty unicorn. This is the original unicorn, the AOKP. Now made out of Nougat! That’s right, all of the AOKP stuff you love, plus LineageOS, plus a built in side bar, and more! All wrapped up into one! With tons of settings from status bar tweaks to button remaps, it’s all here and ready to rumble!

**** This is an UNOFFICIAL ROM. Install at your own risk! ****

Features and Screenshots!

– Advanced Reboot
– Omni-Switcher
– Kernel Adiutor

+ Rom Control:

+ App Launchers
– App Circle Bar
– App Side Bar
– Gesture Anywhere

+ General
– cLock settings
– Recents settings
– Wakelock Blocker

+ Hardware Keys
– Backlight control
– Power button options
– Launch vibration control
– Home button controls
– Recents button controls
– Long press options, double tap options
– Kill app back button option
– Volume buttons wake
– Volume button playback controls
– Keyboard cursor controls
– Volume button reorientation
– IME features

+ Lockscreen
– Media Cover art
– Display music visualizer
– Show weather
– Blur background
– Fingerprint auth vibration
– Double tap to sleep (DT2S)
– Disable quick settings
– Show lockscreen clock and date
– Lockscreen notification count

+ Notification Drawer
– Brightness slider
– Brightness icon
– Rows in portrait and landscape modes
– Columns
– Tile Animations
– Advanced data tile
– Smart pulldown
– Quick pulldown

+ Power Menu
– Animation choices
– Screenshots
– Screenrecord
– Airplane mode
– Sound Panel

+ Sound
– Various sound settings
– Volumn step control

+ Status Bar tweaks
– Network traffic
– Clock style
– Double tap to sleep (DT2S)
– Superuser indicator
– Icon controls
– AOKP logo

+ User interface
– Toast controls
– AOKP animations
– Transparency controls

AND MORE!!!

Background image:
https://qlfiles.net/2017/01/07/upload-fractal-images/
The background images that I used in this ROM came from the Quiet Learner. You should check out his mathematical artwork, including 3D mandelbox images!

Ready to download? Check it out under my menu –> Homemade Roms –> Galaxy Note Edge!

Linux – keep it simple.

TBLTETMO data fix zips!

Praise God! The TBLTETMO data fix finally works!

What is this for?
-These data fix zips allow you to use a TBLTEXX rom on your phone (provided that you can flash it, see “flashing tbltexx roms” for details on that). If you edit a TBLTEXX rom and flash it to your phone, you will not be able to use the cellular, but now you can with these data fix zips!

THIS IS FOR THE 6.0.1 BOOTLOADER ONLY! THIS ONLY WORKS ON ROMS BUILT FOR THE TBLTEXX ON THE 6.0.1 BOOTLOADER! PLEASE USE WITH CAUTION!

Flashing TBLTEXX roms:
You have two choices, either flash a TBLTEXX recovery, so you can flash TBLTEXX roms, or you can use a TBLTETMO recovery and follow the steps below.
Steps:
1. Download the TBLTEXX rom that was built using the 6.0.1 bootloader.
2. Unzip the rom.
3. Open ./META-INF/com/google/android/updater-script in gedit or notepad++.
4. Delete the first line – should say something like

[CODE]assert(getprop(“ro.product.device”) == “tblte” || getprop(“ro.build.product”) == “tblte” || getprop(“ro.product.device”) == “tbltexx” || getprop(“ro.build.product”) == “tbltexx” || getprop(“ro.product.device”) == “tbltedt” || getprop(“ro.build.product”) == “tbltedt” || abort(“E3004: This package is for device: tblte,tbltexx,tbltedt; this device is ” + getprop(“ro.product.device”) + “.”););[/CODE]
5. Save the file.
6. zip the contents back up.
7. Flash!

Thanks!
Mickey387 – For continued development for the TBLTEXX!
louforgiveno – For making the 5.1.1 bootloader data zips for the trlte, which inspired this set of datazips. (Same principle, different files.)

Known working TBLTEXX roms:

[ROM][7.1.1] AOKP Nougat with built in sidebar launcher! [tbltexx]
This rom is available in the T-Mobile thread also for direct use on the T-Mobile phones!
https://forum.xda-developers.com/note-edge/development/rom-aokp-nougat-built-sidebar-launcher-t3558296
Instructions: After downloading this, you do not need to edit the zip, it is ready for flashing, flash rom, gapps. Reboot, let it settle, then, go back into recovery and flash datazip #1. Reboot. Now you will see your cell phone signal as empty, select your apn, and set your phone to 3g mode. Then, after you get the H+ by your cell signal, you can switch back to LTE.

[ROM][OFFICIAL]NOUGAT Resurrection remix 5.8.0 (7.1.1)
https://forum.xda-developers.com/note-edge/development/rom-nougat-resurrection-remix-5-8-0-7-1-t3509295
Instructions: After making it flashable, flash rom, gapps. Reboot, let it settle, then, go back into recovery and flash datazip #1. Reboot. Now you will see your cell phone signal as empty, select your apn, and set your phone to 3g mode. Then, after you get the H+ by your cell signal, you can switch back to LTE.

[rom][6.0.1] aokp mm [n915t/n915f/n915fy/n915g]
https://forum.xda-developers.com/note-edge/development/rom-aokp-mm-t3484354
Instructions: After downloading the 6.0.1 bootloader version, you do not need to edit the zip, it is ready for flashing. Flash the rom, the gapps, and reboot. After it boots up the first time, go back to recovery and flash data zip #1. You should be good to go! If you have trouble, choose your apn, cycle between 3g and lte!

finnigen2 found that this also works with Resurrection remix 5.8.1 (7.1.1) with the data fix with Mickey’s TWRP 3.0.3.1_915F.

unimatrix725 found that this also works with TekX EPE2 [6.0.1] on a SM-N915R4 (U.S. Cellular).

JeremySS found that if you upgrade from TBLTEXX RR 5.8.0 to 5.8.1, you can flash data zip 2 to fix your issues.

The data zips.

Data Zip #1:
http://www.mediafire.com/file/12bi5tf16dx2jiy/601_915T_datazip1_20170127.zip

Data Zip #2:
http://www.mediafire.com/file/ct843vgvcco6v8k/601_915T_datazip2_20170127.zip

You can also check it out on XDA: https://forum.xda-developers.com/note-edge/tmobile-note-edge-android-development/ril-data-fixes-6-0-1-bootloader-t3546110

Linux – keep it simple.