Thursday, October 30, 2014
JSON App Finished!
Today, I finally finished the JSON App! It fully gets all the needed data, and also allows the user to select different languages, using the CheckBox widget. From there, it will now find the data based on which languages are checked. Although some translations just don't work (due to the site's limitations on translations available), most are available, and I allowed the app to translate up to four languages! It would be easy to add more as well.
Toast
Today I worked on adding more to my hello world app. I decided on adding a button that would display text such as "Hello World" and this pop up is referred to as toast. I used the references at developer.android.com and I mainly used this source along with this one.
- A toast is just a widget that can show pop ups to users
- I kept getting errors that were simply fixed by adding some import statements. So I just have to keep in mind that if something is underlined red then there may be a good chance that I am just missing an import statement.
- I also wasn't placing things the variables in the correct place which means that I have to remember to define my variables in the correct place
- Apparently you don't need to add any xml, you can just use a function called setGravity like below where bigger numbers move it further down or right so right now it's in the top left corner
toast.setGravity(Gravity.TOP|Gravity.LEFT, 0, 0);
- If you want a custom pop up image you need to make your own xml so I guess this would allow you to adjust size or color, etc
So you can see the little message in the corner, it's currently pretty small and only shows up for a short period of time and you can see the majority of the code below. I'll explain it real quick although I could be wrong... so first the code finds the button which I just gave the id "button". Then there is a function to do something when the button is clicked. After that I specified the variables and you can probably guess what each does, like "LENGTH_SHORT" makes the pop up come up for a short time. Then a new Toast called "toast" is made where the text is made and then shown. I don't really get what Context does so I'll have to read up on that.final Button button = (Button) findViewById(R.id.button);button.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
Context context = getApplicationContext();
CharSequence text = "Hello toast!";
int duration = Toast.LENGTH_SHORT;
Toast toast = Toast.makeText(context, text, duration);
toast.show();
toast.setGravity(Gravity.TOP|Gravity.LEFT, 0, 0);
Wednesday, October 29, 2014
Working with JSON
Today I finally got the JSON code working! It does successfully translate most words into most of the languages, with some times it working with all four languages. The lack of fully translating properly, I've found, is ultimately due to their database not having all the necessary information.
The code I've used to get the JSON translated text is the following:
translation1 = "English: " + readJsonFromUrl("https://glosbe.com/gapi/translate?from=eng&dest=eng&format=json&phrase=" + phrase + "&pretty=true").getJSONArray("tuc").getJSONObject(0).getJSONObject("phrase").get("text");
translation2 = "Spanish: " + readJsonFromUrl("https://glosbe.com/gapi/translate?from=eng&dest=spa&format=json&phrase=" + phrase + "&pretty=true").getJSONArray("tuc").getJSONObject(0).getJSONObject("phrase").get("text");
translation3 = "French: " + readJsonFromUrl("https://glosbe.com/gapi/translate?from=eng&dest=fra&format=json&phrase=" + phrase + "&pretty=true").getJSONArray("tuc").getJSONObject(0).getJSONObject("phrase").get("text");
translation4 = "German: " + readJsonFromUrl("https://glosbe.com/gapi/translate?from=eng&dest=deu&format=json&phrase=" + phrase + "&pretty=true").getJSONArray("tuc").getJSONObject(0).getJSONObject("phrase").get("text");
It was actually much more complicated than it seemed. I had to first read the JSON, from a method I created (named readJsonFromUrl), ultimately from the help of this StackOverflow post:
public static JSONObject readJsonFromUrl(String url) throws Exception {
InputStream inputStream = new URL(url).openStream();
try {
BufferedReader rd = new BufferedReader(new InputStreamReader(inputStream, Charset.forName("UTF-8")));
String jsonText = read(rd);
JSONObject json = new JSONObject(jsonText);
return json;
}
finally {
inputStream.close();
}
}
From there, it gets an array known as "tuc", which, from glosbe, is the main array that stores the majority of the data. From there it's simply finding where the value was, I determined it to be the 1st object in tuc (index 0), then the object known as "phrase", and an inside object known as "text". This contained the translated word, which I used to add into a TextView and display to the user!
The code I've used to get the JSON translated text is the following:
translation1 = "English: " + readJsonFromUrl("https://glosbe.com/gapi/translate?from=eng&dest=eng&format=json&phrase=" + phrase + "&pretty=true").getJSONArray("tuc").getJSONObject(0).getJSONObject("phrase").get("text");
translation2 = "Spanish: " + readJsonFromUrl("https://glosbe.com/gapi/translate?from=eng&dest=spa&format=json&phrase=" + phrase + "&pretty=true").getJSONArray("tuc").getJSONObject(0).getJSONObject("phrase").get("text");
translation3 = "French: " + readJsonFromUrl("https://glosbe.com/gapi/translate?from=eng&dest=fra&format=json&phrase=" + phrase + "&pretty=true").getJSONArray("tuc").getJSONObject(0).getJSONObject("phrase").get("text");
translation4 = "German: " + readJsonFromUrl("https://glosbe.com/gapi/translate?from=eng&dest=deu&format=json&phrase=" + phrase + "&pretty=true").getJSONArray("tuc").getJSONObject(0).getJSONObject("phrase").get("text");
It was actually much more complicated than it seemed. I had to first read the JSON, from a method I created (named readJsonFromUrl), ultimately from the help of this StackOverflow post:
public static JSONObject readJsonFromUrl(String url) throws Exception {
InputStream inputStream = new URL(url).openStream();
try {
BufferedReader rd = new BufferedReader(new InputStreamReader(inputStream, Charset.forName("UTF-8")));
String jsonText = read(rd);
JSONObject json = new JSONObject(jsonText);
return json;
}
finally {
inputStream.close();
}
}
From there, it gets an array known as "tuc", which, from glosbe, is the main array that stores the majority of the data. From there it's simply finding where the value was, I determined it to be the 1st object in tuc (index 0), then the object known as "phrase", and an inside object known as "text". This contained the translated word, which I used to add into a TextView and display to the user!
Tuesday, October 28, 2014
Working with JSON!
It turned out that my entire issue yesterday (Android warning about "is INTERNET permission allowed?") was just that the page wasn't returning the data I needed. It turns out that I was using incorrect language codes, and the page didn't exist. It also turns out that it was returning a JSON array, which I can now access using the line:
[CODE]translation1 = "English: " + readJsonFromUrl("https://glosbe.com/gapi/translate?from=eng&dest=eng&format=json&phrase=" + phrase + "&pretty=true").getJSONArray("tuc").get(0).toString();[/CODE]
This line will return the array that contains the phrase. I'm still working on exactly finding the translated phrase, but from here, it shouldn't be too hard to do!
[CODE]translation1 = "English: " + readJsonFromUrl("https://glosbe.com/gapi/translate?from=eng&dest=eng&format=json&phrase=" + phrase + "&pretty=true").getJSONArray("tuc").get(0).toString();[/CODE]
This line will return the array that contains the phrase. I'm still working on exactly finding the translated phrase, but from here, it shouldn't be too hard to do!
Monday, October 27, 2014
Experimenting with the GPS App
Today I installed the GPS Application you mentioned, and fooled around a bit with its functions. I noticed a few things.
- Not all functions work on all devices. This was expected, as my Nexus 7 doesn't feature all the components of a phone (it's a WiFi version, not a 4G, so it isn't constantly accessing towers, etc.) This results in it being unable to connect to certain GPS servers, and therefore doesn't give full GPS access.
- Some functions work great. The accelerometer provides information about current speed the device is traveling, as well is pitch, yaw, roll, acceleration, etc. This helps provide information on possibly where the device is being used (in a car, etc.)
- The SAT finder works and it's pretty interesting. You can use the camera and it'll show dots of nearby satellites, changing their locations relative to where you're looking at with your camera. I'm not quite sure how they do this, but it's definitely interesting.
- From these observations, I'm able to make a conclusion that although I will make a similar app, mine will have to have some changes. I'll have to work on if and else statements (as well as try/catch statements) often, knowing that not all devices will have the same components and that I will have to try all methods to be able to get locations on all devices. I'll also have to use the LOCATION permissions on Android to keep the app fully supported. As for grabbing web data, I'll be using JSON, with the permission to use data on Android, as most people using the app will not be on WiFi.
Friday, October 24, 2014
Hello World
Eclipse seems to be working for the most part and I even managed to successfully run an app on the tablet as seen in the picture below which just says "Hello World".
It's not that interesting but I later tried to run the example they had to depict services. It was supposed to just have two buttons where once pressed it would say "Service Running" and a button to stop it. There were no errors in my code but there were warnings and I'm sure the code they provided had no errors so I don't know what the problem was. I'll try it again with a new project but I don't think I am going to work on it for long because I want to make more progress in the tutorial. Also, Alex suggested that I make my own apps instead of just copying the books code and adding onto the app, like later coding my own buttons to show or delete the "Hello World" text. My brother also suggested that I read the Oracle Java documentation because it apparently had good explanations.
It's not that interesting but I later tried to run the example they had to depict services. It was supposed to just have two buttons where once pressed it would say "Service Running" and a button to stop it. There were no errors in my code but there were warnings and I'm sure the code they provided had no errors so I don't know what the problem was. I'll try it again with a new project but I don't think I am going to work on it for long because I want to make more progress in the tutorial. Also, Alex suggested that I make my own apps instead of just copying the books code and adding onto the app, like later coding my own buttons to show or delete the "Hello World" text. My brother also suggested that I read the Oracle Java documentation because it apparently had good explanations.
Thursday, October 23, 2014
Slight Fix!
I've slightly got the server to stop responding. I did this by putting the accept client code above the command handling code (see GitHub -> AndroidRPGServer -> Main.java). So far the server is receiving up to the message from the client, but freezes and isn't handling commands. Although it's still not working great, it's a step towards a big fix, and I believe that it's likely now a bug on the server-end, rather than the client-end, where I was working on before.
Wednesday, October 22, 2014
Still more bugs...
I'm still working on client-server connection and client freezing bugs. Basically, the client is now not sending text, and I've yet to find the exact cause of it. I'll continue trying to fix it and write a bug-fix post once I figure out what exactly it is.
Eclipse Set up
Okay so just yesterday I think I finished setting up eclipse. At first when I was getting the android SDK I saw they had a bundle which included eclipse so I got that. I thought it would make the process slightly faster but I must have screwed something up on the way because I later noticed my R.java file wasn't generating(you may remember this is the file that is supposed to auto generate and it's used for linking the xml and java code). Anyway, I tried multiple solutions including the ones seen here and here at stack overflow. One problem I noticed was that I was missing some packages like the Android SDK build tools so I installed that but it didn't fix the problem although it may fixed part of it. Then I focused on the project build target because I had tried everything else so I thought maybe I had a different version of android SDK when the program was targeting a different version although I don't see why it would be doing this. I'm really not sure if I was on the right track or not but I kept getting errors such as saying things like my style is not supported, so I would fix this and then I would get an error saying my theme wasn't supported and I would fix that, etc. At this point I just decided to reinstall eclipse and be careful to try and install only what was needed and currently my R.java file has generated and I hope it stays that way.
Monday, October 20, 2014
More Bugfixes, and More Bugs
Today I mainly focused on bugfixes, especially on the server. At the beginning of the day the server was fully unresponsive and unusable. I fixed that by putting the loop code below the command code (see GitHub -> AndroidRPGServer -> src/Main.java).
Other than that, I've been trying to get verification working still. I've tried different servers, different ports, etc. but haven't gotten it working yet, so I will continue working on that.
My goal this week is to get Account Verification working. Just like last week's goal, I guess it takes a bit more than I thought it would to get it fully working.
Other than that, I've been trying to get verification working still. I've tried different servers, different ports, etc. but haven't gotten it working yet, so I will continue working on that.
My goal this week is to get Account Verification working. Just like last week's goal, I guess it takes a bit more than I thought it would to get it fully working.
Thursday, October 16, 2014
Android Tutorial Chapter 8
This chapter focused on services which I think I briefly talked about before but a service allows for an operation to be running for a long time in the background of an app such as music or retrieving data. There are also two states to a service started and bound.
- Started state
- Started seems pretty self explanatory; it just means that the service has begun so that could maybe mean that an individual just started playing music while looking at their email. Also, the music will continue even if they close their email so services can continue as long as they are not specifically closed.
- Bound state
- I don't really understand this but I'm guessing if a service is bound then the app is retrieving data of some sort so text messaging may have a service to retrieve texts for a person to read. Below is a diagram of the process of started and bound services along with their functions.
onStartCommand():Obviously starts the service and it's very important to put in a method to stop it, either stopSelf() or stopService(). Also requires an interface to be implemented for use by the client.onBind():This method is always required when implementing a service but it's possible to still prevent binding(I'm still a bit confused on this and the other binding methods).
onUnbind():Called when all clients are no longer using a service.
onRebind():Used when clients have reconnected to a service.
onCreate():Called to create the service.onDestroy():Called to destroy the service and any resources related to it.
Server and Client Work
Today I mainly worked on bugfixes. I got somewhere, but not enough to actually write any solving of bugs, since so far whenever one is solved there's another to fill its place. I'll try to fix them by Saturday. The main issue is the client freezing when connecting to the server (which I'm thinking is due to the account creation handler, which verifies and authenticates accounts). I hope that some code fixes in the client and server will fix this, so I'll continue working on it.
Tuesday, October 14, 2014
Setting Up GitHub! [Again]
I finally think I got GitHub working, after a lot of issues. I did some research and figured out that the solution to my problem was to just open up terminal and start from there. I entered the following commands, thanks to some help from a StackOverflow post I found:
AndroidRPGNew
After that, I entered the following commands to remove cache files, etc. from my workspace:
AndroidRPGNew:
AndroidRPGNew
git init
git add .
git commit -m "first commit"
git remote set-url origin https://github.com/fccardiff/AndroidRPGNew.git
git push origin master
AndroidRPGServer
git init
git add .
git commit -m "first commit"
git remote set-url origin https://github.com/fccardiff/AndroidRPGServer.git
git push origin master
After that, I entered the following commands to remove cache files, etc. from my workspace:
AndroidRPGNew:
git pull
git rm -r /libs
git rm -r /out
git rm -r .idea/
git rm -r project-proguard.txt
git rm -r project.properties
git rm -r AndroidRPGNew.iml
git commit -m "removed cache files"
git remote set-url origin https://github.com/fccardiff/AndroidRPGNew.git
git push origin master
AndroidRPGServer:
git pull
git rm -r /libs
git rm -r /out
git rm -r .idea/
git rm -r project-proguard.txt
git rm -r project.properties
git rm -r AndroidRPGServer.iml
git commit -m "removed cache files"
git remote set-url origin https://github.com/fccardiff/AndroidRPGServer.git
git push origin master
Although it's a bit complex, I'm glad I got it working because now all changes are tracked through IntelliJ and updated automatically, which makes it a lot easier.
Android Tutorial Chapter 7
I'm using the regular tutorial; not the advanced one
This chapter focused on the "Android application activity life cycle" which basically means the process of a window being created and then destroyed which can be seen by the diagram below.
So from what it looks like an activity, or window, is first created and started which makes it fully visibly, then it can be paused which makes it partially visible. I'm guessing by partially visible it means that the window may be minimized or greyed out or something like that. Then it can either be resumed which makes it fully visible again or instead stopped which would hide it. I guess a hidden activity would be if you went to the menu of your phone or locked your phone and resumed the app later. The other option would be to destroy the app which would be closing the app all together or shutting off your phone, etc.
This chapter focused on the "Android application activity life cycle" which basically means the process of a window being created and then destroyed which can be seen by the diagram below.
So from what it looks like an activity, or window, is first created and started which makes it fully visibly, then it can be paused which makes it partially visible. I'm guessing by partially visible it means that the window may be minimized or greyed out or something like that. Then it can either be resumed which makes it fully visible again or instead stopped which would hide it. I guess a hidden activity would be if you went to the menu of your phone or locked your phone and resumed the app later. The other option would be to destroy the app which would be closing the app all together or shutting off your phone, etc.
- onCreate(): This is the first callback and called when the activity is first created.
- onStart(): This callback is called when the activity becomes visible to the user.
- onResume(): This is called when the user starts interacting with the application.
- onPause(): The paused activity does not receive user input and cannot execute any code and called when the current activity is being paused and the previous activity is being resumed.
- onStop(): This callback is called when the activity is no longer visible.
- onDestroy(): This callback is called before the activity is destroyed by the system.
- onRestart(): This callback is called when the activity restarts after stopping it.
An Attempt At Authentication [UNTESTED]
Today I made an attempt at authentication. I think I have a good start, however my code so far is untested.
The main bug was this: Android has something called a Context. Although I still can't find out as to why it is used, a context is basically something stored in an Activity or Application that tells the phone what's going on. Contexts are important because you need them to start Intents (which basically redirect you from class to class).
The problem was that I needed to call an Intent from a non-Activity class, and to get a Context easily, the main way would be to have an Activity class. The reason I needed to do this was because my Authentication class was a Runnable, not an Activity (Runnables are mainly used for looping, and I needed this to handle client-server interactions to check usernames).
In the end, I ended with this class, AccountVerify.java, which *should* connect to the server and await a servers' response to check usernames if they exist. I haven't written the server-side code yet. If the username exists, it will give the user a Toast message saying that the account has been created and move them over to the MultiplayerMenu (which has a list of servers they can connect to). If not, it will say the username is not available, and to try a different one. And, last but not least, if it is neither (for some odd reason), it will give them an error message, asking if they are connected to the Internet (this is if a response from the server isn't received).
AccountVerify.java
package com.example.AndroidRPGNew.multiplayer;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.widget.Toast;
import java.io.DataOutputStream;
import java.io.Serializable;
import java.net.Socket;
import java.util.Scanner;
/**
* Created by fccardiff on 10/14/14.
*/
public class AccountVerify extends Activity implements Runnable,Serializable{
private Socket socket;
private String username;
private String password;
protected Context context;
public AccountVerify(Socket s, String user, String pass){
socket = s;
username = user;
password = pass;
}
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
run();
}
public void run(){
try{
final DataOutputStream dataOutputStream = new DataOutputStream(socket.getOutputStream());
final Scanner in = new Scanner(socket.getInputStream());
dataOutputStream.writeByte(80);
dataOutputStream.writeUTF("verify");
dataOutputStream.flush();
dataOutputStream.writeByte(81);
dataOutputStream.writeUTF(username);
dataOutputStream.flush();
dataOutputStream.writeByte(82);
dataOutputStream.writeUTF(password);
dataOutputStream.flush();
if(in.hasNext()){
String canCreate = in.nextLine();
boolean available = Boolean.parseBoolean(canCreate);
if(available == false){
userNotAvailable();
}
else if(available == true){
try{
Toast.makeText(context, "Successfully created user!", Toast.LENGTH_SHORT).show();
Intent startMultiplayer = new Intent(getApplicationContext(), MultiplayerMenu.class);
startActivity(startMultiplayer);
}
catch(Exception e){
e.printStackTrace();
}
}
else{
// TODO Send encountered error, is client connected to internet?
Toast.makeText(context, "Cannot create user! Is client connected to the internet?", Toast.LENGTH_SHORT).show();
}
}
}
catch(Exception e){
e.printStackTrace();
}
}
public void userNotAvailable(){
Toast.makeText(context, "Username not available! Please try a different username!", Toast.LENGTH_SHORT).show();
}
}
The main bug was this: Android has something called a Context. Although I still can't find out as to why it is used, a context is basically something stored in an Activity or Application that tells the phone what's going on. Contexts are important because you need them to start Intents (which basically redirect you from class to class).
The problem was that I needed to call an Intent from a non-Activity class, and to get a Context easily, the main way would be to have an Activity class. The reason I needed to do this was because my Authentication class was a Runnable, not an Activity (Runnables are mainly used for looping, and I needed this to handle client-server interactions to check usernames).
In the end, I ended with this class, AccountVerify.java, which *should* connect to the server and await a servers' response to check usernames if they exist. I haven't written the server-side code yet. If the username exists, it will give the user a Toast message saying that the account has been created and move them over to the MultiplayerMenu (which has a list of servers they can connect to). If not, it will say the username is not available, and to try a different one. And, last but not least, if it is neither (for some odd reason), it will give them an error message, asking if they are connected to the Internet (this is if a response from the server isn't received).
AccountVerify.java
package com.example.AndroidRPGNew.multiplayer;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.widget.Toast;
import java.io.DataOutputStream;
import java.io.Serializable;
import java.net.Socket;
import java.util.Scanner;
/**
* Created by fccardiff on 10/14/14.
*/
public class AccountVerify extends Activity implements Runnable,Serializable{
private Socket socket;
private String username;
private String password;
protected Context context;
public AccountVerify(Socket s, String user, String pass){
socket = s;
username = user;
password = pass;
}
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
run();
}
public void run(){
try{
final DataOutputStream dataOutputStream = new DataOutputStream(socket.getOutputStream());
final Scanner in = new Scanner(socket.getInputStream());
dataOutputStream.writeByte(80);
dataOutputStream.writeUTF("verify");
dataOutputStream.flush();
dataOutputStream.writeByte(81);
dataOutputStream.writeUTF(username);
dataOutputStream.flush();
dataOutputStream.writeByte(82);
dataOutputStream.writeUTF(password);
dataOutputStream.flush();
if(in.hasNext()){
String canCreate = in.nextLine();
boolean available = Boolean.parseBoolean(canCreate);
if(available == false){
userNotAvailable();
}
else if(available == true){
try{
Toast.makeText(context, "Successfully created user!", Toast.LENGTH_SHORT).show();
Intent startMultiplayer = new Intent(getApplicationContext(), MultiplayerMenu.class);
startActivity(startMultiplayer);
}
catch(Exception e){
e.printStackTrace();
}
}
else{
// TODO Send encountered error, is client connected to internet?
Toast.makeText(context, "Cannot create user! Is client connected to the internet?", Toast.LENGTH_SHORT).show();
}
}
}
catch(Exception e){
e.printStackTrace();
}
}
public void userNotAvailable(){
Toast.makeText(context, "Username not available! Please try a different username!", Toast.LENGTH_SHORT).show();
}
}
A link from AccountSetup (which handles the text boxes where the user inputs their username/password) allows connection to the server and verification.
ServerConnect.connect();
final int port = 2525;
final String IP = MultiplayerMenu.getIP();
try {
Log.w("attempting socket connection", "...");
socket = new Socket(IP, port);
Log.w("Server:", "Connected to " + IP + ":" + port);
AccountVerify verify = new AccountVerify(socket, user, pass);
Thread thread = new Thread(verify);
thread.start();
}
catch(Exception e){
Log.w("", "Error connecting to Account Verification Server!");
e.printStackTrace();
}
Once again, I haven't tested this yet and it probably has a lot of bugs in it, but it's definitely a starting attempt at getting the server to verify and authenticate users.
Goals for this week:
1. Finish User Authentication
2. Setup basic server announcement commands (maybe automated restarts?)
3. Add "Connect to IP" box in client, to connect to different IPs than the server list
Goals for this week:
1. Finish User Authentication
2. Setup basic server announcement commands (maybe automated restarts?)
3. Add "Connect to IP" box in client, to connect to different IPs than the server list
Friday, October 10, 2014
More Bug Fixes!
I also fixed some more SQLite bugs! My SQLite functions now get and set data. A perfect example of this is the bug below, which I fixed today. I got errors such as "No such column: " then the username specified (I had a "create" username command, which created permissions for a user). I solved this with the code below.
The bug was in these lines:
connection.prepareStatement("INSERT INTO USERS (UserID, Password) VALUES (" + userID + ", " + password + ");");
connection.prepareStatement("INSERT INTO PERMISSIONS (UserID, PermissionsList) VALUES (" + userID + ", " + "permissionsCreated:true);");
The issue is this: when you store values to SQLite databases, specifically Strings, they need to be surrounded by 's, or single quotes. My code above didn't do this. I fixed it with the lines below.
connection.prepareStatement("INSERT INTO USERS (UserID, Password) VALUES (" + "'" + userID + "'" + ", " + "'" + password + "'" + ");");
connection.prepareStatement("INSERT INTO PERMISSIONS (UserID, PermissionsList) VALUES (" + "'" + userID + "'" + ", " + "'permissionsCreated:true');");
As you can see, the new lines fix this issue. They insert my provided strings, while also adding single quotes around them.
SQLite injection is still vulnerable. That will come with a fix next week.
Overall, I'm proud of what I finished this week. Although it was mainly bugfixes, they were major bugfixes, and my server is now functioning as it should!
The bug was in these lines:
connection.prepareStatement("INSERT INTO USERS (UserID, Password) VALUES (" + userID + ", " + password + ");");
connection.prepareStatement("INSERT INTO PERMISSIONS (UserID, PermissionsList) VALUES (" + userID + ", " + "permissionsCreated:true);");
The issue is this: when you store values to SQLite databases, specifically Strings, they need to be surrounded by 's, or single quotes. My code above didn't do this. I fixed it with the lines below.
connection.prepareStatement("INSERT INTO USERS (UserID, Password) VALUES (" + "'" + userID + "'" + ", " + "'" + password + "'" + ");");
connection.prepareStatement("INSERT INTO PERMISSIONS (UserID, PermissionsList) VALUES (" + "'" + userID + "'" + ", " + "'permissionsCreated:true');");
As you can see, the new lines fix this issue. They insert my provided strings, while also adding single quotes around them.
SQLite injection is still vulnerable. That will come with a fix next week.
Overall, I'm proud of what I finished this week. Although it was mainly bugfixes, they were major bugfixes, and my server is now functioning as it should!
Android Tutorial Chapter 5 + Chapter 6
The book has been pretty helpful so far and I think xml is pretty simple considering it's just tag notation(the layouts can be a bit confusing though) and Finn's code is starting to make more sense.
Chapter 5
Chapter 5
- Intents change the activity so a main menu button could change to a different menu, or activity like a settings menu
- Views are just UI elements like seekbars or buttons
- Resources are elements imported into the project like pictures, text etc
- To specify an xml file you write the name out with R.layout.name because there is a file that connects the xml and java called an R file
- ImageView imageView = (ImageView) findViewById(R.id.myimageview);
imageView.setImageResource(R.drawable.myimage); - Strings.xml just contains all the strings the app uses
- I also made a hello world app which was pretty easy because it was just xml
- This chapter focused on organizing the resource folder which generally looks like this
- MyProject/
src/
MyActivity.java
res/
drawable/
icon.png
layout/
activity_main.xml
info.xml
values/
strings.xml - There are also many other sub directories which are supported which can be seen below along with what they do
- anim/: XML files that define property animations. They are saved in res/anim/ folder and accessed from the R.anim class.
- color/: XML files that define a state list of colors. They are saved in res/color/ and accessed from the R.color class.
- drawable/: Image files like .png, .jpg, .gif or XML files that are compiled into bitmaps, state lists, shapes, animation drawables. They are saved in res/drawable/ and accessed from the R.drawable class.
- layout/: XML files that define a user interface layout. They are saved in res/layout/ and accessed from the R.layout class.
- menu/: XML files that define application menus, such as an Options Menu, Context Menu, or Sub Menu. They are saved in res/menu/ and accessed from the R.menu class.
- raw/: Arbitrary files to save in their raw form. You need to
callResources.openRawResource() with the resource ID, which is R.raw.filename to open such raw files. - values/: XML files that contain simple values, such as strings, integers, and colors. For example, here are some filename conventions for resources you can create in this directory: arrays.xml for resource arrays, and accessed from the R.array class. integers.xml for resource integers, and accessed from the R.integerclass. bools.xml for resource boolean, and accessed from the R.bool class. colors.xml for color values, and accessed from the R.color class. dimens.xml for dimension values, and accessed from the R.dimen class. strings.xml for string values, and accessed from the R.string class. styles.xml for styles, and accessed from the R.style class.
- xml/: Arbitrary XML files that can be read at runtime by calling Resources.getXML(). You
can save various configuration files here which will be used at run time. - Also I mentioned some of this before but there are alternative resources which are resources that are used under certain conditions so I said before in a different post that there are different drawable folders like drawable-hdpi, drawable-xhdpi, etc where different pictures would be used on different devices due to their resolution. The book also stated that another possible alternative resource would be in the layout folder called layout-ar which would be used to change the language of the UI to arabic when needed.
A Bug Fix
This bug took around 4 hours to fix. It wasn't anything too complicated, but I was looking in the wrong class. I just thought it'd be good to paste the incorrect and correct code to explain why exactly it was confusing me.
I was in my SQLConnection class on the server, which handles the creation of databases and user permissions. I was working with a properties file, named "server.properties", which handled basic server functions, such as if the SQLite Database existed, etc, so that it wouldn't recreate the database every single time it started.
This ran into a problem. The server.properties file wasn't loading correctly, and was therefore resetting every single time the server ran. This messed up a ton of other things, the most important being that it would also reset the SQLite Database every single time also because it thought that the server was running for the first time.
The fix was extremely simple. It was in my main class:
The code was right at the top.
java.util.Properties properties = new java.util.Properties();
if(properties == null){
properties.load(new FileInputStream(new File("server.properties")));
}
The problem was pretty basic. Every time the first line was called, it would make a new null Properties. The second line checked if they were null, which they obviously always were. It then reloaded a new file and stored new properties to that file, resulting in rewriting the properties file every single time the server stopped.
It was fixed with this line:
java.util.Properties properties = new java.util.Properties();
if(!new File("server.properties").exists()){
properties.store(new FileOutputStream("server.properties"), "");
}
properties.load(new FileInputStream("server.properties"));
This line instantiates a new Properties like normal, and then loads from the file. If the file doesn't exist, it will create one. This way, if the file is empty, I can create the property file's properties below.
if(properties.getProperty("propertySetup") == null || properties.getProperty("propertySetup").equalsIgnoreCase("false")){
properties.setProperty("propertySetup", "true");
}
Then, it can rewrite new properties. That way, I never have to worry about a blank properties file.
I just posted this to show how easily a single line of code can mess up the functions of an entire program, and it can often take quite a while to fix if it doesn't display an error!
I was in my SQLConnection class on the server, which handles the creation of databases and user permissions. I was working with a properties file, named "server.properties", which handled basic server functions, such as if the SQLite Database existed, etc, so that it wouldn't recreate the database every single time it started.
This ran into a problem. The server.properties file wasn't loading correctly, and was therefore resetting every single time the server ran. This messed up a ton of other things, the most important being that it would also reset the SQLite Database every single time also because it thought that the server was running for the first time.
The fix was extremely simple. It was in my main class:
The code was right at the top.
java.util.Properties properties = new java.util.Properties();
if(properties == null){
properties.load(new FileInputStream(new File("server.properties")));
}
The problem was pretty basic. Every time the first line was called, it would make a new null Properties. The second line checked if they were null, which they obviously always were. It then reloaded a new file and stored new properties to that file, resulting in rewriting the properties file every single time the server stopped.
It was fixed with this line:
java.util.Properties properties = new java.util.Properties();
if(!new File("server.properties").exists()){
properties.store(new FileOutputStream("server.properties"), "");
}
properties.load(new FileInputStream("server.properties"));
This line instantiates a new Properties like normal, and then loads from the file. If the file doesn't exist, it will create one. This way, if the file is empty, I can create the property file's properties below.
if(properties.getProperty("propertySetup") == null || properties.getProperty("propertySetup").equalsIgnoreCase("false")){
properties.setProperty("propertySetup", "true");
}
Then, it can rewrite new properties. That way, I never have to worry about a blank properties file.
I just posted this to show how easily a single line of code can mess up the functions of an entire program, and it can often take quite a while to fix if it doesn't display an error!
Wednesday, October 8, 2014
SQL Work
Today I finally tested my command and SQL code. The commands work, but I'm having some serious trouble with handling the creation of databases and finding variables, etc. so it could be awhile to figure out the bugs. I'm also working on securing the SQL code so that injections aren't possible. So, in short, today was a bugfix day with these improvements:
- Added "create" command (for developer only), allowing you to create user permissions (for testing)
- Added "permissions" command to display user permissions
- Worked on some more SQL checking, getting, and setting code
I'm still working on getting the SQL to load and save properly.
Tuesday, October 7, 2014
Android Tutorial Chapter 4
I decided to use the android tutorial you found and I just skipped
the first 3 chapters which talked about set up. Also, I have gone over
some of this material but I'll just repeat it anyway. This chapter went over the four main components of making an android app which include an activity, a service, broadcast receivers, and content providers.
- An activity is basically a screen of the app so an app for text messaging may have a UI for contacts and a UI for the actually text
- Activities are implemented like this where "MainActivity" is the name
of the class
public class MainActivity extends Activity {}
- A service is when a long process is running in the background such as playing music while running a different app or grabbing data without preventing interaction with the app
- Services are implemented like this where "MyService" is the name of the class
public class MyService extends Service {}
- I'm not actually sure what a broadcast receiver is but from what it looks like it allows apps to be notified if anything was downloaded to the device and allows the app to use it. So I'm guessing that means that whenever I download an app and it asks for permissions that may apply to broadcast receivers because it wants to access the data on my phone.
- Broadcast receivers are implemented the same way with the name after the class and each message is classified as an intent object which I think I will get into more later
public class MyService extends Service { }
- I think content providers are the subclasses that actually supply the data for the broadcast receivers
- Content providers are implemented the same ways and require APIs to enable the transaction of data (I'm guessing they will explain that in more detail later as well)
public class MyContentProvider extends ContentProvider {}
10/7/14
Today I started coding some very confusing things, mainly to do with SQL column creation and user account handling. They are all done via a Switch and DataInputStream, and are handled in the server-client relationship.
- Added more cases to the DataOutputStream
- Added sending password to server (will fix later tomorrow to improve security)
- Created checkDatabase methods that check if users have permissions and are in the users and permissions databases
- Created setupUser methods that will setup users in the users and permissions databases if they do not exist from the checkDatabase method
- Added more code to strengthen the server-client relationship
It's a bit tough to explain what the code actually does, since really it is pretty miniscule, but it has a large impact on how the program functions. Most of the code was added on the server-side end, but code was added client-side to send more information to the server (passwords, etc.). I'm hoping to work on user authentication soon, since this code will make that pretty easy.
Monday, October 6, 2014
Today I mainly helped Aki with setup. However, I also got some things done on my own code-wise!
We also started a User Story, which Aki will post.
Today I did the following:
We also started a User Story, which Aki will post.
Today I did the following:
- Cleaned up some SQL Code, worked on finding User Permissions
- Started working more on the Admin permission, created User Setup method for SQL (Creates a new row when a new user joins for permissions and userID password combination)
- Helped Aki re-setup IntelliJ, Android SDK, JDK, etc.
My goals for the week are:
- Fully get permissions database working
- Work on chat tags
- Work on finishing all SQL getting, setting, and checking code
Friday, October 3, 2014
Image Button Listener
Today I made a listener file which is basically a file with certain conditions that changes something when the conditions are met. So in this case I made a listener file for a image file so that the image is can change under certain circumstances.
For example the back button now has 2 different states
For example the back button now has 2 different states
- A normal state where when nothing is happening the image will stay the same
<item android:drawable="@drawable/back_normal" /> <!-- default -->
- A pressed state for when the button is clicked so you can highlight it(the first line is the condition and the second line is the image it changes to)
<item android:state_pressed="true" android:drawable="@drawable/back_pressed" /> <!-- pressed -->
- A focused state for when the button has a cursor over it but this won't apply to android apps
SQL, Servers, and more!
Today I forgot my laptop, but I wanted to document what I got done yesterday!
- Finished connection to SQLite Database (Using SQLite JDBC Driver, and Java's DriverManager)
- Successfully created SQLite Databases (Called USERS) with 3 columns - UserID VARCHAR(15), Password VARCHAR(15), and Permissions VARCHAR(MAX). The permissions string file has no limit, allowing for a very large number of permissions.
- Permissions is a list of user permissions, and I also started working on a command to add permissions to the user, if the user has the permission to add permissions, or add permissions to a user via console
- Added "admin" command for user - Doesn't do anything yet, but will give a user the "hasAdmin" permission, marking them as a game admin
- Created Java methods for getting and setting information in the database
- Soon to add: Saving userID and Password to database, saving permissions to database, checking userID and Password combinations to allow a user to login to the game
- The server and SQLite database are saved in the same folder, and server preferences are loaded from a java Preferences file (specifically titled server.preferences) and the SQLite database, users.db, is in the same directory.
- Server notifies server admin of creation of databases, database connection, starting, stopping, handles commands, and prints stack traces if necessary, via System.out.println, and taking commands with a Scanner.
- GitHub was also setup this week for AndroidRPGNew and AndroidRPGServer projects. However, the code updated this week hasn't been pushed yet (as I plan to push it at the end of every week, and I don't have access to my laptop right now).
While I got most of this done yesterday, it really took all week. Lots of bugfixes, etc. resulted in a lot of time being used up researching it all, but I'm happy with the result!
Wednesday, October 1, 2014
Image Buttons Continued
Apparently the only reason my image buttons were not rendering was because their file name began with a number so now I know there are some restrictions on the file name. I just changed the file name to a proper name like "back" and it now works. I also added
Finn Edit:
I worked on some very basic bugs today. One was the server was not connecting to SQL, and I have fully fixed that via changing imports in IntelliJ. I also added a "stop" command to the server so I can update it and easily restart it without reconnecting to SSH.
"
android:background="@android:color/transparent"
to the xml because image buttons still have the default background which looks ugly. I might also try adding some different items to the buttons like "pressed" so it highlights when pressed. Finn Edit:
I worked on some very basic bugs today. One was the server was not connecting to SQL, and I have fully fixed that via changing imports in IntelliJ. I also added a "stop" command to the server so I can update it and easily restart it without reconnecting to SSH.
Subscribe to:
Posts (Atom)