当前位置: 移动技术网 > IT编程>移动开发>Android > Android实现在ServiceManager中加入自定义服务的方法详解

Android实现在ServiceManager中加入自定义服务的方法详解

2019年07月24日  | 移动技术网IT编程  | 我要评论

纯情罗曼史漫画,针锋对决 水千丞,郭富城身高体重

本文实例讲述了android实现在servicemanager中加入自定义服务的方法。分享给大家供大家参考,具体如下:

当我们要使用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包,添加方式可参考在eclipse中使用sdk中@hide函数的方法附加说明。另外,添加服务,需要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;
    }
  }
}

附:在eclipse中使用sdk中@hide函数的方法

我们使用eclipse进行android开发时,使用的是adt中提供的sdk,里面是不包含@hide函数和变量的。因为android为了兼容、安全等原因,在提供sdk时,把这些函数给隐藏了。但是,很多时候,我们又需要使用这些函数,因此我们需要手动添加android sdk。例如,当我们使用audiomanager时,当需要看某种streamtype是否mute时,可以调用isstreammute(int streamtype)这个方法,但是因为它是@hide的,所以我们就需要引入自己的sdk,才能编译通过。

1. android系统编译时,当编译“include $(build_java_library)”时,会在$android_source_base/out/target/common/obj/java_libraries生成中间文件,当我们需要使用某些类库时,可以从这里面找。

isstreammute(int streamtype)在framework.jar中,我们从out/target/common/obj/java_libraries/framework_intermediates中,将classes.jar拷贝到本地,并重命名为framework.jar。

2. 在eclipse中右键工程->properties->java build path->libraries->add external jar

3. 点击order and export,将framework.jar 置顶

4. 现在,我们就可以使用audiomanager中的isstreammute(int streamtype)方法了

更多关于android相关内容感兴趣的读者可查看本站专题:《android基本组件用法总结》、《android视图view技巧总结》、《android资源操作技巧汇总》、《android操作json格式数据技巧总结》、《android开发入门与进阶教程》、《android编程之activity操作技巧总结》及《android控件用法总结

希望本文所述对大家android程序设计有所帮助。

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网