AIDL不同APP间调用service出现Service Intent must be explicit 解决方案


app Client调用app Service 中的service时候出现 java.lang.IllegalArgumentException: Service Intent must be explicit: Intent { act=com.ada.aidls.IMyAidlInterface }

查阅资料表明,是Android 5.0出来后,其中有个特性就是Service Intent must be explitict。本地调用使用显示调用解决,但是aidl跨进程访问service时候确实需要使用隐式调用。

源码如下:


    private void validateServiceIntent(Intent service) {
            if (service.getComponent() == null && service.getPackage() == null) {
                if (getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.LOLLIPOP) {
                    IllegalArgumentException ex = new IllegalArgumentException(
                            "Service Intent must be explicit: " + service);
                    throw ex;
                } else {
                    Log.w(TAG, "Implicit intents with startService are not safe: " + service
                            + " " + Debug.getCallers(2, 3));
                }
            }
        }

Google官网给出了解决方案 ,隐式调用是除了设置setAction()外,还需要设置setPackage();


    Intent mIntent = new Intent();
    mIntent.setAction("XXX.XXX.XXX");//你定义的service的action
    mIntent.setPackage("XXX.XXX.XXX");//这里你需要设置你应用的包名
    context.startService(mIntent);


Note:

setPackage(""),中的报名,为服务器的APP Service的包名,在AndroidManifest.xml中查看,注意不要引入service服务所在的包名。




下面是我的例子

public class ClientActivity extends AppCompatActivity implements View.OnClickListener{
    IMyAidlInterface mIMyAidlInterface;
    private Button btnDate;
    private Button btnBind;
    private Context mContext;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_client);
        btnDate=(Button) findViewById(R.id.btn_get_remote_time);
        mContext=this;
        btnDate.setOnClickListener(this);
        btnBind=(Button) findViewById(R.id.btn_bind_remote_service);
        btnBind.setOnClickListener(this);

    }

    private ServiceConnection mConnect=new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
            mIMyAidlInterface= IMyAidlInterface.Stub.asInterface(iBinder);
            Log.e("ClientActivity", "connect success");
        }

        @Override
        public void onServiceDisconnected(ComponentName componentName) {
            Log.e("ClientActivity", "Service has unexpectedly disconnected");
            mIMyAidlInterface=null;
        }
    };

    @Override
    public void onClick(View view) {
        switch (view.getId()) {
            case R.id.btn_bind_remote_service:
                Log.e("ClientActivity", "开始绑定");
                Intent bindIntent = new Intent(); 
                //方法一:
                bindIntent.setAction("com.ada.aidls.IMyAidlInterface");
                bindIntent.setPackage("com.ada.aidlservicedemo");
               // 方法二:
//                bindIntent.setClassName("com.ada.aidlservicedemo", "com.ada.aidlservicedemo.service.RemoteService");
                boolean a=bindService(bindIntent, mConnect, Context.BIND_AUTO_CREATE); 
                break;
            case R.id.btn_get_remote_time:
                try {
                    String id=mIMyAidlInterface.getID();
                    Toast.makeText(mContext,"id="+id, Toast.LENGTH_LONG).show();
                } catch (RemoteException e) {
                    e.printStackTrace();
                }
                break;
            default:
                break;
        }

    }
}





你可能感兴趣的:(AIDL不同APP间调用service出现Service Intent must be explicit 解决方案)