Android——service
来源:互联网 发布:建筑论文怎么写 知乎 编辑:程序博客网 时间:2024/06/15 12:26
Android Service
android中service主要有本地service(localService)和远程service(remoteService)
启动service的方式主要有直接启动(startService)与绑定启动(bindService)
- 本文还将介绍一个较为普遍的service灰色保活手段。
demo下载地址:http://download.csdn.net/detail/sapce_fish/9616181
本地service(localService)
1.编写service类(在service创建后会启动一个线程,模拟在service中的任务)
package com.space.service.local;import android.app.Service;import android.content.Intent;import android.os.*;import android.support.annotation.Nullable;import android.util.Log;/** * Created by space on 2016/8/26. */public class LocalService extends Service{ private final static String TAG = "LocalService"; private boolean mIsRun; private LocalBind mLocalBind; @Nullable @Override public IBinder onBind(Intent intent) { Log.i("space", TAG+"---onBind()"); return mLocalBind; } @Override public void onCreate() { super.onCreate(); Log.i("space", TAG + "---onCreate() Process.myPid=" + android.os.Process.myPid()); startDownload(); mLocalBind = new LocalBind(); } @Override public int onStartCommand(Intent intent, int flags, int startId) { Log.i("space", TAG + "---onStartCommand()"); return super.onStartCommand(intent, flags, startId); } @Override public boolean onUnbind(Intent intent) { Log.i("space", TAG + "---onUnbind"); return super.onUnbind(intent); } @Override public void onDestroy() { super.onDestroy(); Log.i("space", TAG + "---onDestroy()"); mIsRun = false; } public class LocalBind extends Binder{ public void localDownload(){ if(!mIsRun){ startDownload(); }else{ Log.i("space", TAG + "---------下载任务正在进行"); } } } private void startDownload(){ mIsRun = true; new Thread(new Runnable() { @Override public void run() { try { for(int i=0;i<1000 && mIsRun;i++){ Log.i("space", TAG + "---------下载线程在执行 " + i); Thread.sleep(5 * 1000); } Log.i("space", TAG + "---下载线程执行完了 "); } catch (InterruptedException e) { e.printStackTrace(); } } }).start(); }}
2.Manifest中注册service
<service android:name=".local.LocalService" android:label="测试localService"></service>
3.启动service
直接启动
startService(new Intent(this,LocalService.class));
关闭
stopService(new Intent(this, LocalService.class));
bind启动
bindService(new Intent(this, LocalService.class), mLocalSerConn, BIND_AUTO_CREATE);
解除绑定
if(mIsBindLocal){ unbindService(mLocalSerConn); mIsBindLocal = false; }else{ Log.i(TAG,"还没有绑定service"); }
两种启动方式对比:
情况\启动方式 直接启动service bind启动 启动方式 startService bindService 关闭方式 stopService unbindService finish acitivty 不会关闭 会关闭 开启后调用service中的方法 不可调用 可通过返回的bind调用
注:service是运行在主线程上的,如果需要在service中做耗时操作,避免ANR则需要在service中开线程执行
远程service(remoteService)
1.定义aidl接口文件
package com.space.service.remote;interface IRemote{ String remoteDownload(String parame);}
2.编写service类(在service创建后会启动一个线程,模拟在service中的任务)
package com.space.service.remote;import android.app.Service;import android.content.Intent;import android.os.*;import android.os.Process;import android.support.annotation.Nullable;import android.util.Log;/** * Created by space on 2016/8/26. */public class RemoteService extends Service { private final String TAG = "RemoteService"; private boolean mIsRun; @Nullable @Override public IBinder onBind(Intent intent) { Log.i("space",TAG+"---onBind()"); return remoteBind; } @Override public void onCreate() { super.onCreate(); startDownload(); Log.i("space", TAG + "---onCreate() Process.myPid="+ Process.myPid()); } @Override public int onStartCommand(Intent intent, int flags, int startId) { Log.i("space", TAG + "---onStartCommand()"); return super.onStartCommand(intent, flags, startId); } @Override public boolean onUnbind(Intent intent) { Log.i("space", TAG + "---onUnbind"); return super.onUnbind(intent); } @Override public void onDestroy() { super.onDestroy(); Log.i("space", TAG + "---onDestroy()"); mIsRun = false; } @Override public void onLowMemory() { super.onLowMemory(); Log.i("space", TAG + "---onLowMemory()"); } public IRemote.Stub remoteBind = new IRemote.Stub() { @Override public String remoteDownload(final String parame) throws RemoteException { Log.i("space", TAG + "---------接收到的参数为 " + parame); if(!mIsRun){ startDownload(); }else{ Log.i("space", TAG + "---------下载任务正在进行"); } return "success"; } }; private void startDownload(){ mIsRun = true; new Thread(new Runnable() { @Override public void run() { try { for(int i=0;i<1000 && mIsRun;i++){ Log.i("space", TAG + "---------下载线程在执行 " + i); Thread.sleep(5 * 1000); } Log.i("space", TAG + "---下载线程执行完了 "); } catch (InterruptedException e) { e.printStackTrace(); } } }).start(); }}
3.在Manifest中注册service
<service android:name=".remote.RemoteService" android:process=":remotefff" android:label="测试remoteService"> <intent-filter> <action android:name="com.space.service.remoteService"/> </intent-filter> </service>
4.启动service
直接启动
Intent i = new Intent();i.setAction("com.space.service.remoteService");startService(new Intent(createExplicitFromImplicitIntent(this,i)));
关闭
Intent in = new Intent();in.setAction("com.space.service.remoteService");stopService(new Intent(createExplicitFromImplicitIntent(this,in)));
bind启动
Intent intent = new Intent();intent.setAction("com.space.service.remoteService");Intent eintent = new Intent(createExplicitFromImplicitIntent(this,intent));mIsBindRemote = bindService(eintent, mRemoteSerConn, BIND_AUTO_CREATE);
解除绑定
if(mIsBindRemote){ unbindService(mRemoteSerConn); mIsBindRemote = false;}else{ Log.i(TAG,"还没有绑定 remote service");}
因为直接用隐式intent的方法启动service会报异常,另外一种启动方式如下:
public static Intent createExplicitFromImplicitIntent(Context context, Intent implicitIntent) { //Retrieve all services that can match the given intent PackageManager pm = context.getPackageManager(); List<ResolveInfo> resolveInfo = pm.queryIntentServices(implicitIntent, 0); //Make sure only one match was found if (resolveInfo == null || resolveInfo.size() != 1) { return null; } //Get component info and create ComponentName ResolveInfo serviceInfo = resolveInfo.get(0); String packageName = serviceInfo.serviceInfo.packageName; String className = serviceInfo.serviceInfo.name; ComponentName component = new ComponentName(packageName, className); //Create a new intent. Use the old one for extras and such reuse Intent explicitIntent = new Intent(implicitIntent); //Set the component to be explicit explicitIntent.setComponent(component); return explicitIntent; }
本地service与远程service对比:
情况\service 本地service 远程service 进程 与APP同一进程 不与APP同一进程 与Activity的通信方式 本进程内通信 跨进程通信 Activity被kill 服务停止 服务不受影响(但是当系统内存不足时会被kill)
service灰色保活
之所以称为灰色保活是因为这种保活手段是利用系统漏洞,来提升service的优先级,使service尽量保持运行,实际上许多app都利用此漏洞来保活service。
思路是:API < 18,启动前台Service时直接传入new Notification();
API >= 18,同时启动两个id相同的前台Service,然后再将后启动的Service做stop处理;
知道此种实现得益于看到的另外一篇文章,在此对作者表示感谢,附上文章地址:http://www.jianshu.com/p/63aafe3c12af
首先我们来看一下各大应用是否有使用此种方式来保活service
手机连上电脑打开cmd窗口,手机上打开应用QQ,清空通知栏,然后在cmd窗口中输入
adb shell dumpsys activity services com.tencent.mobileqq
通知栏没有看到QQ的 Notification 但是看到 isForeground=true 则说明QQ利用了这种灰色保活的手段,其他应用大家有兴趣也可以试一下,那我们来看一下灰色保活的具体实现。
灰色保活的实现方式
package com.space.service.gray;import android.app.Notification;import android.app.Service;import android.content.Intent;import android.content.ServiceConnection;import android.os.Build;import android.os.IBinder;import android.support.annotation.Nullable;import android.util.Log;/** * Created by space on 2016/8/28. */public class GrayService extends Service{ private final static String TAG = "GrayService"; private final static int GRAY_SERVICE_ID = 1111; private boolean mIsRun; @Override public void onCreate() { super.onCreate(); startDownload(); Log.i("space", TAG + "---onCreate() Process.myPid=" + android.os.Process.myPid()); } @Nullable @Override public IBinder onBind(Intent intent) { Log.i("space", TAG + "---onbind"); return null; } @Override public int onStartCommand(Intent intent, int flags, int startId) { Log.i("space", TAG + "---onStartCommand()"); if (Build.VERSION.SDK_INT < 18) { Log.i("space",TAG+"api<18"); startForeground(GRAY_SERVICE_ID, new Notification());//API < 18 ,此方法能有效隐藏Notification上的图标 } else { Log.i("space",TAG+"api>18"); Intent innerIntent = new Intent(this, GrayInnerService.class); startService(innerIntent); startForeground(GRAY_SERVICE_ID, new Notification()); } return super.onStartCommand(intent, flags, startId); } @Override public void unbindService(ServiceConnection conn) { super.unbindService(conn); Log.i("space", TAG + "---onUnbind"); } @Override public void onDestroy() { super.onDestroy(); Log.i("space", TAG + "---onDestroy()"); mIsRun = false; } @Override public void onLowMemory() { super.onLowMemory(); Log.i("space", TAG + "---onLowMemory()"); } private void startDownload(){ mIsRun = true; new Thread(new Runnable() { @Override public void run() { try { for(int i=0;i<1000 && mIsRun;i++){ Log.i("space", TAG + "---------下载线程在执行 " + i); Thread.sleep(5 * 1000); } Log.i("space", TAG + "---下载线程执行完了 "); } catch (InterruptedException e) { e.printStackTrace(); } } }).start(); } /** * 给 API >= 18 的平台上用的灰色保活手段 */ public static class GrayInnerService extends Service { private final static String TAG = "GrayInnerService"; @Override public void onCreate() { super.onCreate(); Log.i("space", TAG + "---onCreate"); } @Override public int onStartCommand(Intent intent, int flags, int startId) { Log.i("space", TAG + "---onStartCommand"); startForeground(GRAY_SERVICE_ID, new Notification()); stopForeground(true); stopSelf(); return super.onStartCommand(intent, flags, startId); } @Nullable @Override public IBinder onBind(Intent intent) { return null; } @Override public void onDestroy() { super.onDestroy(); Log.i("space", TAG + "---onDestroy"); } @Override public void onLowMemory() { super.onLowMemory(); Log.i("space", TAG + "---onLowMemory"); } }}
在Manifest中注册service
<service android:name=".gray.GrayService" android:label="测试grayService"></service> <service android:name=".gray.GrayService$GrayInnerService" android:label="测试GrayInnerService"></service>
开启service
startService(new Intent(this, GrayService.class));
关闭service
stopService(new Intent(this, GrayService.class));
至此已经介绍了localService与remoteService的使用
另外如果有不明白的地方可以留言。有写错或者不好的地方欢迎指正
- Android——Service
- Android——service
- android——service
- Android Service 服务 —— Service
- Android Service Test——service
- 详解 android —— service
- Android组件——Service
- 初识android——Service
- Android服务——Service
- Android基础——Service
- Android——Service总结
- Android 组件 — Service 剖析
- android—调试命令service
- Android四大组件—Service
- Android四大组件—Service
- Android Service 服务(一)—— Service
- Android Service 服务(一)—— Service
- Android Service 服务(一)—— Service
- 教师类(多重继承)
- 从零基础接触java第七周第一节
- Method Swizzling的各种姿势
- 实现微博个人页面的滑块浮动切换页面效果(OC)
- dubbo服务启动方式对比
- Android——service
- 为什么静态成员、静态方法中不能用this和super关键字
- JavaBean中boolean类型和Boolean类型的get方法
- 驰骋工作流引擎 - 表单数据存储格式
- UML类图与类的关系详解
- opencv图像的形态学操作:腐蚀与膨胀
- Linux卸载jdk方法
- 一位资深程序员大牛给予Java初学者的学习路线建议
- 计算几何题目分类