Getting fired up with Firebase Database

As you might’ve noticed, in my Open Event Android Project, we are asking the user to enter his/her details and then using these details at the backend for generating the app according to his/her needs.

One thing to wonder is how did we transmit the details from webpage to the server.

Well, this is where Firebase comes to the rescue one more time!

If you’ve read my previous post on Firebase Storage, you might have started to appreciate what an awesometastic service Firebase is.

So without any further adieu, lets get started with this.

Step 1 :

Add your project to Firebase from the console.

 newProj
Click on the Blue button

Step 2 :

Add Firebase to your webapp

Open the project, you’ve just created and click on the bright red button that says, “ Add Firebase to your web app”

 addFirebase

Copy the contents from here and paste it after your HTML code.

Step 3 :

Next up, navigate to the Database section in your console and move to the Rules tab.

 screenshot-area-2016-07-18-204133.png

For now, let us edit the rules to allow anyone to read and write to the database.

 screenshot-area-2016-07-18-204437

Almost all set up now.

Step 4 :

Modify the HTML to allow entering data by the user

This looks something like this :

Now let us setup our javascript to extract this data and store this in Firebase Database.

We are almost finished with uploading the data to the database.

Enter data inside the fields and press submit.

If everything went well, you will be able to see the newly entered data inside your database.

screenshot-area-2016-07-18-205651.png

Now on to retrieving this data on the server.

Our backend runs on a python script, so we have a library known as python-firebase which helps us easily fetch the data stored in the Firebase database.

The code for it goes like this

The data will be returned in JSON format, so you can manipulate and store it as you wish.

Well, that’s it!

You now know how to store and retrieve data to and from Firebase.
It makes the work a lot simpler as there is no Database schema or tables that need to be defined, firebase handles this on its own.

I hope that you found this tutorial helpful, and if you have any doubts regarding this feel free to comment down below, I would love to help you out.

Cheers.

Advertisements
Getting fired up with Firebase Database

Uploading json assets and icons to your app via the app generator

If you have tried out our app generator webpage, you should’ve noticed an option that allows you to upload a zip file which will contain the json for the event.

Why do we need this?

Well, this is needed because not every event organizer can maintain a server and API endpoints which contain the details for their event, so they can simply generate a json for the event by exporting it through the options provided to them on Google Spreadsheets and then they can upload them on the server, so that these files can be packaged in the android and web apps.

Implementation :

The implementation is pretty straightforward and consists of 3 parts :

  1. Making changes to the html file to allow user to upload the zip
<tr>
  <td valign="top">
    <label for="sessions">Zip containing .json files</label>
  </td>
  <td valign="top">
    <input accept=".zip" type="file" id="uploadZip" name="sessions">
  </td>
</tr>

2. Retrieve this file in the javascript and then make an AJAX call to the server

var file_data = $('#uploadZip').prop('files')[0];
 var form_data = new FormData();                 
 form_data.append('file', file_data);
 $.ajax({
            
                  url: '/upload.php', // point to server-side PHP script
                  cache: false,
                  contentType: false,
                  processData: false,
                  data: form_data,                         
                  type: 'post',
                  success: function(php_script_response){
                    // do something
                  }
                });

So here, the form_data contains the details about the file to be uploaded.

In the AJAX call, upload.php takes reads form_data variable and then initiates the upload to the server.

3. Setup a PHP script on the server to respond to the above AJAX call

<?php
    if ( 0 < $_FILES['file']['error'] ) {
        echo 'Error: ' . $_FILES['file']['error'] . '<br>';
    }
    else {
        move_uploaded_file($_FILES['file']['tmp_name'], "/var/www/html/uploads/upload.zip"); 
    }
?>

Here in the PHP script, the file is read and uploaded to a temporary directory in the server.

We then manually copy it to a location and name of our choice.

In case there are multiple users accessing the website and uploading their assets at the same time, we need to pass a timestamp variable to the AJAX call to and later on use it while renaming the uploaded file.

This is to ensure that the file uploaded by one user is not overwritten by another user.

How do we use this data during app compilation

The uploaded zip is then uncompressed and its contents are moved to the assets folder of the android app’s directory.

zip_ref = zipfile.ZipFile(path_to_zip_file, 'r')
zip_ref.extractall(directory)
zip_ref.close()
#TODO: Change path here
for f in os.listdir(directory+ "/zip"):
	if f.endswith('.json'):
		copyfile(f, directoy + "open-event-android/android/app/src/main/assets/"+f)
	elif f.endswith('.png'):
		copyfile(f, directory + "open-event-android/android/app/src/main/res/drawable"+f)
replace(directory+"/open-event-android/android/app/src/main/res/values/strings.xml", 'mipmap/ic_launcher', 'drawable/' + f)

Here replace is a function that searches in the source file for the phrase supplied as it’s argument and changes it with the new phrase.

Now when the app is compiled and ran on a user’s device, it will first search for a json file in the assets directory and if it exists, use that for fetching the data instead of making a network call. For this I have used Gson to first parse the offline files otherwise retrofit makes request to the api and fetches the data from there.

But if there is no json in the assets folder, a normal network call using retrofit will be made and the data will be fetched from the API defined by the user.

Uploading json assets and icons to your app via the app generator

How to parse json assets with gson

So most of us have json assets in our app which we parse on runtime to get the data and use it accordingly but what I have seen is that most of the people create a JSONObject or JSONArray after reading the json into an inputstream but then handling it becomes difficult since we have to manually extract every entity in each array which makes it bound to a lot of errors. A better approach to using it is making use of gson : an open source library by Google to serialise and deserialise Java object to (and from) Json. It’s pretty easy to use and makes the development process easy. For those of you not still convinced on using gson, I’d like to demonstrate the code we had to write to without using gson and the one using gson as well.

So to start with lets see the json file we’ll be using. It’s the events.json file from the open event project.

{
  "events": [
    {
      "color": "#fdfdfd",
      "email": "dev@fossasia.org",
      "end_time": "2015-07-14T00:00:00",
      "id": 4,
      "latitude": 37.783839,
      "location_name": "Moscone centre",
      "logo": "http://mysecureshell.readthedocs.org/en/latest/_images/logo_redhat.png",
      "longitude": -122.400546,
      "name": "FOSSASIA",
      "slogan": "Fossasia",
      "start_time": "2015-05-28T13:00:00",
      "url": "www.google.com"
    }
  ]
}

As you can see it has an object that has an array of event objects. So what we’ll first do is that we’ll get the whole json as a string by openeing an inputstream and then directing it to a buffer. Then we convert the buffer array to a string object.

String json = null;
try {
    InputStream inputStream = getAssets().open("events.json");
    int size = inputStream.available();
    byte[] buffer = new byte[size];
    inputStream.read(buffer);
    inputStream.close();
    json = new String(buffer, "UTF-8");

} catch (IOException e) {
    e.printStackTrace();
}

Now we have the json as a string which we can now parse it using a combination of JSONObject and JSONArray. First we’ll access data in the outer json object i.e. “events”. That’ll be done by

JSONObject jsonObject = new JSONObject(json);
JSONArray events = jsonObject.getJSONArray("events");

Now that we have the array, we can traverse it to get the objects inside events array

for (int j=0; j < events.length(); j++){
    JSONObject cit = events.getJSONObject(j);
    String color = jsonObject.getString("color");
    String email = jsonObject.getString("email"); 
    String endTime = jsonObject.getString("end_time");
    String id = jsonObject.getString("id");
    String latitude = jsonObject.getString("latitude");
    String locationName = jsonObject.getString("location_name");
    String logo = jsonObject.getString("logo");
    String longitude = jsonObject.getString("longitude");
    String name = jsonObject.getString("name");
    String slogan = jsonObject.getString("slogan");
    String startTime = jsonObject.getString("start_time");
    String url = jsonObject.getString("url");
}

This is how we go about it. Now for the exiting part.

We already have an Event data class which has the constructor, getters and setters etc.

public class Event {

    int id;

    String name;

    String email;

    String color;

    String logo;

    @SerializedName("start_time")
    String start;

    @SerializedName("end_time")
    String end;

    float latitude;

    float longitude;

    @SerializedName("location_name")
    String locationName;

    String url;

    String slogan;

    public Event(int id, String name, String email, String color, String logo, String start,
                 String end, float latitude, float longitude, String locationName, String url, String slogan) {
        this.id = id;
        this.name = name;
        this.email = email;
        this.color = color;
        this.logo = logo;
        this.start = start;
        this.end = end;
        this.latitude = latitude;
        this.longitude = longitude;
        this.locationName = locationName;
        this.url = url;
        this.slogan = slogan;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public String getColor() {
        return color;
    }

    public void setColor(String color) {
        this.color = color;
    }

    public String getUrl() {
        return url;
    }

    public void setUrl(String url) {
        this.url = url;
    }

    public String getSlogan() {
        return slogan;
    }

    public void setSlogan(String slogan) {
        this.slogan = slogan;
    }

    public int getId() {

        return id;

    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getLogo() {
        return logo;
    }

    public void setLogo(String logo) {
        this.logo = logo;
    }

    public String getStart() {
        return start;
    }

    public void setStart(String start) {
        this.start = start;
    }

    public String getEnd() {
        return end;
    }

    public void setEnd(String end) {
        this.end = end;
    }

    public float getLatitude() {
        return latitude;
    }

    public void setLatitude(float latitude) {
        this.latitude = latitude;
    }

    public float getLongitude() {
        return longitude;
    }

    public void setLongitude(float longitude) {
        this.longitude = longitude;
    }

    public String getLocationName() {
        return locationName;
    }

    public void setLocationName(String locationName) {
        this.locationName = locationName;
    }

}

Now here we name the parameters to the same as that in the json we have or we can just add @SerializedName(entity_name). Then we go to the code for actually retrieving the data from the json file using this data class. How we can do that is by first making a class that’ll get the array of events for us.

public class EventResponseList {
    @SerializedName("events")
    public List<Event> event;
}

Now all we do is

EventResponseList eventResponseList = gson.fromJson(json, EventResponseList.class);

We have a list of events that were in the json array.

Voila! That’s it. It’s so easy to get a list of all the events from the JSONArray and since the library is available for gradle, it’s even better. You can just add

compile 'com.google.code.gson:gson:2.7'

to your build.gradle dependencies and you’re good to go. Cheers!

How to parse json assets with gson

Push your apk to your GitHub repository from Travis

In this post I’ll guide you on how to directly upload the compiled .apk from travis to your GitHub repository.

Why do we need this?

Well, assume that you need to provide an app to your testers after each commit on the repository, so instead of manually copying and emailing them the app, we can setup travis to upload the file to our repository where the testers can fetch it from.

So, lets get to it!

Step 1 :

Link Travis to your GitHub Account.

Open up https://travis-ci.org.

Click on the green button in the top right corner that says “Sign in with GitHub”

screenshot-area-2016-07-15-205733.png<

Step 2 :

Add your existing repository to Travis

Click the “+” button next to your Travis Dashboard located on the left.

screenshot-area-2016-07-15-210630.png<

Choose the project that you want to setup Travis from the next page

screenshot-area-2016-07-15-210916.png
Toggle the switch for the project that you want to integrate

Click the cog here and add an Environment Variable named GITHUB_API_KEY.
Proceed by adding your Personal Authentication Token there.
Read up here on how to get the Token.

 screenshot-area-2016-07-15-213931.png<

Great, we are pretty much done here.

Let us move to the project repository that we just integrated and create a new file in the root of repository by clicking on the “Create new file” on the repo’s page.

Name it .travis.yml and add the following commands over there

language: android 
jdk:
  - oraclejdk8
android:
  components:
    - tools
    - build-tools-24.0.0
    - android-24
    - extra-android-support
    - extra-google-google_play_services
    - extra-android-m2repository
    - extra-google-m2repository
    - addon-google_apis-google-24
 before_install:
 - chmod +x gradlew
 - export JAVA8_HOME=/usr/lib/jvm/java-8-oracle
 - export JAVA_HOME=$JAVA8_HOME
 after_success:
 - chmod +x ./upload-gh-pages.sh
 - ./upload-apk.sh
 script:
 - ./gradlew build

Next, create a bash file in the root of your repository using the same method and name it upload-apk.sh

  #create a new directory that will contain out generated apk
  mkdir $HOME/buildApk/ 
  #copy generated apk from build folder to the folder just created
  cp -R app/build/outputs/apk/app-debug.apk $HOME/android/
  #go to home and setup git
  cd $HOME
  git config --global user.email "useremail@domain.com"
  git config --global user.name "Your Name" 
  #clone the repository in the buildApk folder
  git clone --quiet --branch=master  https://user-name:$GITHUB_API_KEY@github.com/user-name/repo-name  master > /dev/null
  #go into directory and copy data we're interested
  cd master  cp -Rf $HOME/android/* .
  #add, commit and push files
  git add -f .
  git remote rm origin
  git remote add origin https://user-name:$GITHUB_API_KEY@github.com/user-name/repo-name.git
  git add -f .
  git commit -m "Travis build $TRAVIS_BUILD_NUMBER pushed"
  git push -fq origin master > /dev/null
  echo -e "Done\n"

Once you have done this, commit and push these files, a Travis build will be initiated in few seconds.
You can see it ongoing in your Dashboard at https://travis-ci.org/.

After the build has completed, you will can see an app-debug.apk in your Repository.

IMPORTANT NOTE :

You might be wondering as to why did I write [skip ci] in the commit message.

Well the reason for that is, Travis starts a new build as soon as it detects a commit made on the master branch of your repository.

So once the apk is uploaded, that will trigger another build in Travis and hence forming an infinite loop.

We can prevent this in 2 ways :

First, simply write [skip ci] somewhere in the commit message and it will cause Travis to ignore the commit.

Or, push the apk to any other branch which is not configured for Travis build.

So well, that’s almost it.

I hope that you found this tutorial helpful, and if you have any doubts regarding this feel free to comment down below, I would love to help you out.

Cheers.

Push your apk to your GitHub repository from Travis

Set up Firebase to upload user files

If you’ve read my previous post on uploading files to server, you might have noticed that it was not an easy task to achieve.

There is way too much boilerplate code for uploading a single file, and it will be much more complex in case we plan to upload multiple files, which I need to do for my project.

So what’s the solution to this?

ENTER FIREBASE!

Yeah, you read it right, Firebase once again to the rescue!

I came to know that firebase allows user to store and access the files easily to the built in storage.

Enough chatter for now, lets get to code!

Step 1 :

Add your project to Firebase from the console.

newProj.PNG

Click on the Blue button

Step 2 :

Add Firebase to your webapp

Open the project, you’ve just created and click on the bright red button that says, “ Add Firebase to your web app”

addFirebase.PNGCopy the contents from here and paste it after your HTML code.

Step 3 :

Open the “Storage” tab from the navigation drawer and navigate to the rules tab over there.
We need to set up specific rules as to who all can upload and read files to the storage bucket.

storageRules.PNG
For testing purposes, I’ve allowed everyone to read and write to my storage, but that shouldn’t be the case for your production app

Step 4 :

Add code for uploading your files.

First create a document selection widget and an upload button in your website’s index.html.

<tr>
<td valign=”top”>
<label for=”icon”>Zip File</label>
</td>
<td valign=”top”>
<input accept=”.zip” type=”file” id=”uploadZip” name=”icon”>
</td>
</tr>

Next, create a button to initiate the upload

<tr>
<td colspan=”5″ style=”text-align:center”>
<button type=”submit”>Upload Zip</button>
</td>
</tr>

Next up, inside the JavaScript, add a submitlistener for the submit button and call preventDefault inside it to prevent the form from doing the default action.

var form = document.querySelector(“form”);
form.addEventListener(“submit”, function(event) {
event.preventDefault();

Next up, get a reference to the upload location from your firebase storage bucket.

var timestamp = Number(new Date());
var storageRef = firebase.storage().ref(timestamp.toString());

Next, get the upload button from its ID and add its contents to a variable named file_data.

var $ = jQuery;
var file_data = $(‘#uploadZip’).prop(‘files’)[0];

Now upload that file to firebase.

storageRef.put(file_data);

If everything went as expected, you’ll be able to see the uploaded files onto your firebase console.

 storage

So, you can really appreciate the awesomeness of Firebase by now.
It has replaced the work done by over 50+ lines of code (spread around AJAX calls, PHP Scripts and JavaScript methods) by a single method call.

I would urge you to go through the documentation for more clarity on this.
https://firebase.google.com/docs/storage/

Well, that was it for now.
Next time, I’ll tell you how to retrieve the files back from the storage and add user’s details to Firebase Database.(Yeah, no need for Tables and SQL anymore!)

Cheers. 😀

Set up Firebase to upload user files

Uploading a file to a server via PHP

Uploading a file to a server via PHP

If you have been following my posts about my GSoC project, you would be knowing that we are making an app generator which will allow users to easily generate an android app for any event that they plan to host.

So, the next thing that we wanted in our app was to allow the users to upload a zip containing the json files (in case they don’t have an API, from where app can fetch data from) and then upload it to the server where we can use these files during the app compilation.

Steps below will tell you , how we achieved it :

Changes to HTML

First thing that we needed to do was add a file upload element to out HTML page that would allow only .zip files to be uploaded.
It was pretty simple one liner code which goes as follows

<tr>
<td valign=”top”>
<label for=”sessions”>Zip containing .json files</label>
</td>
<td valign=”top”>
<input accept=”.zip” type=”file” id=”uploadZip” name=”sessions”>
</td>
</tr>

PHP script to upload file on to the server

Next, we needed a server sided script (I used PHP) which would upload the zip provided by the user on to the server and store it to a unique location for each user.
The code for that was,

<?php
if ( 0 < $_FILES[‘file’][‘error’] ) {
echo ‘Error: ‘ . $_FILES[‘file’][‘error’] . ‘<br>’;
}
else {
move_uploaded_file($_FILES[‘file’][‘tmp_name’],“/var/www/html/uploads/upload.zip”);
}
?>

So what is happening here is basically the input arg. is first checked whether it is null or not null.
If it is null, and error is thrown back to the user, else the file is renamed and uploaded to the uploads folder in the server’s public directory.

Changes to the JavaScript

This was the part that needed most of the changes to be done, we first had to store the file that is to be uploaded in the form data, and then make and AJAX call to the php file located on the server.

var file_data = $(‘#uploadZip’).prop(‘files’)[0];
var form_data = new FormData();
form_data.append(‘file’, file_data);
$.ajax(
{ url: ‘/upload.php’, // point to server-side PHP script
cache: false,
contentType: false,
processData: false,
data: form_data,
type: ‘post’,
success: function(php_script_response){
ajaxCall1(); } //Chain up another AJAX call for further operations
});

So, that’s almost it!
Some server sided changes were also required like allowing the web user to execute the upload.php script and making the uploads directory writable by the web user.

Well, does it work?

Um, yeah it does.
There are a few issues with concurrent users which we are still debugging, but apart from that it works like a charm!

Here you can see a folder created by each user based on his/her timestamp
And here you can see the file that was uploaded y him/her
screenshot-area-2016-07-04-124957
Lastly our webapp (Looks stunning right?)

So, that was all for this week, hope to see you again next time.
Cheers and all the best 🙂

Uploading a file to a server via PHP

Error Handling in Retrofit 2

For the Open Event android app we were using retofit 1.9 with an okhttp stack plus a gson parser but recently retrofit 2.0 was released and it was a major update in the sense that it a lot of things have been changed.

For starters, you don’t have to declare synchronous and asynchronous requests upfront and you can just decide that while executing. The code for that will look something like this. This is how we define our request methods in our api service

import retrofit.Call;
public interface APIService {
   @POST(“/list”)
   Call<Repo> loadRepo();
}

Now if we want to make a synchronous request, we can make it like

Call<Repo> call = service.loadRepo();
Repo repo = call.execute();

and for an asynchronous request, we can call enqueue()

Call<Repo> call = service.loadRepo();
call.enqueue(new Callback<Repo>() {
    @Override
    public void onResponse(Response<Repo> response) {
    // Get result Repo from response.body()    
    }
    @Override
    public void onFailure(Throwable t) {

    }
});

And another thing that changed in the async call throws a throwable on failure, so essentially the RetrofitError class is gone and since we were using that in our app, we had to modify the whole error handling in the app, basically from the grounds up.

So, when we decided to move to retrofit 2 after the stable version was released, we had to change a lot of code and the main part that was affected was the error handling. So, replacing the retrofitError class, I used the throwable directly to retrieve the error type something like this

if (error.getThrowable() instanceof IOException) { 
    errorType = “Timeout”; 
    errorDesc = String.valueOf(error.getThrowable().getCause()); 
} 
else if (error.getThrowable() instanceof IllegalStateException) {                 
    errorType = “ConversionError”; 
    errorDesc = String.valueOf(error.getThrowable().getCause()); 
} else { 
    errorType = “Other Error”; 
    errorDesc = String.valueOf(error.getThrowable().getLocalizedMessage()); 
}

This was ofcourse for all failure events. And to handle all response events I compared the HTTP status codes and displayed the errors :

Integer statusCode = response.getStatusCode(); 
if (statusCode.equals(404)) { 
    // Show Errors in a dialog
    showErrorDialog(“HTTP Error”, statusCode + “Api Not Found”); 
}

This is how we can compare other HTTP errors in retrofit and assign the correct status accordingly. I personally think that this is a better implementation than Retrofit 1.9 and the RetrofitError was a bit tedious to work with. It wasn’t very thought of before implementation because it was not easy to tell what kind of error exactly occured. With Response codes, one can see what are the exact error one faces and can gracefully handle these errors.

Error Handling in Retrofit 2