Creating a Widget for your Android App

Having a widget for your app, not only helps it to stand out among its alternatives but also provides user information on the go without having to open the app. Keeping this thought in mind, I decided to make a widget for my GSoC project. Let's go through the steps involved. Step 1: Creating a new widget from Android Studio. Open up your project for which you need a widget and navigate to the project’s Java source. Create a new sub-package there named widget. Right click on the newly created sub-package and select the New->Widget option from there. Follow the instructions on the next screen. Most of the fields here are pretty much self explanatory. After doing this and running the app in your device, you will be able to see a widget for your app in the widget picker.   Just kidding, this was the easy part, off to more harder things now! Step 2: Populating the widget with data. Now, there can be 2 broad type of widgets Information Widgets and Collection Widgets. Information widgets are simple widgets that are used to display an information that changes with time, for example Weather Widget or a Clock Widget. Whereas, collection widgets are widgets which display a collection of data, for example the GMail widget is a collection widget. These are relatively complex and harder than the Information Widgets. In this post, we will focus on making a Collection Widget. For Collection widgets, we need two layout files, one for the widget and one for each item in the widget collection. Go ahead and create the two layout files. The wizard automatically generates the widget_layout.xml for you, you just need to edit it up. stock_layout.xml <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <LinearLayout android:layout_width="match_parent" android:id="@+id/widget_toolbar" android:layout_height="?android:attr/actionBarSize" android:background="@color/colorPrimary"> <ImageView android:layout_width="wrap_content" android:layout_height="match_parent" android:layout_gravity="center" android:src="@drawable/stock_up" android:contentDescription="@string/stock_widget" /> <ImageView android:layout_width="wrap_content" android:layout_height="match_parent" android:layout_gravity="center" android:src="@drawable/stock_down" android:contentDescription="@string/stock_widget" /> <TextView android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:layout_marginStart="32dp" android:gravity="center_vertical" android:text="@string/your_stocks" android:textAppearance="@android:style/TextAppearance.DeviceDefault.Widget.ActionBar.Title" android:layout_marginLeft="32dp" /> </LinearLayout> <ListView android:id="@+id/widget_listView" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@color/backGround"></ListView> </LinearLayout> list_item.xml <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="72dp" android:gravity="center_vertical" android:orientation="horizontal" android:paddingLeft="16dp" android:paddingRight="16dp" > <TextView android:id="@+id/stock_symbol" style="@style/StockSymbolTextStyle" android:layout_width="wrap_content" android:layout_height="wrap_content" android:gravity="start|center_vertical" tools:text="List Item" /> </LinearLayout> Next up, having a look at the modified files, we can see that the Widget creation wizard added some stuff into out AndroidManifest.xml and created a new java file. Upon taking a closer look at the manifest, we can see that the widget’s java class has been registered as a <receiver/> Next, opening up the NewAppWidget.java, we will see that it extends AppWidgetProvider and some methods are already overridden for you. Time to edit up this file to reference to the layouts we have just created. import android.annotation.TargetApi; import android.app.PendingIntent; import android.appwidget.AppWidgetManager; import android.appwidget.AppWidgetProvider; import android.content.Context; import android.content.Intent; import android.os.Build; import android.support.annotation.NonNull; import android.widget.RemoteViews; /** * Implementation of App Widget functionality. */ public class StockWidgetProvider extends AppWidgetProvider { private static void updateAppWidget(Context context, AppWidgetManager appWidgetManager, int appWidgetId) { // Construct the RemoteViews object which defines the view of out widget RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.widget_layout); // Instruct the widget manager to update…

Continue ReadingCreating a Widget for your Android App

Unit testing JSON files in assets folder of Android App

So here is the scenario, your android app has a lot of json files in the assets folder that are used to load some data when in first runs. You are writing some unit tests, and want to make sure the integrity of the data in the assets/*.json are preserved. You'd assume, that reading JSON files should not involve using the Android Runtime in any way, and we should be able to read JSON files in local JVM as well. But you're wrong. The JSONObject and JSONArray classes of Android are part of android.jar, and hence JSONObject myJson = new JSONObject(someString); The above code will not work when running unit tests on local JVM. Fortunately, our codebase already using Google's GSoN library to parse JSON, and that works on local JVM too (because GSoN is a core Java library, not specifically an Android library). Now the second problem that comes is that when running unit tests on local JVM we do not have the getResources() or getAssets() functions. So how do we retrieve a file from the assets folder ? So what I found out (after a bit of trial and error and poking around with various dir paths), is that the tests are run from the app folder (app being the Android application module - it is named app by default by Android Studio, though you might have had named it differently) So in the tests file you can define at the beginning public static final String ASSET_BASE_PATH = "../app/src/main/assets/"; And also create the following helper function public String readJsonFile (String filename) throws IOException { BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(ASSET_BASE_PATH + filename))); StringBuilder sb = new StringBuilder(); String line = br.readLine(); while (line != null) { sb.append(line); line = br.readLine(); } return sb.toString(); } Now wherever you need this JSON data you can just do the following Gson gson = new GsonBuilder().create(); events = gson.fromJson(readJsonFile("events.json"), Event.EventList.class); eventDatesList = gson.fromJson(readJsonFile("eventDates.json"), EventDates.EventDatesList.class);

Continue ReadingUnit testing JSON files in assets folder of Android App

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” < Step 2 : Add your existing repository to Travis Click the “+” button next to your Travis Dashboard located on the left. < Choose the project that you want to setup Travis from the next page 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.  < 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 "Donen" 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…

Continue ReadingPush your apk to your GitHub repository from Travis

Using compression middleware in Node/Express

If you're using ExpressJS to host your server, there's a small performance tweak that you can do (works on universally on any kind of server - HTML templates to JSON REST APIs to image servers) - which is to enable GZIP compression. The changed required to do it should be very simple. First install the compression npm package npm install --save compression In you app.js (or wherever you start your express server), modify the code to include the compression middleware like this var express = require('express); var app = express(); var compression = require('compression'); app.use(compression()); // Rest of your app code // app.get (endpoint, callback) // app.listen(port, callback) This should easily reduce page loads time to the order of 15-20%. For example, page load before compression middleware added   And Page load time after compression is added

Continue ReadingUsing compression middleware in Node/Express

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. 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” Copy 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. 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.   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. :D

Continue ReadingSet up Firebase to upload user files

Using TabLayouts in your Android app

So while making a sessions schedule for the open event app, I wanted to separate the sessions on the basis of the days they are scheduled for to improve the visual clarity. So to do this I had various approaches like add a filter to separate by date or add checkboxes to show only checked dates but I though they’d look ugly. Instead the best option was to add tabs in a fragment with a viewpager to scroll within them : It looks appealing, has simple and clean UI, easier to implement with the new design library. So, naturally I opted for using the Tablayout from the design Library. Earlier, when the Support design library was not introduce, it was really a tedious job to add it to our app since we had to extend Listeners to check for tab changes and we had to manually open fragments when a tab was selected or unselected or even when it was reselected. Essentially this meant a lot of errors and memory leaks. In the design library we essentially need to add tablayout and a viewpager to our layout like this : <android.support.design.widget.AppBarLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent"> <android.support.design.widget.TabLayout android:id="@+id/tabLayout" android:layout_width="match_parent" android:layout_height="wrap_content" app:tabGravity="fill" app:tabMode="fixed" app:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar" /> <android.support.v4.view.ViewPager android:id="@+id/viewpager" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@android:color/white" /> </android.support.design.widget.AppBarLayout> Next in our activity/ fragment, we can just inflate this view and create an adapter for the viewpager extending a FragmentPagerAdapter: public class OurAdapter extends FragmentPagerAdapter { private final List<Fragment> mFragmentList = new ArrayList<>(); private final List<String> mFragmentTitleList = new ArrayList<>(); public ScheduleViewPagerAdapter(FragmentManager manager) { super(manager); } @Override public Fragment getItem(int position) { return mFragmentList.get(position); } @Override public int getCount() { return mFragmentList.size(); } public void addFragment(Fragment fragment, String title, int day) { mFragmentList.add(fragment); mFragmentTitleList.add(title); } @Override public CharSequence getPageTitle(int position) { return mFragmentTitleList.get(position); } } Now I had to make dynamic number of tabs, since I wanted the app to customisable on the number of days listed in the json downloaded from the server. So, I made some changes in the traditional code. This is what we do in our activity/fragment’s onCreate/OnCreatView : viewPager = (ViewPager) view.findViewById(R.id.viewpager); for (int i = 0; i < daysofEvent; i++) { adapter.addFragment(new DayScheduleFragment(),title, dayNo); } viewPager.setAdapter(adapter); scheduleTabLayout = (TabLayout) view.findViewById(R.id.tabLayout); scheduleTabLayout.setupWithViewPager(viewPager); This is it. Now we have a basic working tablayout in a viewpager. This also has the capability to change according to the number of days specified in the json we have written. Earlier without the design library, we would have to even add switch cases in the FragmentPagerAdapter like this : public class OurAdapter extends FragmentPagerAdapter { public TabsPagerAdapter(FragmentManager fm) { super(fm); } @Override public Fragment getItem(int index) { switch (index) { case 0: return new FirstFragment(); case 1: return new SecondFragment(); case 2: return new ThirdFragment(); } return null; } Then we would have to override methods to listen to activities in tabs : @Override public void onTabReselected(Tab tab, FragmentTransaction ft) { } @Override public void onTabSelected(Tab tab, FragmentTransaction ft) { // on tab selected // show respected fragment view viewPager.setCurrentItem(tab.getPosition()); } @Override public void…

Continue ReadingUsing TabLayouts in your Android app

Getting Signed Release apk’s from the command line

  https://medium.com/@mananwason/getting-signed-release-apks-from-the-command-line-2b8681d39124#.xly87m4qp If anyone of you has deployed an application on the play store, you may have most probably used Android Studio’s built in Generate signed apkoption. The generate apk option in android studio Recently while making the Open Event Apk generator, I had to make release apk’s, so that they could be used by an event organiser to publish their app, plus apk’s had to be signed because if they were not signed, it would be impossible to upload due to checks by Google. Error shown on the developers console So since I was building the app using the terminal and I didn’t have the luxury of signing the app using Android studio and I had to look for alternatives. Luckily I found two of them : Using the Signing configs offered by gradle Using the Oracle sun jarsigner First of all the signing configs in gradle is a great way to do this. Most Open source apps use this as a way to put their code out for everyone to view and sucessfully hide any private keys and password. You just need to add few lines of code in your app level build.gradle file and create a file called keystore.properties In your keystore.properties, we just need to store the sensitive info and this file will be accessible only to people who are part of the project. storePassword=myStorePassword keyPassword=mykeyPassword keyAlias=myKeyAlias storeFile=myStoreFileLocation Next we go to the build.gradle and add these lines to read the keystore.properties file and it’s variables // Create a variable called keystorePropertiesFile, and initialize it to your // keystore.properties file, in the rootProject folder. def keystorePropertiesFile = rootProject.file("keystore.properties") // Initialize a new Properties() object called keystoreProperties. def keystoreProperties = new Properties() // Load your keystore.properties file into the keystoreProperties object. keystoreProperties.load(new FileInputStream(keystorePropertiesFile)) Next we can add the signingConfigs task and reference the values we got above over there android { signingConfigs { config { keyAlias keystoreProperties['keyAlias'] keyPassword keystoreProperties['keyPassword'] storeFile file(keystoreProperties['storeFile']) storePassword keystoreProperties['storePassword'] } } ... } So As you see this is as simple as this but according to my requirements this seemed a bit tedious since a person setting up the apk generator had to make a keystore file, then find the build.gradle and change the path of the keystore file according to the server directories. So this does the trick but this can be so tedious for someone with no technical experience, so I researched on other solutions and then I got it : Jarsigner and Zipalign First of all,the jarsigner and zipalign are 2 great tools and the best part about them is that both of them work perfectly with a just one line commands. For signing the app : jarsigner -keystore <keystore_file> -storepass <storepassword> <apknameTosigned> <alias> and then zipaligning : zipalign -v 4 <unaligned-apk-location> <path-to-generated-aligned-apk> So this is it, we finally used these 2 commands to sign and zipalign an apk and it works perfectly fine. Please test and share comments of the demo live @ http://192.241.232.231. Ciao !

Continue ReadingGetting Signed Release apk’s from the command line

Open Event Apk generator

So we made this apk generator currently hosted on a server (http://192.241.232.231) which let’s you generate an android app for your event in 10 minutes out of which the server takes about 8 minutes to build :P . So, essentially you just have to spare 2 minutes and just enter 3 things(email, Desired app’s name and Api link). Isn’t this cool? So how exactly do we do this? At the backend, we are running a python scripts with some shell scripts where the python script is basically creating directories, interacting with our firebase database to get the data entered by a user. So we made these scripts to first of all to clone the open event android repo, then customise and change the code in the repo according to the parameters entered by the organiser earlier(shown in the image). After the code has been changed by the scripts to customise the app according to the event the app will be used for, we move on to the script to build the apk, where we build and sign the apk in release mode using signing configs and release keys from the server because we don’t the organiser to generate keys and store it on the server to avoid the hassle and also the privacy concerns involving the keys. So this is when the apk is generated on the server. Now you have questions like the apk is generated but how do I get it? Do I have to wait on the same page for 10 minutes while the apk is being sent? The answer is no and yes. What I mean by this is that you can wait to download the apk if you want but we’ll anyways send it to your email you specified on the apk generator website. This is the sample Email we got when we were testing the system So it’s an end to end complete solution from which you can easily get an android app for your event in just 2 minutes. Would love to hear feedback and reviews. Please feel free to contact me @ manan13056@iiitd.ac.in or on social media’s(Twitter, Facebook). Adios! P.S. : Here is the link to the scripts we're using.

Continue ReadingOpen Event Apk generator