参考自:http://blog.csdn.net/guolin_blog/article/details/11952435
http://blog.csdn.net/javazejian/article/details/52709857
一,Service的基本用法:
1,创建一个Service:MyService extends Service,并重写onCreate(), onStartCommand()和onDestroy()
-------------- onStart() 已经不使用。
2,启动和停止Service:
Intent startIntent = new Intent(this, MyService.class); startService(startIntent);
3, 需要在AndroidManifest中生命该Service
<service android:name=".MyService" android:enabled="true" android:exported="true"></service>
二,Service 和 Activity通信:Service的绑定:onBind() bindService();
1) 增加新类MyBinder类继承自Binder类:
class MyBinder extends Binder { public void startDownload() { Log.d(TAG, "startDownload() executed"); } } 2) 并在onBind()时返回该MyBinder实例:private MyBinder mBinder = new MyBinder(); @Override public IBinder onBind(Intent intent) { Log.d("MyService", "====== onBind ============"); return mBinder; }
3) 定义ServiceConnection: 用于在Activity和Service之间连接上之后的处理动作:connection
private MyService.MyBinder myBinder; private ServiceConnection connection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName componentName, IBinder service) { myBinder = (MyService.MyBinder) service; myBinder.startDownload(); Log.d("ServiceConnection", " ======== onServiceConnected ============ "); } @Override public void onServiceDisconnected(ComponentName componentName) { Log.d("ServiceConnection", " ======== onServiceDisConnected ============ "); } };
4) 在Activity中绑定该ServiceConnection:
Intent bindIntent = new Intent(this, MyService.class); bindService(bindIntent, connection, BIND_AUTO_CREATE);
通过上述动作,就可以把Activity和Service绑定,并把任务交到Service去处理。
参考,标准的Service实现模型:
@Override public int onStartCommand(Intent intent, int flags, int startId) { new Thread(new Runnable() { @Override public void run() { // 开始执行后台任务 } }).start(); return super.onStartCommand(intent, flags, startId); } class MyBinder extends Binder { public void startDownload() { new Thread(new Runnable() { @Override public void run() { // 执行具体的下载任务 } }).start(); } }
三,Service的生命周期:
startService() 和 BindService() 均可以启动一个Service,两者的生命周期如下:
需要注意的是Service的销毁,当同时使用StartService()和bindService() 一起调用Service的,如果Service还被绑定,直接调用StopService()是无法销毁该Service的
四,创建前台Service:
创建前台Service的目的:1,提高后台运行Service的优先级;2,避免系统因内存不足而kill掉该Service。
前台Service和普通Service的最大的区别在于:它会一直有一个正在运行的图标显示在状态栏。
Intent notificationIntent = new Intent(this, MainActivity.class); PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0); Notification.Builder builder = new Notification.Builder(this) .setContentIntent(pendingIntent) .setSmallIcon(R.mipmap.ic_launcher) .setContentTitle("这是通知的标题"); Notification notification = builder.build(); startForeground(1, notification); //调到前台
五,Android 5.0以上的隐式启动问题:
在Android 5.0之后google出于安全的角度禁止了隐式声明Intent来启动Service。
解决办法:
* 设置Action和packageName:
final Intent serviceIntent=new Intent(); serviceIntent.setAction("com.android.ForegroundService"); serviceIntent.setPackage(getPackageName());//设置应用的包名 startService(serviceIntent);* 将隐式启动转换为显示启动: public static Intent getExplicitIntent(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; }
使用如下方式调用:
Intent mIntent=new Intent();//辅助Intent mIntent.setAction("com.android.ForegroundService"); final Intent serviceIntent=new Intent(getExplicitIntent(this,mIntent)); startService(serviceIntent); 问题,如果Service在AndroidManifest中设置process属性,调用startService或者BindService;其中onCreate(), onStartCommand() 不会被调用。
需要通过调用AIDL相应的接口,实现所需要的远程调用。
六,