Android Service 浅析(生命周期,启动方式,前台Service)
来源:互联网 发布:佛山新能源汽车知豆 编辑:程序博客网 时间:2024/06/05 15:05
Service是android中四大组件之一,重要性仅次于Activity,Android文档对他的描述如下:
Service组件表示在不影响用户的情况下执行耗时操作或者提供其他应用使用的功能。
在android中所有的组件都运行在主线程,使用service的时候,还需要吧耗时的操作另开启一个线程。但是使用Service,更适合管理耗时的操作,因为service有着不同的生命周期。比如说应用中播放音乐,通常由Service控制。
启动Service
Service 可以通过两种方式启动:Context.startService()或者Context.bindService();
Context.startService()和启动activity的方法类似:
Intent i = new Intent(ServiceActivity.this, ServiceA.class); startService(i);
使用这种方式启动Service后,Service分别会调用onCreate()和onStartCommand()方法。
停止Service的方法:
Intent i = new Intent(ServiceTestActivity.this, ServiceA.class);stopService(i);
也可以调用Service的stopSelf()方法进行停止。
service销毁的时候会调用他的onDestory()方法,在这里进行释放资源的操作。
需要注意的是多次启动Service,onCreate()方法不会多次调用,只有在第一次启动的时候会调用(或者把Service销毁重新start),但是onStartCommand()方法会多次调用。
第二种方式:Context.bindService()
Intent i = new Intent(ServiceTestActivity.this, ServiceA.class);bindService(i,connection,BIND_AUTO_CREATE);
解除绑定方法:
Intent i = new Intent(ServiceTestActivity.this, ServiceA.class);unbindService(connection);
这种方式启动Service的时候,生命周期方法如下:
bindService->onCreate->onBind->unbindService->onUnbind->onDestroy
如果没有调用unbindService方法,当activity销毁的时候此Service也能销毁,但是会发生内存泄露,会报如下错误:
08-30 00:12:06.060 1937-1937/example.ylh.com E/ActivityThread: Activity example.ylh.com.service_demo.ServiceTestActivity has leaked ServiceConnection example.ylh.com.service_demo.ServiceTestActivity$1@513a0eb that was originally bound here······
所以为了防止内存泄露,还是老老实实的unbind吧。
bindService启动的时候,需要传两个参数,第一个是intent,第二个是ServiceConnection,这个是什么东西呢?
我们知道Service启动之后,Service额就开始运行了,但是怎么和Activity交互呢,这个时候就需要ServiceConnection了,ServiceConnection是一个接口:
private ServiceConnection connection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { Log.e(TAG,"onServiceConnected"); } @Override public void onServiceDisconnected(ComponentName name) { Log.e(TAG, "onServiceDisconnected"); } };
onServiceConnected方法的调用时机是在Service的onBind之后,表示service和activity绑定成功,建立关联。
onServiceDisconnected方法表示Service和activity关联失败,没有绑定,一般不会调用。
onServiceConnected方法有两个参数,第二个参数是一个IBinder,这个IBinder就是Service的onBind方法的返回值,所以我们可以通过onBind的返回值和onServiceConnected方法,让activity和Service关联起来,下边是一个典型案例:
activity的xml:
<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="vertical"> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/btn1" android:text="start"/> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/btn2" android:text="stop"/> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/btn3" android:text="action"/> </LinearLayout></RelativeLayout>
activity代码:
package example.ylh.com.service_demo;import android.app.Activity;import android.content.ComponentName;import android.content.Intent;import android.content.ServiceConnection;import android.os.Bundle;import android.os.IBinder;import android.util.Log;import android.view.View;import example.ylh.com.R;/** * Created by yanglihai on 2017/8/17. */public class ServiceTestActivity extends Activity { public static final String TAG = ServiceTestActivity.class.getSimpleName(); private ServiceConnection connection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { mService = ((ServiceA.MyBinder) service).getService(); Log.e(TAG,"onServiceConnected"); } @Override public void onServiceDisconnected(ComponentName name) { Log.e(TAG, "onServiceDisconnected"); } }; private ServiceA mService ; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.service_test_activity); findViewById(R.id.btn1).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Intent i = new Intent(ServiceTestActivity.this, ServiceA.class); bindService(i,connection,BIND_AUTO_CREATE); } }); findViewById(R.id.btn2).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Intent i = new Intent(ServiceTestActivity.this, ServiceA.class); unbindService(connection); } }); findViewById(R.id.btn3).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { mService.doSomething(); } }); }}
service的代码:
package example.ylh.com.service_demo;import android.app.Service;import android.content.Intent;import android.content.ServiceConnection;import android.os.Binder;import android.os.IBinder;import android.support.annotation.Nullable;import android.util.Log;/** * Created by yanglihai on 2017/8/17. */public class ServiceA extends Service { static final String TAG = ServiceA.class.getSimpleName(); @Override public void onCreate() { super.onCreate(); Log.e(TAG, "oncreate"); } @Override public int onStartCommand(Intent intent, int flags, int startId) { Log.e(TAG, "onStartCommand"); return super.onStartCommand(intent, flags, startId); } @Override public void onDestroy() { super.onDestroy(); Log.e(TAG, "onDestroy"); } @Override public boolean bindService(Intent service, ServiceConnection conn, int flags) { Log.e(TAG, "bindService"); return super.bindService(service, conn, flags); } @Override public void unbindService(ServiceConnection conn) { super.unbindService(conn); Log.e(TAG, "unBindService"); } @Override public boolean onUnbind(Intent intent) { Log.e(TAG, "onUnbind"); return super.onUnbind(intent); } @Nullable @Override public IBinder onBind(Intent intent) { Log.e(TAG, "onBind" ); return mbinder; } public void doSomething(){ Log.e(TAG, "doSomething"); } private MyBinder mbinder = new MyBinder(); public class MyBinder extends Binder{ public ServiceA getService(){ return ServiceA.this; } }}
在onServiceConnected方法中,通过强转拿到binder,在通过getService()拿到Service的实例,就可以进行你想要的操作了。
前台Service
当Service启动之后,如果我们不去调用停止方法,Service会一直运行在后台,但是当系统内存不足的时候可能会杀死我们的Service,为了避免被系统杀死,可以把Service设置成前台服务,通过调用Service.startForeground()来实现。
先上代码:
package example.ylh.com.service_demo;import android.app.Notification;import android.app.Service;import android.content.Intent;import android.content.ServiceConnection;import android.os.Binder;import android.os.IBinder;import android.support.annotation.Nullable;import android.util.Log;import example.ylh.com.R;/** * Created by yanglihai on 2017/8/17. */public class ServiceA extends Service { static final String TAG = ServiceA.class.getSimpleName(); @Override public void onCreate() { super.onCreate(); Log.e(TAG, "oncreate"); Notification.Builder builder = new Notification.Builder(this); builder.setSmallIcon(R.mipmap.btn_home_vedio); builder.setContentTitle("视频通知"); builder.setContentText("someone send you a video"); Notification notification = builder.build(); startForeground(2,notification); } @Override public int onStartCommand(Intent intent, int flags, int startId) { Log.e(TAG, "onStartCommand"); return super.onStartCommand(intent, flags, startId); } @Override public void onDestroy() { super.onDestroy(); Log.e(TAG, "onDestroy"); }}
在onCreate中,创建了一个通知,用来告诉用户后台有操作在运行。startForeground()的第一个参数是一个int型的id,需要注意的是这个id不能为0,否则不能创建前台服务。
在这个Service运行期间,通知栏会有一个通知,直到Service停止或者调用StopForeground(true),通知就能消失。
补充一点,不论哪种启动方式,Service也需要在manifest文件中声明:
<?xml version="1.0" encoding="utf-8"?><manifest xmlns:android="http://schemas.android.com/apk/res/android" package="example.ylh.com" > <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/> <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:supportsRtl="true" android:theme="@style/AppTheme" > <activity android:name=".MainActivity" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <service android:name=".service_demo.ServiceA" /> </application></manifest>
- Android Service 浅析(生命周期,启动方式,前台Service)
- 浅析 - Service启动方式
- Android之service生命周期及启动方式
- Android之service生命周期及启动方式
- Android Service生命周期,本地服务远程服务,前台服务后台服务,启动方式,与IntentService区别全面解析
- Android Service 启动方式
- Android Service两种启动方式及 生命周期
- Android Service启动方式以及生命周期以及通信总结
- Android Service的两种启动方式以及生命周期
- Android Service两种启动启动方式 及 adndroid service生命周期
- Android Service两种启动启动方式 及 adndroid service生命周期
- android Service(一) activity启动Service方式一:startService()
- android Service(二) activity启动Service方式二:bindService()
- service 总结之启动方式和生命周期
- Service的生命周期与启动方式
- Service两种启动方式的生命周期
- service的生命周期和启动方式
- Service生命周期浅析
- 字节输入输出流之实现图片文件的复制
- 红帽6 安装oracle 12c 详细步骤
- centos 配置tomcat(jdk)
- linux下如何使用sftp命令
- 杂七杂八
- Android Service 浅析(生命周期,启动方式,前台Service)
- 匹配两个字符串中,相同且最长的子字符串
- CNN字符级中文文本分类-基于TensorFlow实现
- Atitit 建设自己的财政体系 attilax总结 1.1. 收入理论2 1.2. 收入分类2 1.3. 2 1.4. 非货币收入2 1.5. 2 1.6. 降低期望2 1.7.
- React Native TextInput键盘遮挡输入款问题
- Hibernate中.hbm.xml文件的常用设置
- php的socket编程常用函数解析
- 安全的安装PuTTY 0.70
- SharedPreference小结