在ServiceManager中加入自定义的服务

    xiaoxiao2023-03-24  3

    https://my.oschina.net/u/262208/blog/379584

        当我们要使用android的系统服务时,一般都是使用Context.getSystemService方法。例如我们要获取AudioManager,我们可以:

    AudioManager am = (AudioManager) getSystemService(Context.AUDIO_SERVICE);

        获取的服务,其实是在ServiceManager中注册的Binder服务,然后进行封装后,提供给用户。

        可以看ContextImpl.java中的实现:

       static {         ......         // 将AudioManager加入SYSTEM_SERVICE_MAP中,调用getSystemService时,         // 就会从SYSTEM_SERVICE_MAP得到AudioManager         registerService(AUDIO_SERVICE, new ServiceFetcher() {                 public Object createService(ContextImpl ctx) {                     return new AudioManager(ctx);                 }});         ......     }

        AudioManager是对IAudioService的封装,实际操作都是使用IAudioService进行的,看AudioManager中的代码:

      private static IAudioService getService()     {         if (sService != null) {             return sService;         }         // 从ServiceManager中获取Binder         IBinder b = ServiceManager.getService(Context.AUDIO_SERVICE);         // 将Binder转化成IAudioService,方便调用         sService = IAudioService.Stub.asInterface(b);         return sService;     }

        上面是android系统的使用方式。如果我们添加自己的服务,要如何做呢?

        

        我们在eclipse中建3个测试工程:

        1)MyServiceLib:这是个lib工程,需要在eclipse中勾选Is Library。后面的两个工程,都需要将MyServiceLib添加到Library中。

        2) MyService: 用于在android开机时注册自定义服务进ServiceManager。因为ServiceManager被@hide隐藏了,所以要使用它需要自己手动添加sdk包,添加方式可参考http://my.oschina.net/u/262208/blog/379548。另外,添加服务,需要System用户,所以manifest文件中需要加上android:sharedUserId="android.uid.system", 并且要使用platform签名签名apk。

        3)MyServiceTest:用于测试上面两个工程。

    下面我们就来编码。

    先在MyServiceLib工程中创建一个aidl文件,android编译工具会帮我们生成相应的java类,aidl文件如下

    package com.test.lib; interface IMyService {     void setValue(int val);     int getValue(); }

    定义了两个接口用于测试,setValue和getValue。

    android编译工具会帮我们在gen目录下生成一个IMyService的java类。

        2. 在MyService工程中创建MyService类, 这个类继承自IMyService.Stub,实现了setValue和getValue接口,这就是一个Service。

    package com.test.myservice;   import android.os.RemoteException; import com.test.lib.IMyService;   public class MyService extends IMyService.Stub {       private int value;           @Override     public void setValue(int val) throws RemoteException {         this.value = val;     }       @Override     public int getValue() throws RemoteException {         return value;     }   }

    下面我们将把它加入至ServiceManager中。

    3. 在MyService工程中创建MyServiceApplication类

    package com.test.myservice;   import android.app.Application; import android.os.ServiceManager;   public class MyServiceApplication extends Application{       @Override     public void onCreate() {         super.onCreate();         ServiceManager.addService("MYSERVICE"new MyService());     }       }

    这是一个Application,我们希望android系统启动时,就创建这个Application,在onCreate方法中,创建MyService类,并加入到ServiceManager中。因此,我需要修改下manifest文件

     

      <application         android:name=".MyServiceApplication"   //指定Application为我们创建的MyServiceApplication         android:allowBackup="true"         android:icon="@drawable/ic_launcher"         android:persistent="true"             // 加上persistent=ture,ActivityManager创建的时候,就会创建该应用的进程,并调用MyServiceApplication的onCreate方法         android:label="@string/app_name"         android:theme="@style/AppTheme" >

    注意,这个应用需要system用户,并签名才可运行。

    这样,服务端就好了,并且开机时,我们的服务就已经在ServiceManager中了。

    4. 下面我们提供一个Manager类方便客户端使用。在MyServiceLib中创建MyManager类:

    package com.test.lib;   import android.os.RemoteException; import android.os.ServiceManager;   public class MyManager {       private static MyManager instance;     private IMyService myservice;       public static MyManager getInstance() {         if (instance == null) {             instance = new MyManager();         }         return instance;     }       private MyManager() {         // 从ServiceManager中获取服务         myservice = IMyService.Stub.asInterface(ServiceManager.getService("MYSERVICE"));     }       public void setValue(int value) throws RemoteException {         myservice.setValue(value);     }       public int getValue() throws RemoteException {         return myservice.getValue();     }   }

    5. 在MyServiceTest工程中进行测试

        通过MyManager.getInstance()可以很方便的获取服务的Manager,对远程服务进行调用。我们创建一个Activity来使用MyManager

    package com.test.client;   import java.util.Random;   import android.app.Activity; import android.content.Context; import android.media.AudioManager; import android.os.Bundle; import android.os.RemoteException; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.TextView; import android.widget.Toast;   import com.test.binder.client.R; import com.test.lib.MyManager;   public class MainActivity extends Activity implements OnClickListener {       MyManager myManager;           Button btnSetValue;     Button btnGetValue;     TextView tvValue;           @Override     protected void onCreate(Bundle savedInstanceState) {         super.onCreate(savedInstanceState);         AudioManager am = (AudioManager) getSystemService(Context.AUDIO_SERVICE);         setContentView(R.layout.activity_main);         btnSetValue = (Button) findViewById(R.id.btn_set_value);         btnGetValue = (Button) findViewById(R.id.btn_get_value);         tvValue = (TextView) findViewById(R.id.tv_value);                   // 获取MyManager         myManager = MyManager.getInstance();     }       @Override     public void onClick(View view) {         switch (view.getId()) {         case R.id.btn_set_value:             int value = new Random().nextInt();             try {                 myManager.setValue(value);                 Toast.makeText(this"set value to "+value+ " success!"0).show();             } catch (RemoteException e) {                 e.printStackTrace();                 Toast.makeText(this"set value fail!"0).show();             }             break;         case R.id.btn_get_value:             try {                 tvValue.setText("value:"+myManager.getValue());             } catch (RemoteException e) {                 // TODO Auto-generated catch block                 e.printStackTrace();             }             break;         default:             break;         }     }       }
    转载请注明原文地址: https://ju.6miu.com/read-1202318.html
    最新回复(0)