Android Service讲解 和 aidl 实现
2016-11-10 16:46
453 查看
Android Service讲解 和 aidl 实现
代码下载 Android Service讲解 和 aidl 实现一、Android Service
1.建立一个service
service和activity很相识,只是service在后台运行,activity在前台运行,他们都属于同一个同一个线程里,都属于UI线程,所以service和Thread是完全不一样的东西。一些耗时的操作在Service里运行也要开辟新的线程。新建一个自己的service,只需要继承系统Service就行了,看下面代码:
public class AIDLService extends Service { private static final String TAG = "AIDLService"; @Override public void onCreate() { super.onCreate(); Log.i(TAG, "onCreate() called"); } @Override public int onStartCommand(Intent intent, int flags, int startId) { Log.i(TAG, "onStartCommand() called"); return super.onStartCommand(intent, flags, startId); } @Override public IBinder onBind(Intent intent) { Log.i(TAG, "onBind() called"); return stub; } @Override public boolean onUnbind(Intent intent) { Log.i(TAG, "onUnbind() called"); return true; } @Override public void onDestroy() { super.onDestroy(); Log.i(TAG, "onDestroy() called"); }
这样就建好了一个service,service建好了了,现在也并不能直接启动,也要像activity一样注册进AndroidManifest.xml中才能,运行它。
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="mangues.com.aidl_service"> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:supportsRtl="true" android:theme="@style/AppTheme"> <activity android:name=".MainActivity"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <service android:name=".AIDLService"> </service> </application> </manifest>
2、启动service
现在我们建好了service,也注册进AndroidManifest.xml中怎么才能运行他呢。有两种方式可以运行:startService 和 bindService
这两种方式的区别:
执行startService时,Service会经历onCreate->onStartCommand。当执行stopService时,直接调用onDestroy方法。调用者如果没有stopService,Service会一直在后台运行,下次调用者再起来仍然可以stopService。
执行bindService时,Service会经历onCreate->onBind。这个时候调用者和Service绑定在一起。调用者调用unbindService方法或者调用者Context不存在了(如Activity被finish了),Service就会调用onUnbind->onDestroy。这里所谓的绑定在一起就是说两者共存亡了。
多次调用startService,该Service只能被创建一次,即该Service的onCreate方法只会被调用一次。但是每次调用startService,onStartCommand方法都会被调用。Service的onStart方法在API 5时被废弃,替代它的是onStartCommand方法。
第一次执行bindService时,onCreate和onBind方法会被调用,但是多次执行bindService时,onCreate和onBind方法并不会被多次调用,即并不会多次创建服务和绑定服务。
2.1、startService
和startActivity一样使用就行了,停止的时候直接调用stopService 就行了。
@Override public void onClick(View view) { Intent startIntent = new Intent(this, AIDLService.class); switch (view.getId()){ case R.id.btn_start: startService(startIntent); break; case R.id.btn_stop: stopService(startIntent); break; case R.id.btn_bind: break; case R.id.btn_unbind: break; } }
多次点击start时,看打印日志
证明了
多次调用startService,该Service只能被创建一次,即该Service的onCreate方法只会被调用一次。但是每次调用startService,onStartCommand方法都会被调用。
2.1、bindService
1.这时候绑定的service会和该activity共存亡。不会单独存在。
2.利用该种方法绑定的service可以和activity交互,不单单只是启动。
看代码:
package mangues.com.aidl_service; import android.app.Service; import android.content.Intent; import android.os.Binder; import android.os.IBinder; import android.os.RemoteException; import android.util.Log; import java.util.Date; import mangues.com.aidl.IPerson; public class AIDLService extends Service { private static final String TAG = "AIDLService"; private MyBinder mBinder = new MyBinder(); @Override public void onCreate() { super.onCreate(); Log.i(TAG, "onCreate() called"); } @Override public int onStartCommand(Intent intent, int flags, int startId) { Log.i(TAG, "onBind() onStartCommand"); return super.onStartCommand(intent, flags, startId); } @Override public IBinder onBind(Intent intent) { Log.i(TAG, "onBind() called"); return mBinder; } @Override public boolean onUnbind(Intent intent) { Log.i(TAG, "onUnbind() called"); return true; } @Override public void onDestroy() { super.onDestroy(); Log.i(TAG, "onDestroy() called"); } class MyBinder extends Binder { public String getMyBinder() { Log.d(TAG, "MyBinder() called"); return new Date().getTime()+""; //获取时间 } } }
利用binder 把数据传出service给activity获取到,只要写个内部类 继承Binder,通过binder写个方法 在利用onBind把这个binder return出去,activity就可以获得这个binder进而得到方法getMyBinder,获得service中数据
Activity代码:
public class MainActivity extends AppCompatActivity implements View.OnClickListener{ private Button mBtnBind; private Button mBtnUnBind; private AIDLService.MyBinder myBinder; private ServiceConnection connection = new ServiceConnection() { @Override public void onServiceDisconnected(ComponentName name) { } @Override public void onServiceConnected(ComponentName name, IBinder service) { myBinder = (AIDLService.MyBinder) service; String time = myBinder.getMyBinder(); Log.i("MainActivity",time); } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); init(); } private void init(){ mBtnBind = (Button)findViewById(R.id.btn_bind); mBtnUnBind = (Button)findViewById(R.id.btn_unbind); mBtnBind.setOnClickListener(this); mBtnUnBind.setOnClickListener(this); } @Override public void onClick(View view) { Intent startIntent = new Intent(this, AIDLService.class); switch (view.getId()){ case R.id.btn_bind: Intent bindIntent = new Intent(this, AIDLService.class); //这里传入BIND_AUTO_CREATE表示在Activity和 //Service建立关联后自动创建Service,这会使得 //MyService中的onCreate()方法得到执行,但 //onStartCommand()方法不会执行。 bindService(bindIntent, connection, BIND_AUTO_CREATE); break; case R.id.btn_unbind: unbindService(connection); break; } } }
点击开始和结束 日志如下:
看第四行:activity 获取到了service中数据
3、注销service
第一种、startService stopService第二种、bindService unBindService
上面都好理解,那么如果我们既点击了startService按钮,又点击了bindService按钮会怎么样呢?
这个时候你会发现,不管你是单独点击stopService按钮还是unbindService按钮,Service都不会被销毁,必要将两个按钮都点击一下,Service才会被销毁。也就是说,点击Stop Service按钮只会让Service停止,点击Unbind Service按钮只会让Service和Activity解除关联,一个Service必须要在既没有和任何Activity关联又处理停止状态的时候才会被销毁。
看日志:
只执行stopService 或者 unbindService 根本没有注销
只有全部执行才会 注销
4.远程service
只要在service中注册信息中加上 android:process=”:remote” 就行了<service android:name=".AIDLService" android:process=":remote"> </service>
远程service有什么用呢?
远程service的作用只是重新建立一个新进程执行,可以独立出去。其他app可以调用这个service。因为是一个新的进程,所以也不能用bind来建立关联了。
可以用新的方式来建立关系就是下面要讲的aidl技术。
二、aidl实现
1.首先我建立2个app工程,通过aidl实现一个app调用另一个app的service
目录结构如下:service提供端app
利用aidl调用service的app
2.在两个app中都建立一个文件 IPerson.aidl注意 包名 要相同
IPerson.aidl只是一个接口文件,用来aidl交互的,建立好之后gradle一下就行了,studio会自动创建需要的文件,具体什么文件你不用管,我们用不到,你在代码里可以看到IPerson.aidl代码
package mangues.com.aidl; interface IPerson { String greet(String someone); }
3.在aidl_service 中建立AIDLService
这个IPerson.Stub 就是通过IPerson.aidl 自动生成的binder 文件,你实现下,然后onBind return出去就好了,就和Android Service实现和activity交互一样。代码:
public class AIDLService extends Service { private static final String TAG = "AIDLService"; IPerson.Stub stub = new IPerson.Stub() { @Override public String greet(String someone) throws RemoteException { Log.i(TAG, "greet() called"); return "hello, " + someone; } }; @Override public void onCreate() { super.onCreate(); Log.i(TAG, "onCreate() called"); } @Override public int onStartCommand(Intent intent, int flags, int startId) { Log.i(TAG, "onBind() onStartCommand"); return super.onStartCommand(intent, flags, startId); } @Override public IBinder onBind(Intent intent) { Log.i(TAG, "onBind() called"); return stub; } @Override public boolean onUnbind(Intent intent) { Log.i(TAG, "onUnbind() called"); return true; } @Override public void onDestroy() { super.onDestroy(); Log.i(TAG, "onDestroy() called"); } }
4.aidl_service MainActivity 中启动这个service
简单点就不写关闭什么的了;@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Intent startIntent = new Intent(this, AIDLService.class); startService(startIntent); }
在AndroidManifest.xml注册
<service android:name=".AIDLService" android:process=":remote"> <intent-filter> <action android:name="android.intent.action.AIDLService" /> <category android:name="android.intent.category.DEFAULT" /> </intent-filter> </service>
作用就是把这个service暴露出去,让别的APP可以利用
android.intent.action.AIDLService 字段隐形绑定这个service,获取数据。
5.aidl_client 中绑定aidl_service service 获取数据
代码:public class MainActivity extends AppCompatActivity { private IPerson person; private ServiceConnection conn = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { Log.i("ServiceConnection", "onServiceConnected() called"); person = IPerson.Stub.asInterface(service); String retVal = null; try { retVal = person.greet("scott"); } catch (RemoteException e) { e.printStackTrace(); } Toast.makeText(MainActivity.this, retVal, Toast.LENGTH_SHORT).show(); } @Override public void onServiceDisconnected(ComponentName name) { //This is called when the connection with the service has been unexpectedly disconnected, //that is, its process crashed. Because it is running in our same process, we should never see this happen. Log.i("ServiceConnection", "onServiceDisconnected() called"); } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Intent mIntent = new Intent(); mIntent.setAction("android.intent.action.AIDLService"); Intent eintent = new Intent(getExplicitIntent(this,mIntent)); bindService(eintent, conn, Context.BIND_AUTO_CREATE); } public static Intent getExplicitIntent(Context context, Intent implicitIntent) { // Retrieve all services that can match the given intent PackageManager pm = context.getPackageManager(); List<ResolveInfo> resolveInfo = pm.queryIntentServices(implicitIntent, 0); // Make sure only one match was found if (resolveInfo == null || resolveInfo.size() != 1) { return null; } // Get component info and create ComponentName ResolveInfo serviceInfo = resolveInfo.get(0); String packageName = serviceInfo.serviceInfo.packageName; String className = serviceInfo.serviceInfo.name; ComponentName component = new ComponentName(packageName, className); // Create a new intent. Use the old one for extras and such reuse Intent explicitIntent = new Intent(implicitIntent); // Set the component to be explicit explicitIntent.setComponent(component); return explicitIntent; } }
和Android Service 中学习的调用MyBinder获取service中数据一样,这边只是吧MyBinder 改成了aidl定义的接口IPerson 本质上还是一个Binder
因为android 5.0 不允许隐形启用service 所有用getExplicitIntent转一下
好了现在看下效果:
相关文章推荐
- Android 四大组件之(2)Service实现原理以及AIDL语言的使用详解
- Android学习指南之二十二:实例讲解AIDL和远程Service调用
- Android进阶(二) Activity调用Service 通过AIDL实现
- Android中aidl实现Activity与service进行通信和回调
- Android中不使用AIDL实现Service的远程调用
- Android---44---使用AIDL Service 实现跨进程调用Service
- Android Service 的使用(五)----如何实现AIDL文件中含有对象的调用
- Android-在Android studio中实现远程服务(Service)AIDL
- 简单音乐播放实例的实现,Android Service AIDL 远程调用服务
- Android:远程服务Service(含AIDL & IPC讲解)
- 初识Android之(二)- 实现Service AIDL小Demo
- Android中不使用AIDL实现Service的远程调用
- Android应用程序四大组件之使用AIDL如何实现跨进程调用Service
- Android 四大组件 Service实现原理以及AIDL语言的使用详解
- Android四大组件应用系列5——使用AIDL实现跨进程调用Service
- Android应用程序四大组件之使用AIDL如何实现跨进程调用Service
- Android控件之Service AIDL实现机制demo
- Android:Service:AIDL实现进程通信
- Android:远程服务Service(含AIDL & IPC讲解)
- 基于Socket的TCP长连接(服务端Java+客户端Android),Service配合AIDL实现