Monday, 13 February 2017

Task Scheduling in Android Via JobScheduler

Hello Guys!!! Hope You all doing well.
Today I am going to discuss JobScheduler in Android, its uses and implementation.
Obviously our first question what is JobScheduler ? What is Task Scheduling ?
Our Android apps, based on our requirement, can perform many of their tasks asynchronously, outside the direct flow of user interaction.
As for examples:

  • Updating network resources.
  • Downloading information.
  • Updating background tasks.
  • Scheduling system service calls.

Scheduling this work intelligently can improve our app’s performance, along with device battery life.
That's why JobScheduler does this scheduling work for us.
Options for scheduling
Following are the avilable way to schedule tasks in Android

  • JobScheduler API.
  • (outdated) AlarmManager
  • Firebase JobDispatcher
  • SyncAdapter

The job scheduler API
In Android 5.0 Lollipop (API 21) released job scheduler API via the JobScheduler class. This API allows to batch jobs when the device has more resources available. In general this API can be used to schedule everything that is not time critical for the user.

In Android 7 (N API 24) it become Android Framework JobScheduler
As per android developer website Explanation is like below:-
JobScheduler is the Android framework API for scheduling tasks or work. It first became available in Android 5.0 (API level 21), and remains under active development. Notably, Android 7.0 (API level 24) added the ability to trigger jobs based on ContentProvider changes.

JobScheduler is implemented in the platform, which allows it to collect information about jobs that need to run across all apps. This information is used to schedule jobs to run at, or around, the same time. Batching job execution in this fashion allows the device to enter and stay in sleep states longer, preserving battery life.
Advantages of the job scheduler API
  • The JobScheduler supports batch scheduling of jobs, that is not possible via custom SyncAdapter or the alarm manager.
  • By using JobScheduler android system can combine jobs so that battery consumption is reduced.
  • JobManager makes handling uploads easier as it handles automatically the unreliability of the network.
  • It also survives application restarts.
Example when to use job scheduler:
  • Tasks that should be done once the device is connect to a power supply
  • Tasks that require network access or a Wi-Fi connection.
  • Task that are not critical or user facing
  • Tasks that should be running on a regular basis as batch where the timing is not critical
We can schedule the task to run under specific conditions, such as:
  • Device is charging
  • Device is connected to an unmetered network
  • Device is idle
  • Start before a certain deadline
  • Start within a predefined time window, e.g., within the next hour
Inline image 1
job service life cycle

Hands On
Let us create a simple application that uses JobScheduler API. You can download full source code.
1. Creating the Job Service
To start, we are going to create a new Android project with a minimum required API of 21, because the JobScheduler API was added in the most recent version of Android
Dowload Source code



package com.example.saurabh.blogapplication;

import android.app.job.JobInfo;
import android.app.job.JobParameters;
import android.app.job.JobScheduler;
import android.app.job.JobService;
import android.content.Context;
import android.content.Intent;
import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;
import android.util.Log;
import android.widget.Toast;

/**
 * Created by ee208840 on 16/5/17.
 */
//Require API Level 21
public class MyJobService extends JobService {

    private static final String TAG = "MyJobService";

    // this is required method for JobService
    // This method is called when the scheduled job
    // is started
    @Override
    public boolean onStartJob(JobParameters params) {
        Log.d(TAG, "on start job...");
        Toast.makeText(this, "MyJobService.onStartJob()", Toast.LENGTH_SHORT).show();
          /*
      * True - if your service needs to process
     * the work (on a separate thread).
     * False - if there's no more work to be done for this job.
     */
        return false;
    }

    // this is required method for JobService
    // This method is called when the scheduled job
    // is stopped
    @Override
    public boolean onStopJob(JobParameters params) {
        Log.d(TAG, "on stop job....");
        Toast.makeText(this, "MyJobService.onStopJob()", Toast.LENGTH_SHORT).show();
        return false;
    }


    // This method is called when the service instance
    // is created
    @Override
    public void onCreate() {
        super.onCreate();
        Log.d(TAG, " myJobService created....");
    }

    // This method is called when the service instance
    // is destroyed
    @Override
    public void onDestroy() {
        super.onDestroy();
        Log.d(TAG, "myJobService destroyed...");
    }

    MainActivity myMainActivity;

    public void setUICallback(MainActivity activity) {
        myMainActivity = activity;
    }

    // This method is called when the start command
    // is fired
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.d(TAG, "myJobService onStartCommand called...");
        Messenger callback = intent.getParcelableExtra("messenger");
        Message m = Message.obtain();
        m.what = 2;
        m.obj = this;
        try {
            callback.send(m);
        } catch (RemoteException e) {
            Log.e(TAG, "Error passing service object back to activity.");
        }
        return START_NOT_STICKY;

    }

    // Method that schedules the job
    public void scheduleJob(JobInfo build) {
        Log.d(TAG, "Scheduling job...");
        JobScheduler jobScheduler = (JobScheduler) getSystemService(Context.JOB_SCHEDULER_SERVICE);
        jobScheduler.schedule(build);
    }
}

package com.example.saurabh.blogapplication;

import android.app.job.JobInfo;
import android.app.job.JobScheduler;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.os.Handler;
import android.os.Message;
import android.os.Messenger;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;

import java.util.List;

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    private Button jobScheduleButton;
    private Button btnStartJob;
    private Button btnCancelJobs;

    ComponentName myServiceComponent;
    MyJobService myJobService;
    Handler myHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            myJobService = (MyJobService) msg.obj;
            myJobService.setUICallback(MainActivity.this);
        }
    };

    // Second Example
    JobScheduler jobScheduler;
    private static final int MYJOBID = 1;

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

        initRes();

        myServiceComponent = new ComponentName(this, MyJobService.class);
        Intent myServiceIntent = new Intent(this, MyJobService.class);
        myServiceIntent.putExtra("messenger", new Messenger(myHandler));
        startService(myServiceIntent);

        //Second example
        jobScheduler = (JobScheduler) getSystemService(Context.JOB_SCHEDULER_SERVICE);

    }

    @Override
    public void onClick(View v) {
        if (v == jobScheduleButton) {
            JobInfo.Builder builder = new JobInfo.Builder(0, myServiceComponent);
            builder.setRequiresCharging(true);
            //builder.setRequiresDeviceIdle(true);
            //builder.setRequiredNetworkType(JobInfo.NETWORK_TYPE_UNMETERED);
            myJobService.scheduleJob(builder.build());
        }
        if (v == btnStartJob) {
            ComponentName jobService =
                    new ComponentName(getPackageName(), My2ndJobService.class.getName());
            JobInfo jobInfo =
                    new JobInfo.Builder(MYJOBID, jobService).setPeriodic(10000).build();
    /*
     * setPeriodic(long intervalMillis)
     * Specify that this job should recur with the provided interval,
     * not more than once per period.
     */
            int jobId = jobScheduler.schedule(jobInfo);
            if (jobScheduler.schedule(jobInfo) > 0) {
                Toast.makeText(MainActivity.this, "Successfully scheduled job: "
                        + jobId, Toast.LENGTH_SHORT).show();
            } else {
                Toast.makeText(MainActivity.this, "RESULT_FAILURE: "
                        + jobId, Toast.LENGTH_SHORT).show();
            }
        }
        if (v == btnCancelJobs) {
            List<JobInfo> allPendingJobs = jobScheduler.getAllPendingJobs();
            String s = "";
            for(JobInfo j : allPendingJobs){
                int jId = j.getId();
                jobScheduler.cancel(jId);
                s += "jobScheduler.cancel(" + jId + " )";
            }
            Toast.makeText(MainActivity.this, s,
                    Toast.LENGTH_SHORT).show();

            //or
            //jobScheduler.cancelAll();
        }
    }

    private void initRes() {
        jobScheduleButton = (Button) findViewById(R.id.buttonScheduleJob);
        jobScheduleButton.setOnClickListener(MainActivity.this);
        btnStartJob = (Button) findViewById(R.id.startJob_btn);
        btnStartJob.setOnClickListener(MainActivity.this);
        btnCancelJobs = (Button) findViewById(R.id.cancelJobs_btn);
        btnCancelJobs.setOnClickListener(MainActivity.this);
    }

}
package com.example.saurabh.blogapplication;

import android.app.job.JobParameters;
import android.app.job.JobService;
import android.widget.Toast;

/**
 * Created by ee208840 on 16/5/17.
 */

public class My2ndJobService extends JobService{

    public My2ndJobService() {
    }

    @Override
    public boolean onStartJob(JobParameters params) {

        Toast.makeText(this, "My2ndJobService.onStartJob()", Toast.LENGTH_SHORT).show();
  /*
   * True - if your service needs to process
   * the work (on a separate thread).
   * False - if there's no more work to be done for this job.
   */
        return false;
    }

    @Override
    public boolean onStopJob(JobParameters params) {

        Toast.makeText(this, "My2ndJobService.onStopJob()", Toast.LENGTH_SHORT).show();

        return false;
    }
}

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.example.saurabh.blogapplication.MainActivity">

    <TextView
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="10dp"
        android:text="Hello Job Scheduler"
        android:textColor="#000000"
        android:textStyle="bold" />

    <Button
        android:id="@+id/buttonScheduleJob"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="10dp"
        android:layout_below="@+id/textView"
        android:textAllCaps="false"
        android:text="Schedule Job" />

    <TextView
        android:id="@+id/second_txt_view"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/buttonScheduleJob"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="10dp"
        android:textColor="#000000"
        android:textStyle="bold"
        android:text=".... Second Example on Job Scheduler ..."/>

    <Button
        android:id="@+id/startJob_btn"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="10dp"
        android:layout_below="@+id/second_txt_view"
        android:text="Start a Job" />

    <Button
        android:id="@+id/cancelJobs_btn"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="10dp"
        android:layout_below="@+id/startJob_btn"
        android:layout_centerHorizontal="true"
        android:text="Cancel all Jobs" />


</RelativeLayout>
Please go through inline comment in above code. It will help you to understand Jobscheduler better.
Thanks
Saurabh
Happy Coding!!!!

Sunday, 5 February 2017

Describing Content of AOSP Folder

Hello Guys!!! Hope You all doing well.

Toady I am going to describe what all file and folder contained by AOSP source code folder and its uses.  In my Previous Post, I had described "How to download Android AOSP Code". Click here for that post.
 So after successfully download of Android AOSP source code for any version(L,M or N), you find so many subfolders and file inside AOSP source Code Folder.   Today I am going to put some light on it.

 Now I am starting folder name in alphabetical order .

1. abi - This folder contains a subfolder called cpp which actually contains many C++ files linked to many places.

2. art - it is the folder that deals with the compilation of the latest android ART run time.

3. bionic - Bionic is mainly a port of the BSD C library to our Linux kernel with the following additions/changes:

  • No support for locales.
  • No support for wide chars (i.e. multi-byte characters).
  • its own smallish implementation of pthreads based on Linux futexes.
  • Support for x86, ARM and ARM thumb CPU instruction sets and kernel interfaces.
4. bootable - Boot and startup related code. Some of it is legacy, the fastboot protocol info could be interesting since it is implemented by boot loaders in a number of devices such as the Nexus ones.

5. build - The main entry point of the build system resides here - envsetup.sh. 
First step before you do anything to build Android is to use the command
source build/envsetup.sh
This script will check few things to make sure all the needed application available in the local machine. It also setup the devices that can be built, which is extracted from the directory device.

6. cts - the compatibility tests. The test suite to ensure that a build complies with the Android specification. How to use it or download it. Please follow my this Blog Link

7. dalvik - This is the folder responsible for the compilation of the Dalvik runtime for the Android devices.
Have a look at the difference between the two(art and dalvik) folders and you'll have an idea of how things work in that case.

8. Development - This directory contains application that are not part of the deployed app in the OS. There are some useful application such as widget builder, etc

9. Device - It contains the device specific configurations for many devices. It contains following   subfolder  'common',  'generic', 'Google' and 'Sample'.
 common - This directory contains gps information and also a script that allows you to extract proprietary binary files from your phone to be part of the build process.(You can try to have a look at your device's device tree and then the cm.mk file, where you could find relations of these files. In my case, it shows like this:
# Include GSM stuff
$(call inherit-product, vendor/cm/config/gsm.mk)
-and-
# Inherit some common cyanogenmod stuff.
$(call inherit-product, device/common/gps/gps_eu_supl.mk)
generic - This directory contains the generic device configuration that is called ‘goldfish’. This is the device classification used when building for the emulator.

Google - This directory contains the Android Accessories Kit code. It contains a demokit Android app that allows you to control the ADK board.

sample - This directory contains a full example of writing your own Android platform shared library, without changing the Android framework. It also shows how to write JNI code for incorporating native code into the library, and a client application that uses the library. This example is ONLY for people working with the open source platform to create a system image that will be delivered on a device which will include a custom library as shown here. It can not be used to create a third party shared library, which is not currently supported in Android.

10. external - This directory contains source code for all external open source projects such as SQLite, Freetype, webkit and webview.

11. frameworks - One of the most important directories. it contains the sources for the framework. Here you will find the implementation of key services such as the System Server with the Package and Activity managers.
A lot of the mapping between the java application APIs and the native libraries is also done here.

12. hardware - Hardware related source code such as the Android hardware abstraction layer (HAL) specification and implementation. This folder also contains the reference Radio Interface Layer(RIL - To communicate with the modem side) implementation.

13. Kernel - It's not a default folder in the source code, but it's a part of device configuration set-up. It contains the kernel source of your device.

14. libcore - I'll explain this one with the important folders inside this, since every folder performs a different function.
dalvik - DalvikVM runtime for Android
dom - Java test classes for DOM
expectations - Contains information about the test cases
include - Some C/C++ include files that used for Array and String handling
json - JSON based Java implementation
luni - Contains test source code for loading .jar and .dex files
support - Contains support class file for testing Dalvik
xml - XML pull and push implementation

15. ndk - Contains build scripts and helper files for building the NDK

16. out - The build output will be placed here after you run make.
The folder structure is out/target/product/. In the default build for the emulator the output will be placed in out/target/product/generic. This is where you will find the images used by the emulator to start (or to be downloaded and flashed to a device if you are building for a hardware target).

17. packages - Standard Android application that are available as part of the AOSP - Camera, SMS, Dialer, Launcher, etc

18. prebuilt - Contains files that are distributed in binary form for convenience. Examples include the cross compilations toolchains for different development machines.

19. sdk - This directory contains lots of apps that are not part of operating system. There are quite useful apps that developers can leverage on and can be enhanced further as part of the operating system.

20. system - Source code files for the core Android system. That is the minimal Linux system that is started before the Dalvik VM and any java based services are enabled. This includes the source code for the init process and the default init.rc script that provide the dynamic configuration of the platform.

21. tools - Some external important tools that help in compiling. Not sure.

22. vendor - This directory contains vendors specific libraries. Most of the proprietary binary libraries from non-open source projects are stored here when building AOSP.

Apart from above mention folder , there is  a hidden .repo directory that contains the source for the repo utility. It also contain a manifest specifying what git repositories you want to track for this Android source project. If you have your own additions you could automatically track them by adding a local manifest here.

For modifications of the platform framework there are some instructions available in the device/sample folder of the source code tree. That will show you how to add APIs to Android without having to modify the core framework.

Hope it will help you understanding the Android AOSP Source code subfolder and its uses. In my next Blog I will deal "Android AOSP Build Process and its command"

Happy Coding!!!

Thanks
Saurabh
Note:- Please proved your comment and suggestion for my post. It will energize me.

Wednesday, 1 February 2017

Generate .SO file by using NDK and use it in Android APP

Hello Guys !!! Hope You all are doing well.

Today I am going to Discuss how to generate .So file  by using NDK and how to use this file  as library in Android App by using Android Studio.

Obvious question  What is SO File??
Right I am giving brief detail...
In Android we are able to use C, C++ code known as a Native code for java. Android NDK  compiles this code into .so files. just like jar file in java to use it as library.  As per  Android NDK site below is  brief detail 

Application Binary Interface (ABI): The ABI defines exactly how your app's machine code is expected to interact with the system at runtime. The NDK builds .so files against these definitions. Different ABIs correspond to different architectures: The NDK includes ABI support for ARMEABI (default), MIPS, and x86. For more information, see ABI Management.

Now, I hope Guys I can proceed further.  Second Question How to create .SO file from Native Code?
  Here  I am describing it as a Step by Step procedure.

Step 1 Create a Folder (Let say hello-jni/jni)
I am using Ubuntu machine so let say under the u dir I have created one hello-jni folder and then one more jni folder. Then add three files inside this jni folder. Android.mk, Application.mk and hello-jni.c

Step 2 Modify content of MK file
Now open one by one 2 MK file. First open Android.mk file and copy paste following code in it.

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE    := hello-jni
LOCAL_SRC_FILES := hello-jni.c
include $(BUILD_SHARED_LIBRARY)
Open Application.mk file and copy paste follwoing code
APP_CFLAGS += -Wno-error=format-security
APP_ABI := all
# APP_ABI := armeabi armeabi-v7a x86 

Step 3 Modify Native Code
Open hello-jni.c file and copy paste following code in it.
#include <string.h>
#include <jni.h>

JNIEXPORT jstring JNICALL 
Java_softsolution_sks_com_myhellojni_MainActivity_getStringFromJNI(JNIEnv *env, jobject thisObj) {
   return (*env)->NewStringUTF(env, "Hello from native code!");
}

jstring
Java_softsolution_sks_com_myhellojni_MainActivity_getJniString(JNIEnv* env, jobject thiz){
    return (*env)->NewStringUTF(env, "Hello from JNI! Saurabh");
}

JNIEXPORT jint JNICALL 
Java_softsolution_sks_com_myhellojni_MainActivity_getIntSqure(JNIEnv* env, jobject obj,jint value) {
    return value * value;
}

JNIEXPORT jboolean JNICALL 
Java_softsolution_sks_com_myhellojni_MainActivity_getBooleanMethod(JNIEnv* env,jobject obj, jboolean unsignedChar) {
    return !unsignedChar;
}
Step 4 Generate .SO file by using NDK Build
This is the last step to generate .so file for your native code by using NDK Build command. After Generation this SO file, You can use it as lib in Your Android Studio Project.
 Open Your terminal(Ubuntu) and reached till your hello-jni folder.

As for Example u/hello-jni/jni . Then set Path variable for your NDK . Here I am assuming that You had downloaded NDK and kept it in u Dir.

export PATH=$PATH:/u/android-ndk-r14-beta1
 SYSROOT=u/android-ndk-r14-beta1/platforms/android-21/arch-arm/
After it run build command  
 ndk-build
That's it, It will generate .SO file for all ABI. Now Copy these ABI(.So file) and use it in your Android App. I am going to explain it below.

Using .So file in Android Studio 
With Latest Android Studio version(2.2.3), You are able to directly developed your app with NDK. 
But here i am discussing how you can use generated .so file in Android studio. 
  
Step 1 Create one new Project (or module in your existing Project) 
Let create one new Project/Module myhellojni in Android Studio. Then create a folder inside src main  as for example
 /src/main/jniLibs Then copy all your .so file with folder and paste it inside jniLibs like below.

Step 2 Add jniLibs path in build.gradle 

add below given path in hello-jni/build.gradle file under android{...} tag

sourceSets.main {
    jniLibs.srcDir 'src/main/libs'}


Step 3  Use Native Method in MainActivity 
Now you can use native method inside your app activity. As for example

public class MainActivity extends AppCompatActivity {

    private static final String TAG = "MainActivity";

    static {
        Log.d(TAG,"Loads lib started..");
        System.loadLibrary("hello-jni");
        Log.d(TAG,"Load libs finished");
    }

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

        TextView tv = (TextView)findViewById(R.id.hello_txt);
        tv.setText(" hi "+getStringFromJNI());
    }

    public native String getStringFromJNI();
}


That's it.  Hope you guys Enjoy it.

Happy Coding!!!

Thanks
Saurabh

Note:- Please proved your comment and suggestion for my post. It will energize me.

Build a Custom Kernel Module for Android

Hi Guys!!!Hope you are doing well !!!. Today I will describe how you can write a custom kernel module(Hello world) for Android and load it a...