http://blog.csdn.net/guolin_blog/article/details/9797169java
http://www.jianshu.com/p/eeb2bd59853fandroid
将一个普通的Service转换成远程Service其实很是简单,只须要在注册Service的时候将它的android:process属性指定成:remote就能够了,代码以下所示:app
<service android:name=".AIDLService"
android:process=":remote"></service>
远程service可让service在另外一个进程运行,因此能够执行阻塞进程的操做ide
远程Service这么好用,干脆之后咱们把全部的Service都转换成远程Service吧,还免得再开启线程了。其实否则,远程Service非但很差用,甚至能够称得上是较为难用。通常状况下若是能够不使用远程Service,就尽可能不要使用它。ui
下面就来看一下它的弊端吧,首先将MyService的onCreate()方法中让线程睡眠的代码去除掉,而后从新运行程序,并点击一下Bind Service按钮,你会发现程序崩溃了!为何点击Start Service按钮程序就不会崩溃,而点击Bind Service按钮就会崩溃呢?这是因为在Bind Service按钮的点击事件里面咱们会让MainActivity和MyService创建关联,可是目前MyService已是一个远程Service了,Activity和Service运行在两个不一样的进程当中,这时就不能再使用传统的创建关联的方式,程序也就崩溃了。this
那么如何才能让Activity与一个远程Service创建关联呢?这就要使用AIDL来进行跨进程通讯了(IPC)。spa
调用者和Service若是不在一个进程内, 就须要使用android中的远程Service调用机制.
android使用AIDL定义进程间的通讯接口. AIDL的语法与java接口相似, 须要注意如下几点:.net
AIDL实现
1.首先我创建2个app工程,经过aidl实现一个app调用另外一个app的service
目录结构以下:
service提供端app线程
利用aidl调用service的appcode
2.在两个app中都创建一个文件 IPerson.aidl注意 包名 要相同
IPerson.aidl只是一个接口文件,用来aidl交互的,创建好以后在Studio中点Build-->Rebuild会自动建立须要的java文件。
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"); } }
这里为何能够这样写呢?由于Stub其实就是Binder的子类,因此在onBind()方法中能够直接返回Stub的实现。
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; } }
在上一篇文章中咱们已经知道,若是想要让Activity与Service之间创建关联,须要调用bindService()方法,并将Intent做为参数传递进去,在Intent里指定好要绑定的Service,示例代码以下:
Intent bindIntent = new Intent(this, MyService.class); bindService(bindIntent, connection, BIND_AUTO_CREATE);
这里在构建Intent的时候是使用MyService.class来指定要绑定哪个Service的,可是在另外一个应用程序中去绑定Service的时候并无MyService这个类,这时就必须使用到隐式Intent了
<intent-filter> <action android:name="com.example.servicetest.MyAIDLService"/> </intent-filter>
这就说明,MyService能够响应带有com.example.servicetest.MyAIDLService这个action的Intent。