一、创建Service
1.创建一个myService类,来继承Service。重写其中的方法,包括:onCreate(),onStartCommend(),onDestroy(),onBind()方法是自动重载的。
1.1 onCreate():创建Service的时候调用,只调用一次。
1.2 onStartCommend():执行Service的时候调用,执行几次,调用几次。
1.3 onDestroy():在销毁Service的时候调用,只调用一次。
1.4 onBind():在bindService的时候调用。只调用一次。
1.2 myService代码如下:
package com.wangpei.service; import android.app.Service; import android.content.Intent; import android.os.Binder; import android.os.IBinder; import android.util.Log; /** * 作者:WangPei on 2015/7/9 09:48 * 邮箱:460977141@qq.com */ public class myService extends Service { private static final String TAG = "myInfo"; //需要返回Binder实例 private MyBinder myBinder = new MyBinder(); @Override public IBinder onBind(Intent intent) { return myBinder; } @Override public void onCreate() { Log.i(TAG,"onCreate is excute"); super.onCreate(); } @Override public int onStartCommand(Intent intent, int flags, int startId) { Log.i(TAG,"onStartCommand is excute"); return super.onStartCommand(intent, flags, startId); } @Override public void onDestroy() { Log.i(TAG,"onDestroy is excute"); super.onDestroy(); } class MyBinder extends Binder{ public void startDownload(){ //模拟下载任务 Log.i(TAG,"startDownload is excute"); } } }
二、startService AND stopService
2.1 startService
2.1.1 代码如下:
1
2
|
Intent startIntent =
new
Intent(MainActivity.
this
,myService.
class
);
startService(startIntent);
|
2.1.2 调用myService类中的方法顺序如下:
onCreate() ---> onStartCommend() ---先创建Service,然后在执行。
2.2 stopService 代码如下:
2.2.1 代码如下:
Intent stopIntent = new Intent(MainActivity.this,myService.class); stopService(stopIntent);
2.2.2 调用myService类中的方法顺序如下:
onDestroy() --直接被销毁。
三、bindService AND unBindService
3.1 创建ServiceConnection:
//初始化myService中的binder private myService.MyBinder myBinder; private ServiceConnection connection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { myBinder = (myService.MyBinder) service; //启动下载任务 myBinder.startDownload(); } @Override public void onServiceDisconnected(ComponentName name) { } };
3.1.1 onServiceConnected()方法,是在Activity和Service建立连接的时候,进行调用。
3.1.1 onServiceDisconnected()方法,onServiceDisconnected()方法不是解除关联的时候调用,而是发生异常时调用的。
3.2 bindService 代码如下:
Intent bindIntent = new Intent(MainActivity.this,myService.class); bindService(bindIntent,connection,BIND_AUTO_CREATE);
3.2.1 BIND_AUTO_CREATE:意思是在绑定Service的时候,进行自动创建。
3.3 unBindService 代码如下:
unbindService(connection);
3.4 注意 如果同时startService和bindService,必须要stopService和unBindService,才能onDestroy()该Service。
3.5 额外的东西
楼主文中是有说明Service和Activity是如何通信的;首先在自定义的Service类中覆盖onBind(Intent intent)方法,返回一个Binder子类的对象,在自定义的Binder子类中可以定义一些方法;然后再Activity创建个ServiceConnection对象,并实现其onServiceConnected(ComponentName name, IBinder service) 方法,在这个方法中将传入的IBinder对象强转为在Service中定义的Binder子类,这样就拿到了Service中的某个对象的引用了,想怎通信都行;但要使onServiceConnected方法被回调,还需要调用bindService方法,把ServiceConnection的对象当作参数传过去......
四、Service AND Thread 的关系
4.1 Service
4.1.1 Service旨在后台运行,并且Service也是在主线程中运行的。
4.1.2 Service就不同了,所有的Activity都可以与Service进行关联,然后可以很方便地操作其中的方法,即使Activity被销毁了,之后只要重新与Service建立关联,就又能够获取到原有的Service中Binder的实例。
4.1.3 使用Service来处理后台任务,Activity就可以放心地finish,完全不需要担心无法对后台任务进行控制的情况。
4.1.4 我们可以在Service中再创建一个子线程,然后在这里去处理耗时逻辑就没问题了。
4.1.5 较为标准的Service写法:
private MyBinder myBinder;
@Override
public Binder onBind(Intent intent){
return myBinder;
}
@Override public int onStartCommand(Intent intent, int flags, int startId) { new Thread(new Runnable() { @Override public void run() { // 开始执行后台任务 } }).start(); return super.onStartCommand(intent, flags, startId); } class MyBinder extends Binder { public void startDownload() { new Thread(new Runnable() { @Override public void run() { // 执行具体的下载任务 } }).start(); } }
4.2 Thread
4.2.1 Thread是在子线程中运行的,旨在不影响主线程的运行。
4.2.2 Activity很难对Thread进行控制,当Activity被销毁之后,就没有任何其它的办法可以再重新获取到之前创建的子线程的实例;
五、前台Service
5.1 需要在通知栏显示,点击之后,可以跳转到Activity。优点,可以保持持续的运行。比如说墨迹天气,它的Service在后台更新天气数据的同时,还会在系统状态栏一直显示当前天气的信息。具体实现如下:
public class MyService extends Service { public static final String TAG = "MyService"; private MyBinder mBinder = new MyBinder(); @Override public void onCreate() { super.onCreate(); //先定义通知 Notification notification = new Notification(R.drawable.ic_launcher, "有通知到来", System.currentTimeMillis()); //跳转意图 Intent notificationIntent = new Intent(this, MainActivity.class); //将意图转换为等待意图 PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0); //初始化通知 notification.setLatestEventInfo(this, "这是通知的标题", "这是通知的内容", pendingIntent); //然后调用startForeground()方法就可以让MyService变成一个前台Service,并会将通知的图片显示出来。 startForeground(1, notification); Log.d(TAG, "onCreate() executed"); } ......... }
六、远程Service
6.1 远程Service介绍:
在注册service的时候,添加属性:remote即可激活远程service。远程service,是不同有主进程的service。直接可以在内部执行耗时操作,并且不影响主进程的使用。但是,有一个弊端。远程service没有办法和Activity进行绑定。因为,远程service是不同于应用程序主进程的进程,他们之间无法建立连接的。
那么如何,才能使Activity和远程service建立连接呢?这里我们需要使用AIDL。接口定义语言来实现跨进程通信技术。
6.2 AIDL(android interface definition language)的使用:
6.2.1 使用方法,先建立一个后缀为AIDL的文件,这是一个接口文件。然后进行编译。系统会自动生成一个java文件。然后我们就可以进行使用了。
// IMyAidlInterface.aidl package com.wangpei.service; // Declare any non-default types here with import statements interface IMyAidlInterface { /** * Demonstrates some basic types that you can use as parameters * and return values in AIDL. */ int plus(int a, int b); String toUpperCase(String str); }
6.2.2 然后进行编译,系统会自动生成一个相应的java文件。此时,我们就可以使用它了。
在MyService中进行使用(对aidl中的方法,进行重写。):
package com.wangpei.service; import android.app.Notification; import android.app.PendingIntent; import android.app.Service; import android.content.Intent; import android.os.Binder; import android.os.IBinder; import android.os.RemoteException; import android.util.Log; /** * 作者:WangPei on 2015/7/9 09:48 * 邮箱:460977141@qq.com */ public class myService extends Service { private static final String TAG = "myInfo"; private MyBinder myBinder = new MyBinder(); @Override public IBinder onBind(Intent intent) { return mBinder; } IMyAidlInterface.Stub mBinder = new IMyAidlInterface.Stub() { @Override public int plus(int a, int b) throws RemoteException { return a+b; } @Override public String toUpperCase(String str) throws RemoteException { if(str != null){ return str.toUpperCase(); }else { return null; } } }; @Override public void onCreate() { Log.i(TAG,"onCreate is excute"); // Log.i(TAG,"myService thread is :"+Thread.currentThread().getName()); /** * 前台Service的使用 */ // Notification notification = new Notification(R.drawable.ic_launcher,"这是通知的内容",System.currentTimeMillis()); // Intent notificationIntent = new Intent(this,MainActivity.class); // PendingIntent pendingIntent = PendingIntent.getActivity(this,0,notificationIntent,0); // notification.setLatestEventInfo(this,"这是通知的标题","这是主要内容",pendingIntent); // startForeground(1,notification); super.onCreate(); } @Override public int onStartCommand(Intent intent, int flags, int startId) { Log.i(TAG,"onStartCommand is excute"); return super.onStartCommand(intent, flags, startId); } @Override public void onDestroy() { Log.i(TAG,"onDestroy is excute"); super.onDestroy(); } class MyBinder extends Binder{ public void startDownload(){ Log.i(TAG,"startDownload is excute"); } } }
6.2.3 最后在Activity中进行调用,即可,使用Aidl中,所定义的方法。
private ServiceConnection connection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { // myBinder = (myService.MyBinder) service; // myBinder.startDownload(); iMyAidlInterface = IMyAidlInterface.Stub.asInterface(service); try { int result = iMyAidlInterface.plus(9,15); String str = iMyAidlInterface.toUpperCase("wang pei"); Log.i(TAG,result+""); Log.i(TAG,str); } catch (RemoteException e) { e.printStackTrace(); } }