service全面解析(二)

前一篇我们分析了service的一些基本知识和用法,service全面解析(一),今天一起来看看如何提高service的进程优先级,跨进程通信的问题。
一:如何将service设置为前台进程:
首先我们简单的来看下Android中的几种进程:
1.前台进程(active process)
前台进程是那种用于和用户交互控件的程序,这些进程Android系统都会极力保护的,一般以下的场景都是前台进程:
a:处于前台的activity,它用于和用户进程交互
b:activity service 或者正在执行onReceiver()方法的BroadcastReceiver
c:正在执行onStart onCreate onDestroy方法的service
2.可见进程(Visible Process)
可见但不活动的那些进程,一般是可见的Activity但是不能和用户进行交互,比如一个Activity被部分遮挡的时候,可见进程在极端的情况下才会被系统杀死,来维护前台进程,一般的可见进程有
a:可见的Activity,但是处于onPause状态
b.被绑定到可见Activity的service
3.服务进程(service process)
进程中已经启动的service,
4.后台进程(background process)
不可见的Activity和没有启动的service都属于后台进程
5.空进程(empty process)
Android中问了整个系统性能,会保留把些已经走完生命周期的应用程序,Android缓存这些进程用来提高再次启动应用的时间。
分析完Android中的进程,我们会发现service处于第三个服务进程中,通常我们会将一个耗时的操作放在一个线程中,见这样的线程放在service中比放在Activity中会有较高的优先级,降级被系统杀掉的可能性,因为Activity一旦被转为后台,它的优先级会降为第四级的后台进程,明显没有service的进程优先级高。
service中有两个方法用来设置为前台进程和取消前台进程
startForeground(int id,Notification notif)可以设置services为前台进程;
stopForeground(int id)取消前台进程
将service设置为前台进程

Intent intent = new Intent();
intent.setClass(this, ServiceActivity.class);//设置目标service
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0,
intent, PendingIntent.FLAG_UPDATE_CURRENT);
Notification notification = new Notification(R.drawable.weixin,
         "service", System.currentTimeMillis());
notification.flags = Notification.FLAG_ONGOING_EVENT;
         notification.setLatestEventInfo(this, "service",
         "serviceForeprocess",
         pendingIntent);
startForeground(2525, notification);

这样我们就可很容易讲一个service设置为前台进程,被设置为前台的service拥有最高的优先级,这样我们可以降级被系统杀掉的风险。
一:service跨进程通讯
有的时候我们需要跨进程去和另一个应用进程通讯,Android跨进程通讯有好几种比如broadcastReceiver等还有我们今天要讲的service跨进程调用
service的跨进程调用称为AIDL(Android Interface Define Language)Android接口定义语言。AIDL相当于两个进程通讯的协议,按照这个协议编写程序就可以进程进程通讯。
进程通讯需要两个应用程序,首先我们来看看服务端的代码。我们创建一个服务端应用起名为AndroidTestAidl,接着创建一个包为com.sg.androidtestaidl,在这包下我们创建一个AIDL文件IMyService.aidl

 interface IMyService {
  void play(String taregetStr);
}

这里需要注意的是在定义aidl文件的时候,不能有访问修饰符就算是public也不行,出了基本类型 String List Map 其他的都需要导包,就算是在同一个包下也需要导包。
好了创建好IMyService.aidl文件之后刷新一下我们的工程,会在gen目录下生成对应的接口文件IMyService.java,打开这个文件我们简单看一下。

我们看第九行Stub是IMyService类的内部抽象类继承了Binder类 这个是需要我们之后在绑定service的时候返回的,再看21行Stub的asInterface方法,这个方法负责将客户端返回的对象转为IMyService.Stub对象 我们在看90行就是我们在在aidl文件中声明的方法。
接下来看看我们的AIDLService.Java

 public class AIDLService extends Service {
    public static String TAG = AIDLService.class.getSimpleName();
    public MyBinder binder;
    @Override
    public IBinder onBind(Intent intent) {
        // TODO Auto-generated method stub
        Log.i("---------", "-----------aidlonbind-------");
        return new MyBinder();
    }
    @Override
    public void onCreate() {
        // TODO Auto-generated method stub
        super.onCreate();
    }
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.i("---------", "-----------onStartCommand-------");
        return super.onStartCommand(intent, flags, startId);
    }
    public class MyBinder extends IMyService.Stub {

        @Override
        public void play(String targetStr) throws RemoteException{
        AIDLService.this.play(targetStr);
        }
    }
    public void play(String targetStr) {
        Log.i(TAG, "---------" + targetStr);
    }
}

我们在AIDLService 类中定义了一个MyBinder类,它继承IMyService.Stub,这里和定义本地service通信不同,并在onBind方法中返回这个对象,在play方法中打印了一下传进来参数。
最后注册一下service

 <service android:name=".AIDLService" >
            <intent-filter>
                <action android:name="com.example.service.aidl" />
            </intent-filter>
  </service>

最后在创建一个客户端程序,将IMyService.aidl连通包一起复制到我们的客户端应用中。因为AIDL文件两个应用的包名文件必须一致。看看客户端调用服务端的代码:

public class ServiceActivity extends Activity implements OnClickListener {
    private IMyService binder;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        // TODO Auto-generated method stub
        super.onCreate(savedInstanceState);
        setContentView(R.layout.service_main);
        Button start_service_bt = (Button) findViewById(R.id.bt_start_service);
        Button stop_service_bt = (Button) findViewById(R.id.bt_stop_service);
        Button bind_service_bt = (Button) findViewById(R.id.bt_bind_service);
        start_service_bt.setOnClickListener(this);
        stop_service_bt.setOnClickListener(this);
        bind_service_bt.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        Intent intent = new Intent();
         intent.setAction("com.example.service.aidl");
        switch (v.getId()) {
        case R.id.bt_start_service:
             try {
             binder.play("service跨进程通讯");;
             } catch (RemoteException e) {
             e.printStackTrace();
         }
            break;
        case R.id.bt_stop_service:
            unbindService(connection);
            break;
        case R.id.bt_bind_service:
        bindService(intent,connection,Service.BIND_AUTO_CREATE);
            break;
        }}
private ServiceConnection connection = new ServiceConnection({
        @Override
        public void onServiceDisconnected(ComponentName name) {
            // TODO Auto-generated method stub
            Log.i("---------", "-------disConnection-------");
        }
        @Override
public void onServiceConnected(ComponentName name, IBinder service) {
        binder =  IMyService.Stub.asInterface(service);
        }
    };  
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值