android service 自动解绑并销毁

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了android service 自动解绑并销毁相关的知识,希望对你有一定的参考价值。

我在bind的service里面开启下载线程(onCreate方法里面),下载完成之后activity没有销毁,我也没有手动的解绑,但是下载线程结束之后服务就自动解绑并销毁了,为什么会这样?我试过,在onCreate方法里面不开启下载线程,service就不会解绑也不销毁,求解!

参考技术A 诚祺零零落落零零落落零零落落

安卓服务service全解,生命周期,前台服务后台服务,启动注销绑定解绑,注册


全栈工程师开发手册 (作者:栾鹏)

​​ python教程全解​​

定义服务(服务的生命周期)

安卓服务service全解,生命周期,前台服务、后台服务,启动注销、绑定解绑,注册_android

调用context.startService()时依次执行 ->onCreate()- >onStartCommand()->Service running

调用context.stopService()时依次执行 ->onDestroy()

调用context.bindService()时依次执行->onCreate()->onBind()->Service running

调用context.onUnbind()时依次执行 -> onDestroy()

当绑定service和所有客户端解除绑定之后,Android系统将会销毁它,(除非它同时被onStartCommand()方法开启)。

因此,如果你的service是一个纯粹的绑定service,那么你不需要管理它的生命周期。

然而,如果你选择实现onStartCommand()回调方法,那么你必须显式地停止service,因为service此时被看做是开启的。

这种情况下,service会一直运行到它自己调用 stopSelf()或另一个组件调用stopService(),不论它是否和客户端绑定。

另外,如果你的service被开启并且接受绑定,那么当系统调用你的 onUnbind()方法时,如果你想要在下次客户端绑定的时候接受一个onRebind()的调用(而不是调用 onBind()),你可以选择在 onUnbind()中返回true。

onRebind()的返回值为void,但是客户端仍然在它的 onServiceConnected()回调方法中得到 IBinder 对象。

下图展示了这种service(被开启,还允许绑定)的生命周期:

安卓服务service全解,生命周期,前台服务、后台服务,启动注销、绑定解绑,注册_绑定_02

代码示例:

代码中设计服务的生命周期,服务设置为前台服务和后台服务。

package com.lp.app.service;


import com.lp.app.Activity1;
import com.lp.app.R;

import android.app.Notification;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.util.Log;


//服务的生命周期
public class Service1 extends Service

public final static String action_name = "com.lp.action.service1";
public final static String key1 = "key1";
public final static String key2 = "key2";

//当服务被创建时,执行oncreat函数
@Override
public void onCreate()
Log.v("服务生命周期", "服务第一次被启动");
pausePlayback(); //将服务放置在后台。默认服务就是后台服务。前台服务是一个通知栏
startPlayback("显示标题","显示文本"); //打开一个通知栏,点击通知,可以将服务移动至前台


//onStartCommand为service的重新启动函数
@Override
public int onStartCommand(Intent intent, int flags, int startId)
//startBackgroundTask(intent, startId); //将服务设置到后台运行

//START_STICKY:如果service进程被kill掉,保留service的状态为开始状态,但不保留递送的intent对象。随后系统会尝试重新创建service,重新启动后参数Intent将为null。
//START_NOT_STICKY:“非粘性的”。使用这个返回值时,如果在执行完onStartCommand后,服务被异常kill掉,系统不会自动重启该服务。
//START_REDELIVER_INTENT:重传Intent。使用这个返回值时,如果在执行完onStartCommand后,服务被异常kill掉,系统会自动重启该服务,并将原来Intent的值传入。
//START_STICKY_COMPATIBILITY:START_STICKY的兼容版本,但不保证服务被kill后一定能重启。


//参数flags可以用来确定service的启动方式。START_FLAG_REDELIVERY表示Intent参数是由系统运行时在通过stopSelf显式停止service之前终止它而重新传递的。
//FLAF_RETRY表示service已经在异常终止后重新启动,如果service之前被设为START_STICKY,则会传入这个标志
Log.v("服务生命周期", "服务被其他窗口通过startService()启动");
return Service.START_STICKY;



public class MyBinder extends Binder
Service1 getService()
return Service1.this;


private final IBinder binder = new MyBinder();
@Override
public IBinder onBind(Intent intent)
// TODO 自动生成的方法存根
Log.v("服务生命周期", "一个客户端正在通过bindService()函数绑定到本服务");
return binder;


@Override
public void onRebind(Intent intent)

//在onUnbind()函数已经被调用过后执行
Log.v("服务生命周期", "一个客户端正在通过bindService()函数绑定到当前服务");


@Override
public boolean onUnbind(Intent intent)

Log.v("服务生命周期", "所有客户端已经通过unbindService()函数脱离绑定");
return true; //返回允许绑定



@Override
public void onStart(Intent intent,int startId)
Log.v("服务生命周期", "服务启动");
super.onStart(intent, startId);


@Override
public void onDestroy()
Log.v("服务生命周期", "服务销毁");
super.onDestroy();




//将一个service移动至前台
//(前台服务:会在通知一栏显示 ONGOING 的 Notification。当服务被终止的时候,通知一栏的 Notification 也会消失,这样对于用户有一定的通知作用)
//前台服务具有较高的优先级,能在内存不足时,不被杀死
private void startPlayback(String contenttitle, String contenttext)
int NOTIFICATION_ID = 1;

//创建一个当单击通知时将打开主activity的intent
Intent intent = new Intent(this, Activity1.class);
PendingIntent pi = PendingIntent.getActivity(this, 1, intent, 0);

//设置Notification UI参数
Notification notification = new Notification(R.drawable.icon,"启动app窗口", System.currentTimeMillis());
notification.setLatestEventInfo(this, contenttitle, contenttext, pi);

//设置notification为持续显示
notification.flags = notification.flags | Notification.FLAG_ONGOING_EVENT;

//将service移到前台。
startForeground(NOTIFICATION_ID, notification);



//将service移动到后台
public void pausePlayback()
//移动到后台并移除Notification
stopForeground(true);


在manifest文件中注册服务

这里我们hi演示显式启动服务和隐式启动服务。所有这里处理设置服务的名称,还设置了触发条件

<!-- service注册服务,其中permission表示要想外部应用程序使用这个服务,必须要包含的自定义权限(只是个名称) -->
<service
android:name="com.lp.app.service.Service1"
android:permission="com.lp.my_service1_permission">
<intent-filter>
<action android:name="com.lp.action.service1"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</service>

显式的启动和终止服务

Intent serviceIntent=null;
//显示启动一个服务
private void explicitStart()
serviceIntent = new Intent(this, Service1.class);
startService(serviceIntent);


//显式终止一个服务
private void explicitStop()
if(serviceIntent!=null)
stopService(serviceIntent);

隐式的启动和终止服务

隐式启动,相当于把自定义服务注册为系统服务,再以启动系统服务的方式启动自定义服务。

这种方式的和显式的启动和停止服务不同,而是通过intent触发指定名称的事件。而这个事件又触发了注册在manifest文件中的service,所以需要在manifest文件中注册服务时,设定触发源

//隐式的启动一个Service。相当于把自定义服务注册为系统服务,再以启动系统服务的方式启动自定义服务
private void implicitStart()
Intent intent = new Intent(Service1.action_name); //在注册服务是设置了intent-filter,所以启动这个,可以启动对应的服务
intent.putExtra(Service1.key1, "value1");
intent.putExtra(Service1.key2, "value2");
startService(intent);


//隐式终止一个服务
private void implicitStop()
Intent intent = new Intent(Service1.action_name);
stopService(intent);

绑定和解除绑定

//为Service绑定创建一个service连接
//service的引用
private Service1 serviceRef;

//处理service和 activity之间的连接
private ServiceConnection mConnection = new ServiceConnection()
//当建立连接时调用此函数
public void onServiceConnected(ComponentName className, IBinder service)
serviceRef = ((Service1.MyBinder)service).getService();
Log.v("服务绑定客户端", "服务绑定建立连接");

//当service意外断开时执行
public void onServiceDisconnected(ComponentName className)
serviceRef = null;
Log.v("服务绑定客户端", "服务绑定断开连接");

;

Intent bindIntent=null;
//绑定一个service和activity
private void bindToService()
bindIntent = new Intent(this, Service1.class);
bindService(bindIntent, mConnection, Context.BIND_AUTO_CREATE);
//BIND_AUTO_CREATE表示收到绑定请求的时候,如果服务尚未创建,则即刻创建,在系统内存不足需要先摧毁优先级组件来释放内存,且只有驻留该服务的进程成为被摧毁对象时,服务才被摧毁
//BIND_DEBUG_UNBIND通常用于调试场景中判断绑定的服务是否正确,但容易引起内存泄漏,因此非调试目的的时候不建议使用
//BIND_NOT_FOREGROUND表示系统将阻止驻留该服务的进程具有前台优先级,仅在后台运行,该标志位位于Froyo中引入


//解除一个绑定
private void unbindToService()
if (bindIntent!=null)
unbindService(mConnection);


以上是关于android service 自动解绑并销毁的主要内容,如果未能解决你的问题,请参考以下文章

Service的生命周期

android:当Activity和Service 都被销毁后,如何控制其中生成的线程?

Android中怎么启动关闭Service及功能解释

在哪里停止/销毁 Android Service 类中的线程?

android中启动service的activity销毁了,这时怎么关闭service?

Service的启动与停止绑定与解绑