WebViewHelper Library in Android

Recently, I've fiddling around a long lived Widget in Android "WebViews". I created a open source library WebView Helper to help with automatic URL validations and connivence methods to enable and disable JavaScript in a WebView. Don't forget to checkout out this post.

Source code is available on Github here.

RecyclerView sample code examples

If you're looking for sample code to get started with RecyclerView in Android, then this post is for you !

Here's link to my github repo to demonstrate Linear and Grid Layout using RecyclerView. 

Convert Canvas into Bitmap and Saving image in Gallery

Have you ever thought of drawing something on Canvas and sharing it with others ? If yes, then this post is for you :)

So, you know that you can draw your stuff on a Canvas view. If you want to share your work with others, you may want to save it as an image. This post shows how to convert a Canvas view into a bitmap. First "Play" menu-item will show a programmatically drawn text on canvas view. "Save" icon will save it in gallery as well as in external SD card.

Details:

First create Custom View called MyCanvas class:
package com.teach.mycanvasapp;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.view.View;

public class MyCanvas extends View {
    public MyCanvas(Context context) {
        super(context);
        // TODO Auto-generated constructor stub    }

    @Override    protected void onDraw(Canvas canvas) {
        // TODO Auto-generated method stub        super.onDraw(canvas);
        Paint pBackground = new Paint();
        pBackground.setColor(Color.WHITE);
        canvas.drawRect(0, 0, 512, 512, pBackground);
        Paint pText = new Paint();
        pText.setColor(Color.BLACK);
        pText.setTextSize(20);
        canvas.drawText("This is a sample canvas image", 100, 100, pText);
    }
}

Second, reference MyCanvas from MainActivity class to show it inside ImageView. I've two menu-items, one is for showing the bitmap and another is to take save action :

package com.teach.mycanvasapp;

import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.drawable.BitmapDrawable;
import android.media.MediaScannerConnection;
import android.net.Uri;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.ImageView;

import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;

public class MainActivity extends AppCompatActivity {

    ImageView imageView = null;

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

    @Override    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.menu, menu);
        return true;
    }

    @Override    public boolean onOptionsItemSelected(MenuItem item) {
        int id = item.getItemId();

        if (id == R.id.show_canvas) {
            View v = new MyCanvas(getApplicationContext());
            Bitmap bitmap = Bitmap.createBitmap(500/*width*/, 500/*height*/, Bitmap.Config.ARGB_8888);
            Canvas canvas = new Canvas(bitmap);
            v.draw(canvas);
            imageView = (ImageView) findViewById(R.id.imageView);
            imageView.setImageBitmap(bitmap);
            return true;
        } else if (id == R.id.save_canvas) {
            saveImageToGallery();
            return true;
        }

        return super.onOptionsItemSelected(item);
    }

    public void saveImageToGallery() {
        Bitmap bitmap = ((BitmapDrawable)imageView.getDrawable()).getBitmap();

        //Writing image to SD card.        //It could also be saved to internal storage.        // That way, we don't need to have extra permissions        File dir = new File("/sdcard/tempfolder/");

        try {
            if (!dir.exists()) {
                dir.mkdirs();
            }

            File output = new File(dir, "tempfile.jpg");
            if (!output.exists())
                output.createNewFile();

            OutputStream os = null;
            os = new FileOutputStream(output);
            bitmap.compress(Bitmap.CompressFormat.JPEG, 100, os);
            os.flush();
            os.close();

            //Scans image and save it in gallery            MediaScannerConnection.scanFile(this, new String[] { output.toString() }, null,
                    new MediaScannerConnection.OnScanCompletedListener() {
                        public void onScanCompleted(String path, Uri uri) {
                            Log.d("Test", "Image saved in gallery!");
                        }
                    }
            );
        } catch (Exception e) {
            Log.d("Test", "Exception: " + e.getMessage());
        }
    }
}

Here's link to the github repo: https://github.com/ptyagi911/MyCanvasApp

Safe Installing from Web on Mac OSX


  • Step 1: You should have md5 tool setup to verify installer/file downloaded from web.
    • brew install md5sha1sum


  • Step 2: Check downloaded file like this:
    • md5sum <path-to-file-to-be-verified>

Android Studio: Files to keep in version control

Here's list of files that should be kept under version control like Git:

  • compiler.xml
  • encodings.xml
  • modules.xml
  • *.ipr : Contains project related data.
File to be included in gitignore OR not to be kept under version control:
  • workspace.xml
  • *.iws : Contains user specific data.

Tinkering with Physical Web (Android)

How to convert a device into beacon (Device 1)


  • Install Beacon Toy application on device that you want to convert/use as beacon.
  • Enable data (wifi or cellular and bluetooth on this device)
  • Configure URL in Beacon Toy application. You also have option to choose to get a short url.
  • I'm using my blog's url for this testing purpose.

How to enable physical web on your device (Device 2)

  • Enable data, location and bluetooth
  • Open Chrome and turn on Physical Web 
    • Chrome --> Settings --> Privacy --> Physical Web
  • Download Physical Web app from Play Store.
  • Open Physical Web app.
    • It'll start scanning all the nearby beacons.
    • It'll pick up Device 1's transmitted url and open my blog :)

Tinkering with Firebase: Notifications

Here are quick steps/tips to integrate Firebase notifications in your client app:

  • AndroidManifest :

<application>
.....
.....
<service android:name=".MyFirebaseMessagingService"> <intent-filter> <action android:name="com.google.firebase.MESSAGING_EVENT"/> </intent-filter> </service> <service android:name=".MyFirebaseInstanceIdService"> <intent-filter> <action android:name="com.google.firebase.INSTANCE_ID_EVENT"/> </intent-filter> </service> </application>
  • app/build.gradle:
dependencies {
    compile 'com.google.firebase:firebase-messaging:9.0.2'}

//Make sure to apply it at the end of the file
apply plugin: 'com.google.gms.google-services'
  • Project level build.gradle:
dependencies {
    classpath 'com.google.gms:google-services:3.0.0'
}
  • New Classes:
    • class MyFirebaseMessagingService extends FirebaseMessagingService
      • This is where notifications rendering is handled.

      • Method responsible for message handling: 

      @Overridepublic void onMessageReceived(RemoteMessage remoteMessage) {}

    • class MyFirebaseInstanceIdService extends FirebaseInstanceIdService

      • This class is useful in getting the device token. This token is used if you want to send message to that particular device.
      • This token can be collected: FirebaseInstanceId.getInstance().getToken() during app initialization.


  • Side Notes:
    
    
    • You app should be signed setup for using Firebase by generating and copying google-services.json under your app/ folder.
    • You'll get opportunity to download google-services.json while configuring your Firebase Notifications via Firebase Console.
    • New SHA can be added from Setting tabs under chosen project.

How to keep Multi-Dex issue away !



Configuring gradle plug-in:

Global build.gradle:

classpath 'com.getkeepsafe.dexcount:dexcount-gradle-plugin:0.5.0'


Local : app/build.gradle

apply plugin: 'com.android.library'
//AFTER android or library pluginapply plugin: 'com.getkeepsafe.dexcount'






References:
  • http://jeroenmols.com/blog/2016/05/06/methodcount

Rx-Android sample code

There's lots of fuss around Rx/functional programming these day. I wanted to learn by doing, but couldn't find any simple example code to get me started. There're plenty of information for advanced programmers, but nothing basic. So I'm sharing a very simple sample app that uses Rx-Android to do the same thing that an AsyncTask would do. Checkout README for more details.

Source code is here: https://github.com/ptyagi911/rx-android-examples

Super Simple example code for Android Fragment

Looking for easy to follow code to understand Fragments in Android ? You're at right place ! Checkout this sample code in github: https://github.com/ptyagi911/android-fragments-example

Android supported Java8 features


  • default and static methods in Interfaces
    • default and static methods can be declared in Interfaces declarations. These methods don't need to be implemented by the Classes that are implementing those interfaces. static methods are attached to the Interface and Classes which implements such interfaces.
    • Reference: https://docs.oracle.com/javase/tutorial/java/IandI/defaultmethods.html
  • Repeating Annotations
    • Now one annotation can be used multiple times on a specific target.
    • Reference: https://docs.oracle.com/javase/tutorial/java/annotations/repeating.html
  • Lambda expressions:
    • Lambda expressions enable to treat functionality as method argument or code as data.
    • Lambda exp is useful especially to define anonymous class with one method
    • Reference: https://docs.oracle.com/javase/tutorial/java/javaOO/lambdaexpressions.html
    • Syntax for Lambda expressions: https://docs.oracle.com/javase/tutorial/java/javaOO/lambdaexpressions.html#syntax

Terms:
  • Functional interfaces: An interface with only method is called as functional interfaces. JDK defines few built-in functional interfaces in package: java.util.function 

How to setup Signing configuration in Android Studio/Gradle

Add following to your build.gradle :



android {

defaultConfig {}
signingConfigs {

   release {
      storeFile file("<path-to-signing-keys>/signingKeys.jks")
      storePassword "your store password"      keyAlias "your chosen alias"      keyPassword "password"
   }
}
You can also publish to playtore by adding following configuration to your build.gradle:
play {
    serviceAccountEmail = 'serviceAccount@gmail.com'    pk12File = file('key.p12')
    track = 'alpha'}

Automatic publishing apk to Google Play Store Developer Console using Jenkins


  1. Jenkins plugins:
    1. Google Play Publishing plugins (only works on Jenkins version > 1.6.09)
  2. Jenkins Build job
    1. Separate build job for each flavor of apk
    2. Create Free style build job in jenkins as described here.
  3. Configure Service Account on Google Play Store as shown here.

Android Testing using ATSL (Android Testing Support Library)


Running instrumented unit tests
Instrumented unit tests are important when a functionality can't be tested using mock objects.

Tools used
AndroidJunitRunner is used to run such tests.

Configuring build.gradle
defaultConfig {
applicationId "appId" minSdkVersion 17 targetSdkVersion 23 versionCode 1
versionName "1.1"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"}
Dependencies
dependencies {
compile 'com.android.support:support-annotations:23.0.1' compile 'com.android.support:appcompat-v7:23.0.1'

androidTestCompile 'junit:junit:4.12' androidTestCompile 'com.android.support:support-annotations:23.0.1' androidTestCompile 'com.android.support.test:runner:0.4.1' androidTestCompile 'com.android.support.test:rules:0.4.1'
}
Running Instrument tests:
gradlew connectedAndroidTest


Useful links:

How to access build version from build.gradle from Java class

Its available in BuildConfig.java.

So simply access version name like this:
BuildConfig.VERSION_NAME

And Version code could be accessed like this:
BuildConfig.VERSION_CODE 

How to publish artifacts (Android Library in "aar" format) to Maven repo from Android Studio gradle

This post shows build.gradle configuration to be able to push artifacts to local Maven repo. I've taken Android library in its "aar" format as artifact for example.

First add "maven-publish" plugin to enable publishing artifacts from build.gradle:
apply plugin: 'maven-publish'
Don't forget to add local maven repo:
repositories {
    mavenLocal()
}
Add publishing block now:
publishing {
    publications {
        mavenJava(MavenPublication) {
            groupId <GROUP_ID>
            artifactId <ARTIFACT_ID>
            version <currentVersion>

            artifacts = ["${buildDir}/outputs/aar/<your_android_library>.aar"]
        }
    }
}

Scheduling Repeating Local Notifications using Alarm Manager

Learn about Scheduling Repeating Local Notifications using Alarm Manager in this post .