美文网首页
Android Service的使用

Android Service的使用

作者: 黑山老雕 | 来源:发表于2019-12-19 18:00 被阅读0次

    类型和区别

    • 特点:没有UI,后台运行
    • Started
      • 启动方式startSevice()
      • 一旦启动,在后台永远运行,除非主动停止或者被kill
      • 通常不返回值(可发一个PendingIntent, 用广播返回值)
    • Bound
      • 启动方式bindService()
      • 只要有应用绑定到它,就在运行。当没有应用绑定时,service被摧毁。
      • 多个应用可以绑定到一个bind service.
      • BroadcastReceiver不能绑定到服务
      • 可以返回值,以及做进程间通信(IPC)
    • 一个service可以同时实现onStartCommand()和onBind()
    • 注意:Service是在主线程上运行,不要进行耗时操作


      image.png

    创建一个新的service

    1. 重写父类方法

      • onStartCommand(). 被startService()调用,需要用stopSelf() or stopService()手动停用
      • onBind(),当调用bindSerivce()的时候会调用,需要返回一个IBinder
      • onCreate(). 一次性,如service已经在运行,则不再调用
      • onDestroy(). 前台服务>绑定到活动的服务>后台服务>长时间运行的后台服务. 服务会被kill,当有资源时,会尝试恢复。对于started服务,需要考虑当系统自动恢复时的处理。这根据onStartCommand()时的返回值有所不同:
        • START_STICKY, 重新启动时,传入的intent是null
        • START_STICKY_COMPATIBILITY, 不保证会重新调用onStartCommand()
        • START_NOT_STICKY, 不自动重启
        • START_REDELIVER_INTENT, 总是重新发送上次的intent
        • 可以通过flag来判断服务的性质START_FLAG_REDELIVERY, START_FLAG_RETRY
    2. 修改Manifest

      • android:enabled=["true" | "false"]
      • android:exported=[“true” | “false”],如果为false,只有相同userID的能访问。如果有intent filter,默认为true,如果没有,默认为false
      • android:icon="drawable resource“
      • android:isolatedProcess=[“true” | “false”], 为true时,将运行在独立进程中
      • android:label="string resource“
      • android:name="string“
      • android:permission=“string“,如果设置,只有拥有权限的才能访问
      • android:process=“string”

    IntentService & Stop Service &前台服务

    • Intent Service
      • Service的子类,推荐的实现Started Service的方法。会自动为每个request创建worker thread.
      • 自动创建队列进行处理,不用担心线程冲突
      • 队列处理完毕自动stopSelf()
      • 自动为不可bind的(可以通过重写来实现可bind)
      • 只需要两点:
        • 构造函数中调用父类
        • 实现onHandleIntent()方法
      • 可以重写其它方法,但要记得返回父类函数
    • 停止Service
      • 当stop service时,如果多个request同时在处理,stopSelf()可能会把新发起的request结束掉,所以推荐使用stopSelf(int),这样会比较当前正在处理的request是不是结束的目标。
      • 记得stopSelf(),这是消耗系统资源的。
    • 前台Service
      • 提供必需的notification和id, 用startForeground(ONGOING_NOTIFICATION_ID, notification) 启动,用stopForeground(boolean removeNotification)停止
      • stopForeground并不停止服务,而只是会让前台notification消失

    Bounded Service

    创建bounded service的三种方式

    • 扩展Binder类,如果只是自己的应用内使用,用这种方式。
    • 使用Messenger,可实现IPC的最简单(?)的方法,线程安全,C/S端都用Handler来处理消息
    • 使用AIDL,优点是可以同时处理多个请求,对于大部分的app,Google并不推荐使用这种方式(但是在framework里面有很多)
      onBind()只在第一次绑定时执行一次,后续再绑定时返回第一次的Ibinder对象
      当调用服务的方法时,要捕获DeadObjectException异常,这个异常标明service不存在了
    • bindServices的flag
      • BIND_AUTO_CREATE
      • BIND_DEBUG_UNBIND,只用于调试。当设置时,以后的unbind请求的callstack会被保存
      • BIND_IMPORTANT,允许客户端把服务升级为“前台”优先级,一般只能升级到“可见”优先级
      • BIND_NOT_FOREGROUND,不允许把被绑定的服务升级为“前台”优先级。
      • BIND_ABOVE_CLIENT,道友比贫道更重要
      • BIND_ADJUST_WITH_ACTIVITY,如从activity发起,那么允许优先级随其可见性来调整
      • BIND_ALLOW_OOM_MANAGEMENT, 让拥有该服务的进程来自己管理优先级
      • BIND_WAIVE_PRIORITY,放弃调整优先级,让系统像对待普通应用一样对待

    扩展Binder类方式

    • Service端
      • 实现一个Binder实例,其中包含可调用的方法或者其它包含可调用方法的类示例(包括当前的service类)
      • 在onBind()时返回该实例
    • Client端
      • 绑定时传入connection参数(一个ServiceConnection的实例),绑定是异步的,并不返回Binder
      • 在connection的onServiceConnected()方法中接收实例,并转换类型为Binder类型,然后调用需要的方法
      • 实现connection的onServiceDisconnected()方法,处理服务crash和被kill时的情况
    • 示例代码
    //服务端:
    public class LocalService extends Service {
        // Binder given to clients
        private final IBinder mBinder = new LocalBinder();//实例化
        // Random number generator
        private final Random mGenerator = new Random();
    
        /**
         * Class used for the client Binder.  Because we know this service always
         * runs in the same process as its clients, we don't need to deal with IPC.
         */
        public class LocalBinder extends Binder {//实现Binder,其中有可返回当前service的方法
            LocalService getService() {
                // Return this instance of LocalService so clients can call public methods
                return LocalService.this;
            }
        }
    
        @Override
        public IBinder onBind(Intent intent) {
            return mBinder;
        }
    
        /** method for clients */
        public int getRandomNumber() {
          return mGenerator.nextInt(100);
        }
    }
    
    //客户端:
    public class BindingActivity extends Activity {
        LocalService mService;
        boolean mBound = false;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.main);
        }
    
        @Override
        protected void onStart() {
            super.onStart();
            // Bind to LocalService
            Intent intent = new Intent(this, LocalService.class);
            bindService(intent, mConnection, Context.BIND_AUTO_CREATE);//开启Activity时绑定service,绑定后立即返回,connection作为参数传入
                                                                       //绑定完成后,将会调用connection的onServiceConnected方法,客户端将在
                                                                       //那里接收Binder,并转型,然后得到要可调用方法的类,或者该Binder就包含可调方法
        }
    
        @Override
        protected void onStop() {
            super.onStop();
            // Unbind from the service
            if (mBound) {
                unbindService(mConnection);
                mBound = false;
            }
        }
    
        /** Called when a button is clicked (the button in the layout file attaches to
          * this method with the android:onClick attribute) */
        public void onButtonClick(View v) {
            if (mBound) {
                // Call a method from the LocalService.
                // However, if this call were something that might hang, then this request should
                // occur in a separate thread to avoid slowing down the activity performance.
                int num = mService.getRandomNumber();
                Toast.makeText(this, "number: " + num, Toast.LENGTH_SHORT).show();
            }
        }
    
        /** Defines callbacks for service binding, passed to bindService() */
        private ServiceConnection mConnection = new ServiceConnection() {
    
            @Override
            public void onServiceConnected(ComponentName className,
                    IBinder service) {
                // We've bound to LocalService, cast the IBinder and get LocalService instance
                LocalBinder binder = (LocalBinder) service;
                mService = binder.getService();
                mBound = true;
            }
    
            @Override
            public void onServiceDisconnected(ComponentName arg0) {
                mBound = false;
            }
        };
    }
    

    使用Messenger方式

    • Service端
      • 创建Handler来处理消息
      • 用Handler创建一个Messenger
      • 在onBind()中返回Messenger创建的IBinder
    • Client端
      • 用得到的IBinder去创建Messenger
      • 用Messenger发消息指挥Service的Handler运行
      • (如需要回复),创建Client端的Messenger,在send()命令的replyTo参数中传入这个Messenger
    • Sample:
    //服务端:
    public class MessengerService extends Service {
        /** Command to the service to display a message */
        static final int MSG_SAY_HELLO = 1;
    
        /**
         * Handler of incoming messages from clients.
         */
        class IncomingHandler extends Handler {//定义一个Handler
            @Override
            public void handleMessage(Message msg) {
                switch (msg.what) {
                    case MSG_SAY_HELLO:
                        Toast.makeText(getApplicationContext(), "hello!", Toast.LENGTH_SHORT).show();
                        break;
                    default:
                        super.handleMessage(msg);
                }
            }
        }
    
        /**
         * Target we publish for clients to send messages to IncomingHandler.
         */
        final Messenger mMessenger = new Messenger(new IncomingHandler());//用Handler创建一个Messenger
    
        /**
         * When binding to the service, we return an interface to our messenger
         * for sending messages to the service.
         */
        @Override
        public IBinder onBind(Intent intent) {
            Toast.makeText(getApplicationContext(), "binding", Toast.LENGTH_SHORT).show();
            return mMessenger.getBinder();//返回用Messenger创建的IBinder
        }
    }
    
    //客户端:
    public class ActivityMessenger extends Activity {
        /** Messenger for communicating with the service. */
        Messenger mService = null;
    
        /** Flag indicating whether we have called bind on the service. */
        boolean mBound;
    
        /**
         * Class for interacting with the main interface of the service.
         */
        private ServiceConnection mConnection = new ServiceConnection() {
            public void onServiceConnected(ComponentName className, IBinder service) {
                // This is called when the connection with the service has been
                // established, giving us the object we can use to
                // interact with the service.  We are communicating with the
                // service using a Messenger, so here we get a client-side
                // representation of that from the raw IBinder object.
                mService = new Messenger(service);//用IBinder创建Messenger
                mBound = true;
            }
    
            public void onServiceDisconnected(ComponentName className) {
                // This is called when the connection with the service has been
                // unexpectedly disconnected -- that is, its process crashed.
                mService = null;
                mBound = false;
            }
        };
    
        public void sayHello(View v) {
            if (!mBound) return;
            // Create and send a message to the service, using a supported 'what' value
            Message msg = Message.obtain(null, MessengerService.MSG_SAY_HELLO, 0, 0);
            try {
                mService.send(msg);
            } catch (RemoteException e) {//记得Catch Exception
                e.printStackTrace();
            }
        }
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.main);
        }
    
        @Override
        protected void onStart() {
            super.onStart();
            // Bind to the service
            bindService(new Intent(this, MessengerService.class), mConnection,
                Context.BIND_AUTO_CREATE); //实际应用中,这里应该是隐式intent
        }
    
        @Override
        protected void onStop() {
            super.onStop();
            // Unbind from the service
            if (mBound) {
                unbindService(mConnection);
                mBound = false;
            }
        }
    }
    

    AIDL方式

    1. 服务端

      • 创建AIDL
        • 创建接口定义和方法签名
        • 可识别的数据类型包括基本类型(int,long,boolean),String,CharSequence,List(支持泛型,对端接收到的总是一个arrayList),Map接口(不支持泛型,对端接收到的总是一个HashMap),List和Map必须加in/out/inout参数(in:参数会传输到服务端,out:参数只是用来获取输出值,没有传输,inout:两者结合)
        • 只能有方法,不能有静态域
      • 实现接口,SDK自动生成名为Stub的抽象函数(派生于Binder),我们需要派生这个Stub类并实现它的抽象方法
        • 调用通常是以同步方式执行,所以注意不要在调用方的主线程调用,可能引起调用方的ANR
        • 在服务端发出的exception并不会被返回到调用方。
          实现服务,在onBind()中将stub的实例返回去
    2. 客户端

      • 也要导入AIDL
      • 调用bind之后,在onServiceConnected()中用IRemoteService.Stub.asInterface(service)将Binder转换为接口,就可以直接使用了
    3. 本地调用发生在与调用方相同的线程,远程调用发生在一个系统维护的线程池中(这里,跟Service在主线程上运行是有出入的)

    4. example:
      AIDL:

    package com.example.testservice;
    
    interface ITestAidl {
        List<String> testListGeneric();
        List testListNoGeneric();//支持泛型List
        //List testListWithGeneric1(in List param); //不支持非泛型参数
        List testListWithGeneric(in List<String> param);
        //Map<String,String> testMap1(); //不支持泛型Map
        //Map testMap(out Map param);//Map做参数,gen里面会报错,原因应该是因为不支持非泛型参数
        Map testMap(String Param);
        
        List testIn(in List<String> param);//in:参数会被输送到服务端
    //@Override public java.util.List testIn(java.util.List<java.lang.String> param) throws android.os.RemoteException
    //{
    //android.os.Parcel _data = android.os.Parcel.obtain();
    //android.os.Parcel _reply = android.os.Parcel.obtain();
    //java.util.List _result;
    //try {
    //_data.writeInterfaceToken(DESCRIPTOR);
    //_data.writeStringList(param);
    //mRemote.transact(Stub.TRANSACTION_testIn, _data, _reply, 0);
    //_reply.readException();
    //java.lang.ClassLoader cl = (java.lang.ClassLoader)this.getClass().getClassLoader();
    //_result = _reply.readArrayList(cl);
    //}
    //finally {
    //_reply.recycle();
    //_data.recycle();
    //}
    //return _result;
    //}
        List testOut(out List<String> param);//out:参数只是用来获取输出值
    //{
    //android.os.Parcel _data = android.os.Parcel.obtain();
    //android.os.Parcel _reply = android.os.Parcel.obtain();
    //java.util.List _result;
    //try {
    //_data.writeInterfaceToken(DESCRIPTOR);
    //mRemote.transact(Stub.TRANSACTION_testOut, _data, _reply, 0);
    //_reply.readException();
    //java.lang.ClassLoader cl = (java.lang.ClassLoader)this.getClass().getClassLoader();
    //_result = _reply.readArrayList(cl);
    //_reply.readStringList(param);
    //}
    //finally {
    //_reply.recycle();
    //_data.recycle();
    //}
    //return _result;
    //}
        List testInOut(inout List<String> param);//参数会被传输,处理后成为输出值
    //{
    //android.os.Parcel _data = android.os.Parcel.obtain();
    //android.os.Parcel _reply = android.os.Parcel.obtain();
    //java.util.List _result;
    //try {
    //_data.writeInterfaceToken(DESCRIPTOR);
    //_data.writeStringList(param);
    //mRemote.transact(Stub.TRANSACTION_testInOut, _data, _reply, 0);
    //_reply.readException();
    //java.lang.ClassLoader cl = (java.lang.ClassLoader)this.getClass().getClassLoader();
    //_result = _reply.readArrayList(cl);
    //_reply.readStringList(param);
    //}
    //finally {
    //_reply.recycle();
    //_data.recycle();
    //}
    //return _result;
    //}
    }
    
    

    Service:

    package com.example.testservice;
    
    import java.util.ArrayList;
    import java.util.Hashtable;
    import java.util.List;
    import java.util.Map;
    
    import android.app.Service;
    import android.content.Intent;
    import android.os.IBinder;
    import android.os.RemoteException;
    import android.util.Log;
    
    public class SampleService extends Service {
    
        @Override
        public IBinder onBind(Intent arg0) {
            return mBinder;
        }
    
        private ITestAidl.Stub mBinder = new ITestAidl.Stub() {
    
            @Override
            public List testOut(List<String> param) throws RemoteException {
                for (String s : param) {
                    Log.i("TestAIDL", "Before manipulate,param is:" + s);
                }
                param.add("5");
                param.add("6");
                param.add("7");
                return param;
            }
    
            @Override
            public Map testMap(String Param) throws RemoteException {
                Map<Integer, String> myMap = new Hashtable<Integer, String>();
                myMap.put(1, Param);
                myMap.put(2, Param + " " + Param);
                return myMap;
            }
    
            @Override
            public List testListWithGeneric(List<String> param)
                    throws RemoteException {
            for (String s : param) {
                    Log.d("TestAIDL", "Received:" + s);
            }
                return param;
            }
    
            @Override
            public List testListNoGeneric() throws RemoteException {
                List<String> myList = new ArrayList<String>();
                myList.add("A");
                myList.add("B");
                return myList;
            }
    
            @Override
            public List<String> testListGeneric() throws RemoteException {
                List<String> myList = new ArrayList<String>();
                myList.add("A");
                myList.add("B");
                return myList;
            }
    
            @Override
            public List testInOut(List<String> param) throws RemoteException {
                for (String s : param) {
                    Log.i("TestAIDL", "Before manipulate,param is:" + s);
                }
                param.add("5");
                param.add("6");
                param.add("7");
                return param;
            }
    
            @Override
            public List testIn(List<String> param) throws RemoteException {
                for (String s : param) {
                    Log.i("TestAIDL", "Before manipulate,param is:" + s);
                }
                param.add("5");
                param.add("6");
                param.add("7");
                return param;
            }
        };
    }
    
    

    Client:

    package com.example.testserviceclient;
    
    import java.util.ArrayList;
    import java.util.List;
    import java.util.Map;
    import java.util.Map.Entry;
    
    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 android.view.View;
    
    import com.example.testservice.ITestAidl;
    import com.example.zzp.IMyinterface;
    
    public class TestServiceClient extends Activity {
        public static final String ActionName = "com.zzp.test.TESTSERVICE";
        public static final String ActionNameUseJar = "com.zzp.test.USEJAR";
        private ITestAidl myService;
        private IMyinterface myJarService;
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_ttest_service);
    
        }
    
        @Override
        protected void onStart() {
            bindService(new Intent(ActionName), myConnection,
                    Context.BIND_AUTO_CREATE);
            bindService(new Intent(ActionNameUseJar), myJarConnection,
                    Context.BIND_AUTO_CREATE);
            super.onStart();
        }
    
        @Override
        protected void onStop() {
            unbindService(myConnection);
            unbindService(myJarConnection);
            super.onStop();
        }
    
        private ServiceConnection myConnection = new ServiceConnection() {
    
            @Override
            public void onServiceDisconnected(ComponentName arg0) {
                return;
            }
    
            @Override
            public void onServiceConnected(ComponentName arg0, IBinder arg1) {
                myService = ITestAidl.Stub.asInterface(arg1);
            }
        };
        private ServiceConnection myJarConnection = new ServiceConnection() {
    
            @Override
            public void onServiceDisconnected(ComponentName arg0) {
                return;
            }
    
            @Override
            public void onServiceConnected(ComponentName arg0, IBinder arg1) {
                myJarService = (IMyinterface) arg1;
            }
        };
        public void onTestLG(View view) {
            try {
                List<String> myList = myService.testListGeneric();
                for (String s : myList) {
                    Log.d("TestAIDL-Client", "Test List Generic:" + s);
                    // D/TestAIDL-Client(20810): Test List Generic:A
                    // D/TestAIDL-Client(20810): Test List Generic:B
                }
            } catch (RemoteException e) {
                Log.e("TestAIDL-Client", e.getMessage());
                e.printStackTrace();
            }
    
        }
    
        public void onTestLNG(View view) {
            try {
                // List<String> myList = myService.testListNoGeneric();
                List myList = myService.testListNoGeneric();
                for (Object s : myList) {
                    Log.d("TestAIDL-Client",
                            "Test List Non Generic:" + s.toString());
                    // D/TestAIDL-Client(25015): Test List Non Generic:A
                    // D/TestAIDL-Client(25015): Test List Non Generic:B
                }
            } catch (RemoteException e) {
                Log.e("TestAIDL-Client", e.getMessage());
                e.printStackTrace();
            }
        }
    
        public void TestLwG(View view) {
            try {
                // List<String> myList = myService.testListNoGeneric();
                ArrayList<String> param = new ArrayList<String>();
                param.add("Client-A");
                param.add("Client-B");
                List myList = myService.testListWithGeneric(param);
                for (Object s : myList) {
                    Log.d("TestAIDL-Client",
                            "Test List With Generic:" + s.toString());
                    // D/TestAIDL(27513): Received:Client-A
                    // D/TestAIDL(27513): Received:Client-B
                    // D/TestAIDL-Client(27500): Test List With Generic:Client-A
                    // D/TestAIDL-Client(27500): Test List With Generic:Client-B
                }
            } catch (RemoteException e) {
                Log.e("TestAIDL-Client", e.getMessage());
                e.printStackTrace();
            }
        }
    
        public void TestM(View view) {
            try {
                Map<Integer, String> myMap = myService.testMap("ABC");
                for (Entry<Integer, String> s : myMap.entrySet()) {
                    Log.d("TestAIDL-Client",
                            "Test Map:" + s.getKey() + "_" + s.getValue());
                    // D/TestAIDL-Client(29739): Test Map:1_ABC
                    // D/TestAIDL-Client(29739): Test Map:2_ABC ABC
                }
            } catch (RemoteException e) {
                Log.e("TestAIDL-Client", e.getMessage());
                e.printStackTrace();
            }
        }
    
        public void TestIn(View view) {
            try {
                // List<String> myList = myService.testListNoGeneric();
                ArrayList<String> param = new ArrayList<String>();
                param.add("Client-A");
                param.add("Client-B");
                for (String s : param) {
                    Log.d("TestAIDL-Client", "Test In, param:" + s.toString());
                }
    
                List myList = myService.testIn(param);
    
                for (String s : param) {
                    Log.d("TestAIDL-Client", "Test In, param:" + s.toString());
                }
    
                for (Object s : myList) {
                    Log.d("TestAIDL-Client",
                            "Test In, return value:" + s.toString());
    
                }
                // D/TestAIDL-Client(31223): Test In, param:Client-A
                // D/TestAIDL-Client(31223): Test In, param:Client-B
                // I/TestAIDL(29511): Before manipulate,param is:Client-A
                // I/TestAIDL(29511): Before manipulate,param is:Client-B
                // D/TestAIDL-Client(31223): Test In, param:Client-A
                // D/TestAIDL-Client(31223): Test In, param:Client-B
                // D/TestAIDL-Client(31223): Test In, return value:Client-A
                // D/TestAIDL-Client(31223): Test In, return value:Client-B
                // D/TestAIDL-Client(31223): Test In, return value:5
                // D/TestAIDL-Client(31223): Test In, return value:6
                // D/TestAIDL-Client(31223): Test In, return value:7
            } catch (RemoteException e) {
                Log.e("TestAIDL-Client", e.getMessage());
                e.printStackTrace();
            }
        }
    
        public void TestOut(View view) {
            try {
                // List<String> myList = myService.testListNoGeneric();
                ArrayList<String> param = new ArrayList<String>();
                param.add("Client-A");
                param.add("Client-B");
                for (String s : param) {
                    Log.d("TestAIDL-Client", "Test Out, param:" + s.toString());
                }
    
                List myList = myService.testOut(param);
    
                for (String s : param) {
                    Log.d("TestAIDL-Client", "Test Out, param:" + s.toString());
                }
    
                for (Object s : myList) {
                    Log.d("TestAIDL-Client",
                            "Test Out, return value:" + s.toString());
    
                }
                // D/TestAIDL-Client( 2359): Test Out, param:Client-A
                // D/TestAIDL-Client( 2359): Test Out, param:Client-B
                // 这里,服务端并没有收到param
                // D/TestAIDL-Client( 2359): Test Out, param:5
                // D/TestAIDL-Client( 2359): Test Out, param:6
                // D/TestAIDL-Client( 2359): Test Out, param:7
                // D/TestAIDL-Client( 2359): Test Out, return value:5
                // D/TestAIDL-Client( 2359): Test Out, return value:6
                // D/TestAIDL-Client( 2359): Test Out, return value:7
            } catch (RemoteException e) {
                Log.e("TestAIDL-Client", e.getMessage());
                e.printStackTrace();
            }
        }
    
        public void TestInOut(View view) {
            try {
                // List<String> myList = myService.testListNoGeneric();
                ArrayList<String> param = new ArrayList<String>();
                param.add("Client-A");
                param.add("Client-B");
                for (String s : param) {
                    Log.d("TestAIDL-Client", "Test InOut, param:" + s.toString());
                }
    
                List myList = myService.testInOut(param);
    
                for (String s : param) {
                    Log.d("TestAIDL-Client", "Test InOut, param:" + s.toString());
                }
    
                for (Object s : myList) {
                    Log.d("TestAIDL-Client",
                            "Test InOut, return value:" + s.toString());
    
                }
                // D/TestAIDL-Client( 2359): Test InOut, param:Client-A
                // D/TestAIDL-Client( 2359): Test InOut, param:Client-B
                // I/TestAIDL(29511): Before manipulate,param is:Client-A
                // I/TestAIDL(29511): Before manipulate,param is:Client-B
                // D/TestAIDL-Client( 2359): Test InOut, param:Client-A
                // D/TestAIDL-Client( 2359): Test InOut, param:Client-B
                // D/TestAIDL-Client( 2359): Test InOut, param:5
                // D/TestAIDL-Client( 2359): Test InOut, param:6
                // D/TestAIDL-Client( 2359): Test InOut, param:7
                // D/TestAIDL-Client( 2359): Test InOut, return value:Client-A
                // D/TestAIDL-Client( 2359): Test InOut, return value:Client-B
                // D/TestAIDL-Client( 2359): Test InOut, return value:5
                // D/TestAIDL-Client( 2359): Test InOut, return value:6
                // D/TestAIDL-Client( 2359): Test InOut, return value:7
            } catch (RemoteException e) {
                Log.e("TestAIDL-Client", e.getMessage());
                e.printStackTrace();
            }
        }
    
        // public void TestUseJar(View view) {
        // Log.d("TestAIDL-Client", "Use Jar:" + myJarService.test());
        // Log.d("TestAIDL-Client", "Static value:" + myJarService.DEFINE);
        // Hashtable<Integer, String> param = new Hashtable<Integer, String>();
        // param.put(5, "壹");
        // param.put(6, "贰");
        //
        // Hashtable<Integer, String> myTable = myJarService.testGenericMap(param);
        // for (Entry<Integer, String> s : myTable.entrySet()) {
        // Log.d("TestAIDL-Client",
        // "Use Jar Map:" + s.getKey() + "_" + s.getValue());
        // }
        //
        // }
    }
    
    

    附:进程优先级

    当系统决定杀掉一个进程的时候,会按照进程优先级的从低到高来决定先杀哪个。

    • 前台
      • 拥有Activity并用户正在交互(onResume)
      • 拥有服务且服务与一个前台页面绑定
      • 拥有服务,且通过startForeground()调用
      • 正在执行服务的生命周期(onCreate等)
      • 广播正在执行onReceive
    • 可见
      • 页面已暂停
      • 服务绑定到前台或可见页面
    • 服务进程
      • 含有用Start方式启动的服务
    • 后台进程
      • 页面已不再可见(onStop被调用)
      • LRU (least recently used) list, 最早停止的最早kill
    • 空进程
      • 不含有效组件,只为缓存

    转载请注明出处。

    image

    更多视频教程请在网易云课堂搜索黑山老雕。

    相关文章

      网友评论

          本文标题:Android Service的使用

          本文链接:https://www.haomeiwen.com/subject/xucvnctx.html