Sunday, 14 May 2017

Scheduling repeated tasks offline at (almost) exact times

As you probably know, starting from API level 21 (Lollipo) the best way to schedule repeated tasks on Android is using:
  • the JobScheduler API (requires API level 21+);
  • the Firebase JobDispatcher, which provides a JobScheduler-compatible API that works on all recent versions of Android (API level 9+) that have Google Play services installed.
Running apps in the background is expensive, which is especially harmful when they're not actively doing work that's important to the user.
In recognition of these issues, the Android framework team created the JobScheduler. This provides developers a simple way of specifying runtime constraints on their jobs. Available constraints include network type, charging state, and idle state.

On the other hand, the Firebase JobDispatcher uses the scheduling engine inside Google Play services(formerly the GCM Network Manager component) to provide a backwards compatible (back to Gingerbread) JobScheduler-like API.

Problem

However, both the JobScheduler API and the Firebase JobDispatcher, in order to save battery life, depend on the mainance windows of Doze.
In other words, if a user leaves a device unplugged and stationary for a period of time, with the screen off, the device enters Doze mode. In Doze mode, the system attempts to conserve battery by restricting apps' access to network and CPU-intensive services. It also prevents apps from accessing the network and defers their jobs, syncs, and standard alarms.Periodically, the system exits Doze for a brief time to let apps complete their deferred activities. During thismaintenance window, the system runs all pending syncs, jobs, and alarms, and lets apps access the network.
Doze - mantainance windows

Warning

In this post we'll focus on scheduling repeated tasks (even offline, whithout an internet connection) that should start at (almost) exact times.

AlarmManager

Although the aforementioned solution is preferable, because it enables to save battery life, there might be scenarios in which you want to schedule a repetead task to run with an exact timing, even when the device is in Doze mode.
A possible solution is using the AlarmManager. The exact methods and the pattern to follow varies depending on the Android version, because:
  • Doze was first introduced with Marshmallow (API level 23);
  • the AlarmManager methods for scheduling tasks have slightly changed with API leve 19.

The following table shows the methods to use:



repeated
exact times
display ON
repeated
exact times
display OFF
up to API 18
setRepeating
RTC or ELAPSED_REALTIME
(1)
setRepeating
RTC_WAKEUP or
ELAPSED_REALTIME_WAKEUP
API 19-22
setExact with manual re-scheduling
RTC
ELAPSED_REALTIME
(1) (2)
setExact with manual re-scheduling
RTC_WAKEUP
ELAPSED_REALTIME_WAKEUP
API 23+
setExact or setExactAndAllowWhileIdle with manual re-scheduling
(3)
setExactAndAllowWhileIdle with manual re-scheduling
(3)

(1) If an alarm is delayed (by system sleep, for example, for non _WAKEUP alarm types), a skipped repeat will be delivered as soon as possible. After that, future alarms will be delivered according to the original schedule; they do not drift over time. For example, if you have set a recurring alarm for the top of every hour but the phone was asleep from 7:45 until 8:45, an alarm will be sent as soon as the phone awakens, then the next alarm will be sent at 9:00.
(2) as of API 19, all repeating alarms are inexact. If your application needs precise delivery times then it must use one-time exact alarms, rescheduling each time. Legacy applications whose targetSdkVersion is earlier than API 19 will continue to have all of their alarms, including repeating alarms, treated as exact. With setExact the alarm will be delivered as nearly as possible to the requested trigger time.
(3) If you don't need exact scheduling of the alarm but still need to execute while idle, consider using setAndAllowWhileIdle(int, long, PendingIntent).

Frequency

For events less than 60 seconds apart, alarms aren’t the best choice: use the much more efficient Handler (http://goo.gl/CE9vAw) for frequent work.

setExactAndAllowWhileIdle: exact or not?

The method setExactAndAllowWhileIdle, used to trigger alarms even when the device is idle, can significantly impact the power use of the device when idle (and thus cause significant battery blame to the app scheduling them), so it should be used with care.

To reduce abuse, there are restrictions on how frequently these alarms will go off for a particular application:
  • Under normal system operation, it will not dispatch these alarms more than about every minute (at which point every such pending alarm is dispatched)
  • When in low-power idle modes this duration may be significantly longer, such as 15 minutes


Manual rescheduling

As you can see from the above table, starting with API 19 you have to use setExact or setExactAndAllowWhileIdle the schedule a repeated task at exact times.
Infact, as of API 19, all repeating alarms are inexact. If your application needs precise delivery times then it must use one-time exact alarms, rescheduling each time as described below. Legacy applications whose targetSdkVersion is earlier than API 19 will continue to have all of their alarms, including repeating alarms, treated as exact.

Create an AlarmManager instance:
AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);

Create an Intent to broadcast to a BroadcastReceiver:
Intent intent = new Intent(MyActivity.this, MyReceiver.class);

Create a PendingIntent that holds the intent:
PendingIntent pendingIntent = PendingIntent.getBroadcast(MyActivity.this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);

Create the alarm:
alarmManager.setExact(AlarmManager.RTC_WAKEUP, initialDelay, pendingIntent);

Reschedule the next alarm in the onReceive method of your BroadcastReceiver using the same code described above.

WakefulBroadcastReceiver

The Alarm Manager holds a CPU wake lock as long as the alarm receiver's onReceive() method is executing. This guarantees that the phone will not sleep until you have finished handling the broadcast. Once onReceive() returns, the Alarm Manager releases this wake lock. This means that the phone will in some cases sleep as soon as your onReceive() method completes. If your alarm receiver called Context.startService(), it is possible that the phone will sleep before the requested service is launched. To prevent this, your BroadcastReceiver and Service will need to implement a separate wake lock policy to ensure that the phone continues running until the service becomes available.

An easy way to achieve this is by using a WakefulBroadcastReceiver. WakefulBroadcastReceiver is a BroadcastReceiver that receives a device wakeup event and then passes the work off to a Service, while ensuring that the device does not go back to sleep during the transition. This class takes care of creating and managing a partial wake lock for you; you must request the WAKE_LOCK permission to use it.

public class MyWakefulBroadcastReceiver extends WakefulBroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        // Reschedule the alarm. See the code above.

        // Create an Intent to start a Service.
        Intent service = new Intent(context, MyService.class);

        // Start the service, keeping the device awake while it is launching.
        startWakefulService(context, service);
    }
}

The service (in this example, an IntentService) does some work. When it is finished, it releases the wake lock by calling completeWakefulIntent(intent). The intent it passes as a parameter is the same intent that the WakefulBroadcastReceiver originally passed in.

public class MyService extends IntentService {
    public MyService() {
        super("MyService");
    }

    @Override
    protected void onHandleIntent(Intent intent) {
        // Do some work here.
        // At this point SimpleWakefulReceiver is still holding a wake lock
        // for us.  
        // Note that when using this approach you should be aware that if your
        // service gets killed and restarted while in the middle of such work
        // (so the Intent gets re-delivered to perform the work again), it will
        // at that point no longer be holding a wake lock since we are depending
        // on SimpleWakefulReceiver to that for us.  If this is a concern, you can
        // acquire a separate wake lock here.

        // Release the wake lock after executing the task.
        SimpleWakefulReceiver.completeWakefulIntent(intent);
    }
}

Saturday, 6 May 2017

Sticky Broadcast


Sticky Broadcast(s) are a special kind of Broadcast(s) that remain active for awhile after being sent. You can send a sticky Broadcast with the method:
Context.sendStickyBroadcast()

If you register a BroadcastReceiver that listens to sticky Broadcast(s), it can receive two kind of Broadcast(s):
  1. Broadcast(s) that have just been sent
  2. Broadcast(s) that have been sent previously and are still active
You can find out what kind of Broadcast you have just received with the method:
isInitialStickyBroadcast()
returning false if the Broadcast represents an event that has just occured.

Sticky Broadcast(s) are generally used for events lasting for a certain period of time. Examples of such Broadcast(s) sent by the system are:
  • Intent.ACTION_BATTERY_CHANGED: indicates changes in the battery level. BroadcastReceiver(s) must be programmatically registered with Context.registerReceiver()
  • Intent.ACTION_DOCK_EVENT: indicates when a device is placed on a dock
  • Intent.ACTION_DEVICE_STORAGE_LOW: indicates low memory condition
public class MyBroadcastReceiver extends BroadcastReceiver {
    public void onReceive(Context context, Intent intent) {
        String action = intent.getAction();
        if(action.equals(Intent.ACTION_DOCK_EVENT)) {
            if(!isInitialStickyBroadcast()) {
                // this is a new broadcast
            } 
            else {
                // this is an old broadcast
            }
        }
    }
}

In order to send sticky Broadcast(s) you must include the permission android.permission.BROADCAST_STICKY in the Manifest file.

If you want to remove a sticky Broadcast you can use the method:
Context.removeStickyBroadcast(Intent intent)
passing the Intent that was previously broadcast.

NB. Sticky Broadcast(s) consume system resources, so use them sparingly when really needed!

API level 21

Starting from API level 21 sticky Broadcast(s) are deprecated.
"Sticky broadcasts should not be used. They provide no security (anyone can access them), no protection (anyone can modify them), and many other problems. The recommended pattern is to use a non-sticky broadcast to report that something has changed, with another mechanism for apps to retrieve the current value whenever desired".

Monday, 26 September 2016

Reverse engineering part 2: apktool

After getting the apk file (see article: Reverse engineering part 1: getting the apk file) it's time to disassemble it and analyze its content.
The tool I will talk about is called apktool and can be downloaded from https://ibotpeaches.github.io/Apktool/, where you can also read the complete documentation. Apktool is especially useful to analyze resource files (xml layout files, Manifest, drawables, xml animation files, strings).

Apktool

Apktool is a tool for reverse engineering 3rd party, closed, binary Android apps. It can decode resources to nearly original form and rebuild them after making some modifications. It also makes working with an app easier because of the project like file structure and automation of some repetitive tasks like building apk, etc.

Reverse engineering

After installing apktool you'll find the apktool.bat file that can be run from the command line.
You just have to type:
apktool d filename.apk
(replace filename.apk with the actual file name of the apk file)

and apktool disassembles the apk file in a folder where you can find all the resource files perfectly readable.

For example, I ran apktool for Whatsapp and this is the result:

In the "res" folder you can have a look at almost every resource file of the app:


This is the layout file settings_security.xml of Whatsapp. As you can see the file is completely readable.

This is another example: the animation defined in design_fab_out.xml, that fades out a FloatingActionButton:
Analyzing the file you can find out how the animation is achieved: animating alpha from 1 to 0 and the scale of the FAB from 1 to 0. Very easy!

Conclusion

Apktool is a very powerful utility especially if you want to analyze the resource files of an app. If you have found an app with a beautiful design, or a fancy animation, and want to find out how they are made, apktool is the tool to use.

Wednesday, 21 September 2016

Reverse engineering part 1: getting the apk file

Reverse engineering, also called back engineering, is the processes of extracting knowledge or design information from anything man-made and re-producing it or re-producing anything based on the extracted information. The process often involves disassembling something (a mechanical device, electronic component, computer program, or biological, chemical, or organic matter) and analyzing its components and workings in detail.

As far as Android is concerned, suppose we have full-working Android app and we would like to find out how a particular layout is structured, how a specific animation is coded, how a visual effect is made. We can do that by reverse-engineering the apk file and extract useful information from it.

There are different tools for doing that and in the following articles we'll have a look at some of the most widely used.
Reverse engineering

Getting the apk file

The first step to reverse-engineer an Android app is getting the apk file, in order to disassemble and analyze it using the different tools available.

From the web

The easiest way to obtain the apk file of a particular app is using one the many online resources available.
For example, using this website:

you can paste the Google Play Store Url of the app you're interested in, and the service lets you download the apk file to your pc.
If you download an apk file from the web, like the online service previously mentioned, be aware of the risk of possible viruses or other malware.

From the smartphone

You can also very easily extract the apk file from an app installed on your smartphone.
To do that we can use the adb.exe utility of the Android Sdk platform (you can find it in the folder: Android\sdk\platform-tools).

Just connect the device to your pc and type the following commands in command line...

adb shell pm list packages 
to obtain a list of the apps (packages) installed and find the package you are interested in

adb shell pm path your-package-name
replace "your-package-name" with the name of the desired package
to get the full package name and the name of the app

adb pull full_path_of_the.apk
replace "full_path_of_the.apk" with the full package name of the apk file obtained with the previous command
to get the apk file in the folder where the command is executed


Monday, 19 September 2016

How to blur an image using Renderscript

RenderScript is a framework for running computationally intensive tasks at high performance on Android. RenderScript is primarily oriented for use with data-parallel computation, although serial workloads can benefit as well. The RenderScript runtime parallelizes work across processors available on a device, such as multi-core CPUs and GPUs.
RenderScript is especially useful for applications performing image processing, computational photography, or computer vision.
Let's see how you can use Renderscript to effectively blur an image.
Blurred image

Integrating Renderscript with Gradle

To add the Renderscript support library to your Android Studio project just add the following lines to build.gradle (module: app).
android {
    ...
    defaultConfig {
        renderscriptTargetApi 19
        renderscriptSupportModeEnabled true
    }
    ...
}


Code to blur the image

Now create the utility class BlurBuilder that uses RenderScript to blur the image:
/*
 * Copyright (c) - Software developed by iClaude.
 */

package com.flingsoftware.personalbudget.utilita;


import android.content.Context;
import android.graphics.Bitmap;
import android.support.v8.renderscript.Allocation;
import android.support.v8.renderscript.Element;
import android.support.v8.renderscript.RenderScript;
import android.support.v8.renderscript.ScriptIntrinsicBlur;


/**
 * This class is used to blur a Bitmap.
 * The static method blur takes a Bitmap as input e returns a blurred version of if.
 */
public class BlurBuilder {
    private static final float BITMAP_SCALE = 0.4f;
    private static final float BLUR_RADIUS = 7.5f;


    public static Bitmap blur(Context context, Bitmap image) {
        int width = Math.round(image.getWidth() * BITMAP_SCALE);
        int height = Math.round(image.getHeight() * BITMAP_SCALE);

        Bitmap inputBitmap = Bitmap.createScaledBitmap(image, width, height, false);
        Bitmap outputBitmap = Bitmap.createBitmap(inputBitmap);

        RenderScript rs = RenderScript.create(context);
        ScriptIntrinsicBlur theIntrinsic = ScriptIntrinsicBlur.create(rs, Element.U8_4(rs));
        Allocation tmpIn = Allocation.createFromBitmap(rs, inputBitmap);
        Allocation tmpOut = Allocation.createFromBitmap(rs, outputBitmap);
        theIntrinsic.setRadius(BLUR_RADIUS);
        theIntrinsic.setInput(tmpIn);
        theIntrinsic.forEach(tmpOut);
        tmpOut.copyTo(outputBitmap);

        return outputBitmap;
    }
}

As you can see the class exposes a static method, "blur", that takes the original Bitmap as a parameter and returns the blurred version of the image.
You can adjust the constants BITMAP_SCALE and BLUR_RADIUS to control the amount of blurriness.

Blurring the image

Now, if you have a Bitmap you can blur it using the following code (remeber to do this in a separate thread to avoid locking the UI):
Bitmap origBitmap = ...
Bitmap blurredBitmap = BlurBuilder.blur(mContext, origBitmap);
myImageView.setImageBitmap(blurredBitmap );


Monday, 5 October 2015

Managing AsyncTasks on configuration changes

The problem

Suppose you have an AsyncTask performing some task in the background (downloading data from a web service, updating an online database, etc.). If the user rotates the device, as you probably know, the current Activity is destroyed and recreated (the callback methods onDestroy and onCreate are invoked).

As a result, when the AsyncTask finishes its task and should deliver its results, the original Activity may no longer exist or it could have been replaced by a brand new Activity. However the AsyncTask is tied to the original Activity and its onPostExecute method won’t work with the newly created Activity. The newly created Activity may even start another AsyncTask (like in our example, see below), thus wasting system resources.

That’s why, as a general rule, you should always perform network operations in a Service: the Service’s lifecycle isn’t directly tied to the Activity lifecycle; a Service is not destroyed and recreated on configuration changes, like AsyncTasks do.
However AsyncTasks are generally easier and quicker to program than Services, so let’s examine some possibile solutions to our “configuration changes problem” using AsyncTasks.

Code

You can download the code for this tutorial from the Android – The Techinal Blog Githubrepository.

The easy solution

A very easy solution to our problem is preventing the Activity from being destroyed and recreated on configuration changes. For example, if you use the same layout for portrait and landscape orientation there is no need to destroy and recreate the Activity when the user rotates the device.

To achieve this, just insert the following line in the AndroidManifest.xml file under the Activity tag:
android:configChanges="orientation|screenSize|keyboardHidden”
This way, when the user rotates the device, the Activity is not destroyed and recreated anymore; conversely the method onConfigurationChanged gets called and you can override it if you need it.

The correct solution

The correct solution to the “configuration change problem” is using a so called “retained Fragment”.
A Fragment represents a behavior or a portion of the user interface within an Activity. Fragment’s life cycle is generally coordinated with the lifecycle of its containing Activity: when the Activity is destroyed on configuration changes all the contained Fragments get destroyed too.

However if you call setRetainInstance(true) within the Fragment class the destroy-and-recreated cycle of the Fragment is bypassed. As a result you can use a “retained Fragment” to hold active objects, like the AsyncTasks, Sockets, etc.


Let’s start with the retained Fragment:
/**
 * This Fragment performs a specific background task and is not
 * destroyed on configuration changes.
 */
public class RetainedFragment extends Fragment {
    /**
     * Interface used by the retained Fragment to communicate with
     * the Activity.
     */
    interface RetainedFragmentCallbacks {
        void onPreExecute();

        void onProgressUpdate(int progress);

        void onCancelled();

        void onPostExecute();
    }

    private RetainedFragmentCallbacks retainedFragmentCallbacks;
    private MyAsyncTask myAsyncTask;

    /**
     * Hold a reference to the parent Activity so we can report the
     * task's current progress and results (the Activity must implement
     * the RetainedFragmentCallbacks interface to receive the data sent
     * by this Fragment).
     * On configuration changes the Android framework passes to this
     * method a reference to the newly created Activity. This way
     * the AsyncTask can deliver its results to the new Activity.
     */
    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
        retainedFragmentCallbacks = (RetainedFragmentCallbacks) activity;
    }

    /**
     * This method gets invoked when the Fragment is created for
     * first time.
     */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // This Fragment won’t be destroyed on configuration changes.
        setRetainInstance(true);

        // Create and execute the background task.
        myAsyncTask = new MyAsyncTask();
        myAsyncTask.execute();
    }

    /**
     * Set the callback to null so we don't accidentally leak the
     * Activity instance.
     */
    @Override
    public void onDetach() {
        super.onDetach();
        retainedFragmentCallbacks = null;
    }

    /**
     * This AsyncTask performs a long task in the background
     * (we fake it with a sleep) and communicates progress and
     * results to the containing Activity.
     * In each method we check that retainedFragmentCallbacks is
     * not null because the Activity may have been destroyed on
     * configuration changes or because the user exits the Activity
     * pressing the back button.
     */
    private class MyAsyncTask extends AsyncTask {

        @Override
        protected void onPreExecute() {
            if (retainedFragmentCallbacks != null) {
                retainedFragmentCallbacks.onPreExecute();
            }
        }

        /**
         * Note that we do NOT call the callback object's methods
         * directly from the background thread, as this could result
         * in a race condition.
         */
        @Override
        protected Void doInBackground(Void... ignore) {
            for (int i = 0; !isCancelled() && i < 10; i++) {
                SystemClock.sleep(1000);
                publishProgress(i);
            }
            return null;
        }

        @Override
        protected void onProgressUpdate(Integer... progress) {
            if (retainedFragmentCallbacks != null) {
                retainedFragmentCallbacks.onProgressUpdate(progress[0]);
            }
        }

        @Override
        protected void onCancelled() {
            if (retainedFragmentCallbacks != null) {
                retainedFragmentCallbacks.onCancelled();
            }
        }

        @Override
        protected void onPostExecute(Void ignore) {
            if (retainedFragmentCallbacks != null) {
                retainedFragmentCallbacks.onPostExecute();
            }
        }
    }
}

And now the code of the main Activity:
/**
 * This Activity creates a RetainedFragment to perform a background
 * task, and receives progress updates and results from the
 * Fragment when they occur.
 */
public class MainActivity extends AppCompatActivity implements RetainedFragment. RetainedFragmentCallbacks {

    private static final String TAG_RETAINED_FRAGMENT = "RETAINED FRAGMENT";
    private RetainedFragment retainedFragment;
    private TextView textView;

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

        textView = (TextView) findViewById(R.id.textView);

        FragmentManager fm = getFragmentManager();
        retainedFragment = (RetainedFragment) fm.findFragmentByTag(TAG_RETAINED_FRAGMENT);

        // If the Fragment is not null, then it is currently being
        // retained across a configuration change.
        if (retainedFragment == null) {
            retainedFragment = new RetainedFragment();
            fm.beginTransaction().add(retainedFragment, TAG_RETAINED_FRAGMENT).commit();
            Log.d(TAG_RETAINED_FRAGMENT, "Retained Fragment created anew");
        }
        else {
            Log.d(TAG_RETAINED_FRAGMENT, "Retained Fragment retained on configuration change");
        }
    }

    // The four methods below are called by the RetainedFragment when new
    // progress updates or results are available. The MainActivity
    // should respond by updating its UI to indicate the change.

    @Override
    public void onPreExecute() {
        Log.d(TAG_RETAINED_FRAGMENT, "onPreExecute() received...");
        textView.setText("onPreExecute() received...");
    }

    @Override
    public void onProgressUpdate(int progress) {
        Log.d(TAG_RETAINED_FRAGMENT, "onProgressUpdate received with progress: " + progress);
        textView.setText("onProgressUpdate received with progress: " + progress);
    }

    @Override
    public void onCancelled() {
        Log.d(TAG_RETAINED_FRAGMENT, "onCancelled() received...");
        textView.setText("onCancelled() received...");
    }

    @Override
    public void onPostExecute() {
        Log.d(TAG_RETAINED_FRAGMENT, "onPostExecute() received...");
        textView.setText("onPostExecute() received...");
    }


}

The code is quite self-explanatory.

When the Activity is created for the first time the method findFragmentByTag returns null, since no Fragment has already been created. As a result a new instance of the RetainedFragment class is created and attached to the main Activity. The main Activity implements RetainedFragment.RetainedFragmentCallbacks interface and is registered to receive updates from the Fragment in the method onAttach.

When the Fragment is created setRetainInstance(true) ensures that it won’t be destroyed on configuration changes. In addition to that the Fragment creates and starts an AsyncTask, defined and managed inside the Fragment class, to perform a long lasting task in the background (for example downloading data from a web service).
Progress updates and final results are delivered to the main Activity through the RetainedFragment.RetainedFragmentCallbacks interface, which is implemented in the Activity (see the logs).

Now let’s suppose that the user rotates the device. This is what happens:

  • the RetainedFragment is not destroyed (because we have called setRetainInstance(true) when the Fragment was created) and the AsyncTask continues to work in the background;
  • the main Activity is destroyed and recreated as usual. When it’s destroyed it’s also detached from the RetainedFragment and the retainedFragmentCallbacks variable inside the Fragment class is set to null as a result. When the Activity is recreated it’s re-attached to the existing Fragment and the retainedFragmentCallbacks variable inside the Fragment is now set to point to the newly created Activity: results and progress updates are therefore delivered to this new Activity, and not to the old one (which doesn’t exist anymore). Notice that the RetainedFragment itself is not recreated because the method findFragmentByTag in onCreate now returns the existing Fragment.

Monday, 23 June 2014

Ordered Broadcasts

There are two types of broadcasts in Android: normal and ordered. The following table shows the main differences:


Normal
Ordered
Way of delivery
Normal broadcasts are delivered to the available receivers asynchronously, in an unspecified order
Ordered broadcasts are delivered to the available receivers one at a time, in a specified order (the order depends on the android:priority attribute of the different receivers in the AndroidManifest file)
Feedback
With normal broadcasts no feedback can be sent to the broadcaster
With ordered broadcasts the receiver can send information to the broadcaster (using the methods abortBroadcast(), seResultCode(), setResultData()


Tip: in a receiver (handling ordered broadcasts) you can call the method abortBroadcast() to make sure that the broadcast is not sent to other receivers. If you combine this method with a high value for the android:priority attribute, you can make sure that your receiver is the only one to handle that broadcast (SMS apps can use this technique).

BroadcastReceiver in Android

BroadcastReceiver

Let’s see how a BroadcastReceiver can handle ordered broadcasts (se the comments in the code for more information):
public class MyReceiver extends BroadcastReceiver {
    [...]
    public void onReceive(Context context, Intent intent) {
        //is this an ordered broadcast or not?
        if(isOrderedBroadcast() {
            //here you can handle the broadcast    
            [...]

            //here you can send information back to the broadcaster
            setResultCode(Activity.RESULT_OK);
            setResultData(“here you can pass a String”);

            //you can also create complex data to send to the broadcaster
            Bundle myBundle = getResultExtras(true);
            myBundle.put [...] //code omitted for brevity
        }
    }
}


Broadcaster

Sending an ordered broadcast is quite simple. Let’s look at the code:
Intent int = new Intent(YOUR_FILTER);
sendOrderedBroadcast(int, responseReceiver, null, RESULT_OK, null, null);
As you can see you just have to create an Intent with the filter registered for the BroadcastReceiver MyReceiver and call the method sendOrderedBroadcast. This method takes a BroadcastReceiver (responseReceiver) as a parameter: this is the receiver that will receive the information sent back by the BroadcastReceiver MyReceiver.
So you finally have to register the BroadcastReceiver responseReceiver (to handle the results) in the following way:
BroadcastReceiver responseReceiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
        //here you can retrieve the results sent by MyReceiver
        String str = getResultData();

        //here you can retrieve the complex data sent by MyReceiver
        Bundle myBundle = getResultExtras(false);
        if(myBundle != null) {
            //here you can retrieve the data using myBundle.get... methods
        }
    }
}