Android cross-process and start the Service Process FAQ

Disclaimer: This article is a blogger original article, shall not be reproduced without the bloggers allowed. https://blog.csdn.net/One_Month/article/details/80255893

Android recent study inter-process communication, to use AIDL, with reference to the development of artistic exploration, but the practice also encountered some problems, special note of the process and frequently asked questions, use the tool Android Studio

1. The server file written AIDL
Write pictures described here
click new, create AIDL interface file
File Structure
generated IMyAidlInterface.aidl file, the file name can be modified their own

package com.example.android_7_test;

// Declare any non-default types here with import statements
import com.example.android_7_test.Book;

interface IMyAidlInterface {
    /**
     * Demonstrates some basic types that you can use as parameters
     * and return values in AIDL.
     * 在接口文件中定义 服务端提供的方法  供客户端调用 ,下面的setBook是我测试的方法
     *
     */
    void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat,
            double aDouble, String aString);
    /**
    1.定义的方法不能有修饰符
    2.不能有方法体
    3.除了基本数据类型,要加上方向参数  in 输入性(作为参数传入)  out 输出型(返回值) inout
    */
    boolean setBook(in Book book);
}

And there are entities like Book a test of (the entity class to implement parcelable Interface), while creating Book.aidl in the same package, custom entity classes will need to create aidl file of the same name, you can click on the new - "file -" appropriate filename suffix map .aidl, above the reference

package com.example.android_7_test;
/**
注明 parcelable + 自定义类名
*/
parcelable Book;

Note: The three class package name must be the same, it is possible to automatically generated with the package name. AIDL the .xxx, may be wrong, it will be removed, but also expressly incorporated IMyAidlInterface interface to the relevant entity class, the top of the reference code
entity class and two aidl do not have to file in the same package, but in order to facilitate the transplant client, it is recommended to put the same package, but this will result in a java class can not access the directory entity classes, there will not be find class reference, this time you need to add configuration build.gradle

android{
sourceSets {
        main {
            manifest.srcFile 'src/main/AndroidManifest.xml'
            java.srcDirs = ['src/main/java', 'src/main/aidl']
            resources.srcDirs = ['src/main/java']
            aidl.srcDirs = ['src/main/aidl']
            res.srcDirs = ['src/main/res']
            assets.srcDirs = ['src/main/assets']
        }
    }
}

2. Synchronize the project to generate the java file AIDL
Write pictures described here
click synchronization project, under the build- in the Project directory structure after the completion of "source-" aidl can see the generated java file
Write pictures described here
3. The server implements the interface

1.实现接口
2.重写onBind,返回binder对象
/**
这个是kotlin代码,可以自己改成java代码
*/
class MyService : Service() {
    //实现接口,这里实现的是接口的内部stub类
    val interfa = object : IMyAidlInterface.Stub() {


        override fun setBook(book: Book?): Boolean {
            //实现定义的方法,这里是发送一个toast
            Handler(Looper.getMainLooper()).post({ Toast.makeText(applicationContext, "收到设置", Toast.LENGTH_SHORT).show() })
            return true
        }

        override fun basicTypes(anInt: Int, aLong: Long, aBoolean: Boolean, aFloat: Float, aDouble: Double, aString: String?) {
            TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
        }
    }

    override fun onBind(intent: Intent): IBinder {
        //返回binder对象,不返回的话绑定服务无法成功
        return interfa.asBinder()
    }
}

4. Registration Service in Manifest file

<!--
process = ":remote"  这个表示在新的进程中运行
exported = "true"  这个标识是否可被外部程序调用,不设置的话外部程序绑定启动这个service会出现
java.lang.SecurityException: Not allowed to bind to service Intent 
-->
<service     
            android:name=".MyService"
            android:process=":remote"
            android:exported="true"
           ></service>

5. Create a copy of the client files to the same package
can be the same server, create aidl files, generate aidl directory, but this would be inconsistent with the generated package name, you can create a new package in the directory, file and server names package agreed
Write pictures described here
① Similarly, the class files in this directory java can not access the entity classes Book, or to carry out the above configuration build.gradle in! ! !

② package name must match the package name of the server! ! ! Otherwise, there will Binder invocation to an incorrect interface

6. Client binding start service, call the relevant methods

/**
获取返回的binder对象
*/
IMyAidlInterface iMyAidlInterface = null;
    private ServiceConnection serviceConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            iMyAidlInterface = IMyAidlInterface.Stub.asInterface(service);
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {

        }
    };
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main2);
        Intent intent = new Intent();
        /**
        跨进程,无法使用Intent(this,xx.class)方法,可以使用下面的,通过包名和完整路径类名创建Intent
        */
        intent.setClassName("com.example.android_7_test","com.example.android_7_test.MyService");
        bindService(intent,serviceConnection,BIND_AUTO_CREATE);
    }

Behind can call the service defined by the end IMyAidlInterface object method for communication, error-prone to be noted the above-mentioned point.

Thanks for reading, if wrong, please correct me.

Guess you like

Origin blog.csdn.net/One_Month/article/details/80255893