Android五大组件-Service

Service本质

Service在是后台服务(即它的运行不依赖于UI,即Acitivy死掉了甚至程序关掉了Service仍然可以活着只要进程没死就可以),适合。。。。但它并不是异步也还是在主线程,故而不可做耗时操作

生命周期
这里写图片描述
Service和线程:

  1. Service仍然运行在主线程需要注意不可做耗时操作,但Service不依赖UI,只要进程活着就行。所以其生命周期可以很长
  2. Thread是异步的,适合做耗时操作。但Activity很难把控Thread,Thread生命周期可以比Acitivity长。
  3. Activity创建一个子线程,Activity死掉后其他的Activity无法获得该线程;而Service只要注册下就可以拿到。(这也就有了再Service中创建子线程去完成耗时任务的做法,IntentService)

Service的启动方式

  • 第一种:无法通信,启动后就是失联了。
//启动Service!第一次启动会调用onCreate,后面多次触发也只调用onStartCommand
startService(new Intent(this,MyService.class));
//销毁Service
stopService(new Intent(this,MyService.class));
  • 第二种:通过Binder关联
    @Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        //启动Service!bindService只调用一次,onCreate->onBinder->onUnbinder->onDestroy
        this.bindService(new Intent(this,MyService.class),conn, Context.BIND_AUTO_CREATE);
        //销毁Service
        this.unbindService(conn);

    }
    private MyService.MyBinder mBinder;
    private ServiceConnection conn = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            mBinder = (MyService.MyBinder) service;
            mBinder.getSome();//通信,获取数据
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {

        }
    };

    class MyService extends Service{

        @Nullable
        @Override
        public IBinder onBind(Intent intent) {
            return null;
        }
        public class MyBinder extends Binder
        {
            public String getSome(){
                return "返回数据给Activity";
            }
        }
    }

Service的几个方法

  • onCreate:第一次创建的时候调用,只调用一次
  • onStartCommand:每次startService都会调用
  • onDestroy:销毁时调用

AIDL的使用

这个例子是两个app之间的交互应用A提供Service服务,应用B请求服务并获得回调的一个完整的交互(代码摘自公司项目,有些地方就打×××了)
首先两个应用都需要有的两个adil文件(注意两个应用的包名需一致,直接复制完整路径即可)

package com.×××.aidl;

import com.×××.aidl.IApkScanCallback;

/**
 * IApkScanInterface.aidl
 *
 */
interface IApkScanInterface {

    /**
    * 扫描已安装apk
    * @param packageName 包名
    * @param callback 扫描结果回调
    */
    oneway void scanInstall(String packageName,IApkScanCallback callback);
}
package com.×××.aidl;
/**
 * IApkScanCallback.aidl
 *
 */
interface IApkScanCallback {
     /**
     * 扫描垃圾结果
     *
     * @param type 类型 
     * @param packageName 包名,没有则为null
     * @param appName 应用名,没有则为null
     * @param virusName 名称,没有则为null
     * @param virusDescription 描述,没有则为null
     */
    oneway void onScanResult(int type, String packageName ,String appName, String virusName, String virusDescription);

}

接下来是应用A提供服务

package com.×××.aidl;

import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;



public class ApkScanService extends Service {
    private static final String TAG = "ApkScanService";

    private Context mContext;

    public ApkScanService() {
        mContext = this;
    }

    @Override
    public IBinder onBind(Intent intent) {
        return mBinder;
    }

    private IApkScanInterface.Stub mBinder = new IApkScanInterface.Stub() {

        @Override
        public void scanInstall(String packageName, IApkScanCallback callback) throws RemoteException {
            callback.onScanResult(1, "包名", "应用名", "名称", "描述");
        }
    };

}

注册下Service,需要注意的是android:exported属性设置为true,否则外部App访问不到

<service
            android:name=".aidl.ApkScanService"
            android:enabled="true"
            android:exported="true"></service>

最后是请求端应用B

package com.×××;

import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;

import com.×××.aidl.IApkScanCallback;
import com.×××.IApkScanInterface;

public class MainActivity extends Activity {

    public static final String TAG = "MainActivity";
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Intent intent = new Intent();
        intent.setComponent(new ComponentName("com.×××",//填写访问Service的包名
                "com.×××.aidl.ApkScanService"));//填写访问Service的路劲
        bindService(intent, conn, Context.BIND_AUTO_CREATE);

        try {
            apkScan.scanInstall("包名", apkCallback);
        } catch (RemoteException e) {
            e.printStackTrace();
        }


    }

    private IApkScanCallback apkCallback = new IApkScanCallback.Stub(){

        @Override
        public void onScanResult(int type, String packageName, String appName, String virusName, String virusDescription) throws RemoteException {
            Log.d(TAG,"type = " + type + "appName = " + appName + "virusName = " + virusName);

        }
    };
    private IApkScanInterface apkScan;

    private ServiceConnection conn = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
            apkScan = IApkScanInterface.Stub.asInterface(iBinder);
        }

        @Override
        public void onServiceDisconnected(ComponentName componentName) {

        }
    };


}

ps:

  • in out inout:非Java基本类型必须修饰,in out inout的含义是指:它们表示数据的流向,in表示C流向S,out表示S流向C,inout则两端均可互相流通。举个粟子,C调用method(in String a,out String b),这个时候S端收到的a是C传过来的a,b则为null,因为out无法从C流向S。详情
  • oneway 当接口使用oneway关键字修饰时,表示接口在远程调用时是不会block的,即接口调用时发送完transaction数据后立即返回而不会等待远端的结果。注意,这只针对IPC的调用,同样的接口如果是在同一进程内部被调用的话,oneway关键字不起任何效果,方法该阻塞就阻塞。

Service源码

待续。。。

Service(杂)

  • Service可以绑定多个组件(Activity,BroadcastReceiver等)
  • 前台Service:Service在onCreate中创建Notification显示在状态栏中
  • IntentService
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值