Wednesday, March 27, 2013

Stop IntentService

I have numbers of post about IntentService before; include Perform background processing with IntentService, Share IntentService among Fragments, Send data from IntentService to Activity, via additional Broadcast and Generate Notification in IntentService. This post is a good exercise to understand the life-cycle of IntentService.

To stop a IntentService, call the method stopService (Intent service). It request that a given application service be stopped. If the service is not running, nothing happens. Otherwise it is stopped. Note that calls to startService() are not counted -- this stops the service no matter how many times it was started. So imple? not at all.

In this exercise, buttons are added to start and stop IntentService. It can be noted that:
  • If you click the "Start IntentService" multi times, only one request will be processed at a time, All requests are handled on a single worker thread. The extra requests will be place in a queue.
  • If you click the "Start IntentService" multi times, only ONE call of stopService() is need to stop all request.
  • If you remove the checking on the boolean stopped, in onHandleIntent() of MyIntentService.java; call stopService() will call onDestroy() of MyIntentService, but the code in onHandleIntent() will keep running until finish by itself. Because onHandleIntent() is running on another worker thread.

Stop IntentService


Layout file
<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="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:orientation="vertical"
tools:context=".MainActivity" >

<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/hello_world" />
<Button
android:id="@+id/start"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Start IntentService" />
<Button
android:id="@+id/stop"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Stop IntentService" />
<TextView
android:id="@+id/result"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<ProgressBar
android:id="@+id/progressbar"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
style="?android:attr/progressBarStyleHorizontal"
android:max="10"
android:progress="0"/>

</LinearLayout>


MainActivity.java
package com.example.androidintentservice;

import android.os.Bundle;
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ProgressBar;
import android.widget.TextView;

public class MainActivity extends Activity {

Button buttonStart, buttonStop;
TextView textResult;
ProgressBar progressBar;

private MyBroadcastReceiver myBroadcastReceiver;
private MyBroadcastReceiver_Update myBroadcastReceiver_Update;

Intent intentMyIntentService;
int numberOfIntentService;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textResult = (TextView)findViewById(R.id.result);
progressBar = (ProgressBar)findViewById(R.id.progressbar);
buttonStart = (Button)findViewById(R.id.start);
buttonStop = (Button)findViewById(R.id.stop);

buttonStart.setOnClickListener(new OnClickListener(){

@Override
public void onClick(View arg0) {
numberOfIntentService++;

//prepare String passing to intentMyIntentService
String msgToIntentService = "Android-er: " + numberOfIntentService;

//Start MyIntentService
intentMyIntentService = new Intent(MainActivity.this, MyIntentService.class);
intentMyIntentService.putExtra(MyIntentService.EXTRA_KEY_IN, msgToIntentService);
startService(intentMyIntentService);
}});

buttonStop.setOnClickListener(new OnClickListener(){

@Override
public void onClick(View arg0) {
if(intentMyIntentService != null){
stopService(intentMyIntentService);
intentMyIntentService = null;
}
}});

numberOfIntentService = 0;

myBroadcastReceiver = new MyBroadcastReceiver();
myBroadcastReceiver_Update = new MyBroadcastReceiver_Update();

//register BroadcastReceiver
IntentFilter intentFilter = new IntentFilter(MyIntentService.ACTION_MyIntentService);
intentFilter.addCategory(Intent.CATEGORY_DEFAULT);
registerReceiver(myBroadcastReceiver, intentFilter);

IntentFilter intentFilter_update = new IntentFilter(MyIntentService.ACTION_MyUpdate);
intentFilter_update.addCategory(Intent.CATEGORY_DEFAULT);
registerReceiver(myBroadcastReceiver_Update, intentFilter_update);
}

@Override
protected void onDestroy() {
super.onDestroy();
//un-register BroadcastReceiver
unregisterReceiver(myBroadcastReceiver);
unregisterReceiver(myBroadcastReceiver_Update);
}

public class MyBroadcastReceiver extends BroadcastReceiver {

@Override
public void onReceive(Context context, Intent intent) {
String result = intent.getStringExtra(MyIntentService.EXTRA_KEY_OUT);
textResult.setText(result);
}
}

public class MyBroadcastReceiver_Update extends BroadcastReceiver {

@Override
public void onReceive(Context context, Intent intent) {
int update = intent.getIntExtra(MyIntentService.EXTRA_KEY_UPDATE, 0);
progressBar.setProgress(update);
}
}

}


MyIntentService.java
package com.example.androidintentservice;

import android.app.IntentService;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.support.v4.app.NotificationCompat;
import android.widget.Toast;

public class MyIntentService extends IntentService {

private static final int MY_NOTIFICATION_ID=1;
private static final int MY_DESTORY_NOTIFICATION_ID=2;
NotificationManager notificationManager;
Notification myNotification;

public static final String ACTION_MyIntentService = "com.example.androidintentservice.RESPONSE";
public static final String ACTION_MyUpdate = "com.example.androidintentservice.UPDATE";
public static final String EXTRA_KEY_IN = "EXTRA_IN";
public static final String EXTRA_KEY_OUT = "EXTRA_OUT";
public static final String EXTRA_KEY_UPDATE = "EXTRA_UPDATE";
String msgFromActivity;
String extraOut;

boolean success;
boolean stopped;

public MyIntentService() {
super("com.example.androidintentservice.MyIntentService");
success = false;
stopped = false;
}

@Override
protected void onHandleIntent(Intent intent) {

//get input
msgFromActivity = intent.getStringExtra(EXTRA_KEY_IN);
extraOut = "Hello: " + msgFromActivity;

//total 10 sec
for(int i = 0; i <=10; i++){

try {
Thread.sleep(1000); //every 1 sec
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

//--- Try to comment it ---//
if(stopped){
break;
}

//send update
Intent intentUpdate = new Intent();
intentUpdate.setAction(ACTION_MyUpdate);
intentUpdate.addCategory(Intent.CATEGORY_DEFAULT);
intentUpdate.putExtra(EXTRA_KEY_UPDATE, i);
sendBroadcast(intentUpdate);

PendingIntent pendingIntent_doNothing = PendingIntent.getActivity(
getApplicationContext(),
0,
new Intent(), //empty Intent do nothing
Intent.FLAG_ACTIVITY_NEW_TASK);

//generate notification
String notificationText = String.valueOf((int)(100 * i / 10)) + " %";
myNotification = new NotificationCompat.Builder(getApplicationContext())
.setContentTitle("Progress")
.setContentText(notificationText)
.setTicker("Notification!")
.setWhen(System.currentTimeMillis())
.setDefaults(Notification.DEFAULT_SOUND)
.setAutoCancel(true)
.setSmallIcon(R.drawable.ic_launcher)
.setContentIntent(pendingIntent_doNothing)
.build();

notificationManager.notify(MY_NOTIFICATION_ID, myNotification);
}

success = true;
myNotification = new NotificationCompat.Builder(getApplicationContext())
.setContentTitle("Success Finished")
.setContentText("Successful Finished")
.setTicker("Successful Finished")
.setWhen(System.currentTimeMillis())
.setDefaults(Notification.DEFAULT_SOUND)
.setAutoCancel(true)
.setSmallIcon(R.drawable.ic_launcher)
.build();
notificationManager.notify(MY_NOTIFICATION_ID, myNotification);

//return result
Intent intentResponse = new Intent();
intentResponse.setAction(ACTION_MyIntentService);
intentResponse.addCategory(Intent.CATEGORY_DEFAULT);
intentResponse.putExtra(EXTRA_KEY_OUT, extraOut);
sendBroadcast(intentResponse);
}

@Override
public void onCreate() {
super.onCreate();
notificationManager = (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);
}

@Override
public void onDestroy() {
Notification onDestroyNotification;
String notice;

stopped = true;

if(success){
notice = "onDestroy with success";
onDestroyNotification = new NotificationCompat.Builder(getApplicationContext())
.setContentTitle(notice)
.setContentText(msgFromActivity)
.setTicker(notice)
.setWhen(System.currentTimeMillis())
.setDefaults(Notification.DEFAULT_SOUND)
.setAutoCancel(true)
.setSmallIcon(R.drawable.ic_launcher)
.build();
}else{
notice = "onDestroy WITHOUT success!";
onDestroyNotification = new NotificationCompat.Builder(getApplicationContext())
.setContentTitle(notice)
.setContentText(msgFromActivity)
.setTicker(notice)
.setWhen(System.currentTimeMillis())
.setDefaults(Notification.DEFAULT_SOUND)
.setAutoCancel(true)
.setSmallIcon(R.drawable.ic_launcher)
.build();
}
notificationManager.notify(MY_DESTORY_NOTIFICATION_ID, onDestroyNotification);
Toast.makeText(getApplicationContext(), notice, Toast.LENGTH_LONG).show();

super.onDestroy();
}

}


Need to include <service> of "MyIntentService" in AndroidManifest.xml, refer to the post "Send data from IntentService to Activity, via additional Broadcast".


download filesDownload the files.

No comments:

Post a Comment