1、下面介绍Service和AsyncTask的用法和比较。
Service没有界面,用于执行一个需要在后台长期运行的任务。AsyncTask用于执行短时间的异步任务,并跟UI线程交互,用于替代Thread和Handler。
1) MainActivity.java
public class MainActivity extends Activity {
private static final String TAG = MainActivity.class.getSimpleName();
/**便于多次、多地调用,生命周期伴随Activity*/
Intent intent;
@Override
protected void onCreate(Bundle savedInstanceState) {
Log.i(TAG, "onCreate");
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// mAsyncTask.execute("http://www.qinuli.com:83/picture/thumb.jpg", "http://www.qinuli.com:83/picture/hand_in_hand.jpg");
intent = new Intent(this, MyService.class);
}
protected void onDestroy() {
Log.d(TAG, "onDestroy");
super.onDestroy();
};
/**
* 定义一个AsyncTask的子类;实例化并在UI线程调用其execute方法
* <li>3个参数:Params、Progress、Result
* <li>4 steps:onPreExecute->doInBackground->onProgressUpdate->onPostExecute
* <li>功能:用于后台执行前台显示的任务
* <li>意义:代替或封装Thread和Handler,方便后台线程和UI线程交互
*/
AsyncTask<String, Integer, CharSequence> mAsyncTask = new AsyncTask<String, Integer, CharSequence>() {
@Override
protected void onPreExecute() {
Log.d(TAG, "onPreExecute");
};
@Override
protected CharSequence doInBackground(String... params) {
//perform a computation on a background thread
for(int i=0;i<params.length;i++){
publishProgress(Integer.valueOf(i));
}
return "加油!";
}
@Override
protected void onProgressUpdate(Integer... values) {
Log.d(TAG, "onProgressUpdate-"+values[0]);
};
@Override
protected void onPostExecute(CharSequence result) {
Log.d(TAG, "onPostExecute-"+result);
};
};
private ServiceConnection mServiceConnection = new ServiceConnection() {
@Override
public void onServiceDisconnected(ComponentName name) {
Log.d(TAG, "onServiceDisconnected-"+name.getClassName());
}
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
//由bindService触发,在onBind之后
MyService myService = ((MyBinder)service).getService();
Log.d(TAG, "onServiceConnected-"+name.getClassName()+"-"+myService.name);
}
};
public void onClick(View v){
switch (v.getId()) {
case R.id.btn_startService:
//调用Service的空参构造
startService(intent);
break;
case R.id.btn_stopService:
stopService(intent);
break;
case R.id.btn_bindService:
bindService(intent, mServiceConnection, Context.BIND_AUTO_CREATE);
break;
case R.id.btn_unbindService:
unbindService(mServiceConnection);
}
}
}
2) activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
xmlns:android="http://schemas.android.com/apk/res/android">
<Button
android:id="@+id/btn_startService"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="onClick"
android:text="startService"/>
<Button
android:id="@+id/btn_stopService"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="onClick"
android:text="stopService"/>
<Button
android:id="@+id/btn_bindService"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="onClick"
android:text="bindService"/>
<Button
android:id="@+id/btn_unbindService"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="onClick"
android:text="unbindService"/>
</LinearLayout>
3) MyService.java,讲解startService和bindService的原理
/**
* <li>Service的意义:perform a longer running operation
* <li>Service和AsyncTask的区别:Service运行在主线程,不会结束
*/
public class MyService extends Service {
private static final String TAG = MyService.class.getSimpleName();
private MyBinder myBinder = new MyBinder();
public String name = "ShiXin";
public MyService(){
super();
Log.d(TAG, "MyService");
}
/**继承Binder类,Binder类实现IBinder接口。实例化该类供onBind使用*/
public class MyBinder extends Binder{
/**返回Service的实例,进而调用其方法和属性,实现一些数据通信和功能操作*/
public MyService getService(){
return MyService.this;
}
}
@Override
public IBinder onBind(Intent intent) {
Log.d(TAG, "onBind");
//由bindService触发
return myBinder;
}
@Override
public boolean onUnbind(Intent intent) {
Log.d(TAG, "onUnbind");
return super.onUnbind(intent);
}
@Override
public void onCreate() {
Log.d(TAG, "onCreate");
//重新实例化新的Service
super.onCreate();
}
public void onDestroy() {
Log.d(TAG, "onDestroy");
super.onDestroy();
};
@Override
public void onStart(Intent intent, int startId) {
//deprecated 被onStartCommand代替
super.onStart(intent, startId);
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
//每次startService都会触发,bindService不会触发
//startId:unique integer token,标记每次startService,Service创建后从1开始计数
//START_STICKY_COMPATIBILITY 0;Service.START_STICKY 1
stopSelfResult(3);//onStartCommand执行3次
int state = super.onStartCommand(intent, flags, startId);
Log.d(TAG, "onStartCommand-"+intent.getComponent().getClassName()+"-"+flags+"-"+startId+"-"+state);
return state;//1
}
}
4) MyIntentService.java,IntentService用于在后台线程执行异步任务,执行完Service自动destroy
/**
* handle asynchronous requests
*/
public class MyIntentService extends IntentService {
private static final String TAG = MyIntentService.class.getSimpleName();
public MyIntentService() {
//name worker thread
super("worker thread");
}
@Override
protected void onHandleIntent(Intent intent) {
//代替onStartCommand;执行完调用stopSelf()
Log.d(TAG, Thread.currentThread().getName()+"-onHandleIntent");
}
@Override
public void onCreate() {
Log.d(TAG, "onCreate");
super.onCreate();
}
@Override
public void onDestroy() {
Log.d(TAG, "onDestroy");
super.onDestroy();
}
}
5) AndroidManifest.xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.qinuli.testproject"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="19" />
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity android:name="com.qinuli.testproject.MainActivity">
<intent-filter >
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<service android:name="com.qinuli.testproject.MyService"></service>
<service android:name="com.qinuli.testproject.MyIntentService"></service>
</application>
</manifest>
2、如何让服务永久运行
本示例介绍了TIME_TICK和BOOT_COMPLETED广播的用法
public class MainActivity extends Activity {
private static final String TAG = MainActivity.class.getSimpleName();
@Override
protected void onCreate(Bundle savedInstanceState) {
Log.d(TAG, "onCreate");
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
@Override
protected void onDestroy() {
Log.d(TAG, "onDestroy");
super.onDestroy();
}
public void onClick(View v){
switch(v.getId()){
case R.id.btn_killProcess:
Process.killProcess(Process.myPid());
}
}
}
MyService.java
public class MyService extends Service {
private static final String TAG = MyService.class.getSimpleName();
private MyBinder myBinder = new MyBinder();
public class MyBinder extends Binder{
public MyService getService(){
return MyService.this;
}
}
@Override
public IBinder onBind(Intent intent) {
return myBinder;
}
@Override
public void onCreate() {
Log.d(TAG, "onCreate");
super.onCreate();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d(TAG, "onStartCommand");
//进程被杀死,服务会重建
return Service.START_STICKY;
}
@Override
public void onDestroy() {
Log.d(TAG, "onDestroy");
super.onDestroy();
}
}
MyApplication.java
public class MyApplication extends Application {
private static final String TAG = MyApplication.class.getSimpleName();
MyService myService;
Intent intent;
@Override
public void onCreate() {
Log.d(TAG, "onCreate");
super.onCreate();
intent = new Intent(this, MyService.class);
startService(intent);
bindService(intent, mServiceConnection, Context.BIND_AUTO_CREATE);
registerReceiver(new TimeTickReceiver(), new IntentFilter(Intent.ACTION_TIME_TICK));
}
@Override
public void onTerminate() {
Log.d(TAG, "onTerminate");
super.onTerminate();
stopService(intent);
//禁用一个manifest receiver,可禁用清单文件里注册的四大组件
ComponentName componentName = new ComponentName(this, BootCompletedReceiver.class);
PackageManager pm = getPackageManager();
pm.setComponentEnabledSetting(componentName, PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
PackageManager.DONT_KILL_APP);
}
private ServiceConnection mServiceConnection = new ServiceConnection() {
@Override
public void onServiceDisconnected(ComponentName name) {
myService = null;
}
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
Log.d(TAG, "onServiceConnected");
myService = ((MyBinder)service).getService();
}
};
}
BootCompleteReceiver.java
public class BootCompletedReceiver extends BroadcastReceiver {
private static final String TAG = BootCompletedReceiver.class.getSimpleName();
public BootCompletedReceiver(){
super();
Log.d(TAG, "BootCompletedReceiver");
}
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
Log.d(TAG, action);
if (Intent.ACTION_BOOT_COMPLETED.equals(action)) {
//清单文件注册,开机可收到广播
boolean isServiceRunning = false;
ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
for(RunningServiceInfo runningServiceInfo:activityManager.getRunningServices(Integer.MAX_VALUE)){
if(MyService.class.getName().equals(runningServiceInfo.service.getClassName())){
isServiceRunning = true;
}
}
if(!isServiceRunning){
ComponentName comp = new ComponentName(context.getPackageName(), MyService.class.getName());
context.startService(new Intent().setComponent(comp));
}
}else if(ConnectivityManager.CONNECTIVITY_ACTION.equals(action)){
//在清单文件注册,退出APP或杀死进程依然能收到广播,但清掉内存就收不到了
ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo = cm.getActiveNetworkInfo();
if(networkInfo!=null)
Log.d(TAG, "networkstate:"+networkInfo.isConnectedOrConnecting()+"-"+(networkInfo.getType()==ConnectivityManager.TYPE_MOBILE));
}
}
}
TimeTickReceiver.java
public class TimeTickReceiver extends BroadcastReceiver {
private static final String TAG = TimeTickReceiver.class.getSimpleName();
public TimeTickReceiver(){
super();
Log.d(TAG, "TimeTickReceiver");
}
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
Log.d(TAG, action);
if (Intent.ACTION_TIME_TICK.equals(action)) {
boolean isServiceRunning = false;
//拿到所有正在运行的服务
ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
for(RunningServiceInfo runningServiceInfo:activityManager.getRunningServices(Integer.MAX_VALUE)){
if(MyService.class.getName().equals(runningServiceInfo.service.getClassName())){
isServiceRunning = true;
}
}
Log.d(TAG, "isServiceRunning="+isServiceRunning);
if(!isServiceRunning){
ComponentName comp = new ComponentName(context.getPackageName(), MyService.class.getName());
context.startService(new Intent().setComponent(comp));
}
}
}
}
AndroidManifest.xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.qinuli.servicetest"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="21" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<application
android:name="com.qinuli.servicetest.MyApplication"
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity android:name="com.qinuli.servicetest.MainActivity">
<intent-filter >
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<service android:name="com.qinuli.servicetest.MyService"
android:enabled="true"
android:exported="false"/>
<receiver
android:name="com.qinuli.servicetest.BootCompletedReceiver"
android:permission="android.permission.RECEIVE_BOOT_COMPLETED"
android:enabled="true" >
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
<action android:name="android.net.conn.CONNECTIVITY_CHANGE"/>
</intent-filter>
</receiver>
</application>
</manifest>