android7之前启动前台服务,Android开发之如何保证Service不被杀掉(前台服务)

序言

最近项目要实现这样一个效果:运行后,要有一个service始终保持在后台运行,不管用户作出什么操作,都要保证service不被kill。参考了现今各种定制版的系统和安全厂商牛虻软件,如何能保证自己的Service不被杀死呢?其实除了常规的手段,我们可以参考一下 微信 和360,设置-程序-正在运行,可以看到微信是同时开启了两个进程和服务:

20b81a4ecc55b294c6171959e1054504.gif

Service简介

Service是在一段不定的时间运行在后台,不和用户交互应用组件。每个Service必须在manifest中 通过来声明。可以通过contect.startservice和contect.bindserverice来启动。和其他的应用组件一样,运行在进程的主线程中。这就是说如果service需要很多耗时或者阻塞的操作,需要在其子线程中实现(或者用系统提供的IntentService,它继承了Service,它处理数据是用自身新开的线程)。【 当然你也可以在新的线程中startService,这样Service就不是在MainThread了 】

本地服务  Local Service 用于应用程序内部

它可以启动并运行,直至有人停止了它或它自己停止。在这种方式下,它以调用Context.startService()启动,而以调用Context.stopService()结束。它可以调用Service.stopSelf() 或 Service.stopSelfResult()来自己停止。不论调用了多少次startService()方法,你只需要调用一次stopService()来停止服务。

【用于实现应用程序自己的一些耗时任务,比如查询升级信息,并不占用应用程序比如Activity所属线程,而是单开线程后台执行,这样用户体验比较好】

远程服务  Remote Service 用于 Android 系统内部的应用程序之间

它可以通过自己定义并暴露出来的接口进行程序操作。客户端建立一个到服务对象的连接,并通过那个连接来调用服务。连接以调用Context.bindService()方法建立,以调用 Context.unbindService()关闭。多个客户端可以绑定至同一个服务。如果服务此时还没有加载,bindService()会先加载它。

【可被其他应用程序复用,比如天气预报服务,其他应用程序不需要再写这样的服务,调用已有的即可】

1,Service的生命周期

20b81a4ecc55b294c6171959e1054504.gif

2,Service运行方式

以startService()启动服务,系统将通过传入的Intent在底层搜索相关符合Intent里面信息的service。如果服务没有启动则先运行onCreate,然后运行onStartCommand (可在里面处理启动时传过来的Intent和其他参数),直到明显调用stopService或者stopSelf才将停止Service。无论运行startService多少次,只要调用一次stopService或者stopSelf,Service都会停止。使用stopSelf(int)方法可以保证在处理好intent后再停止。onStartCommand ,在2.0后被引入用于service的启动函数,2.0之前为public void onStart(Intent intent, int startId) 。

以bindService()方法启用服务,调用者与服务绑定在了一起,调用者一旦退出,服务也就终止。onBind()只有采用Context.bindService()方法启动服务时才会回调该方法。该方法在调用者与服务绑定时被调用,当调用者与服务已经绑定,多次调用Context.bindService()方法并不会导致该方法被多次调用。采用Context.bindService()方法启动服务时只能调用onUnbind()方法解除调用者与服务解除,服务结束时会调用onDestroy()方法。

3,拥有service的进程具有较高的优先级

官方文档告诉我们,Android系统会尽量保持拥有service的进程运行,只要在该service已经被启动(start)或者客户端连接(bindService)到它。当内存不足时,需要保持,拥有service的进程具有较高的优先级。

1. 如果service正在调用onCreate,onStartCommand或者onDestory方法,那么用于当前service的进程则变为前台进程以避免被killed。

2. 如果当前service已经被启动(start),拥有它的进程则比那些用户可见的进程优先级低一些,但是比那些不可见的进程更重要,这就意味着service一般不会被killed.

3. 如果客户端已经连接到service (bindService),那么拥有Service的进程则拥有最高的优先级,可以认为service是可见的。

4. 如果service可以使用startForeground(int, Notification)方法来将service设置为前台状态,那么系统就认为是对用户可见的,并不会在内存不足时killed。

5. 如果有其他的应用组件作为Service,Activity等运行在相同的进程中,那么将会增加该进程的重要性。

实现前台:

Service如果要防止尽可能不被系统杀掉,需要设置为在前台运行。

1.MainActivity.java

1

package

com.example.helloteacher;

2

3

import

com.example.teacherService.HelloteacherService;

4

import

com.example.teacherService.HelloteacherService2;

5

6

import

android.app.Activity;

7

import

android.content.Intent;

8

import

android.os.Bundle;

9

import

android.util.Log;

10

import

android.view.View;

11

import

android.widget.Button;

12

import

android.widget.TextView;

13

14

public

class

MainActivity

extends

Activity {

15

private

TextView fuction;

16

private

Button start;

17

@Override

18

protected

void

onCreate(Bundle savedInstanceState) {

19

super

.onCreate(savedInstanceState);

20

setContentView(R.layout.activity_main);

21

//

初始化控件

22

init();

23

//

创建进程

24

inProcess();

25

}

26

//

/初始化控件函数

27

private

void

init() {

28

start=

(Button)findViewById(R.id.button1);

29

fuction=

(TextView)findViewById(R.id.tv_bottom_funtion);

30

start.setOnClickListener(

new

StartOnClickListener());

31

fuction.setOnClickListener(

new

FuctionOnClickListener());

32

}

33

//

功能按钮监听实现函数

34

private

final

class

FuctionOnClickListener

implements

View.OnClickListener{

35

36

@Override

37

public

void

onClick(View v) {

38

//

TODO Auto-generated method stub

39

Intent intent =

new

Intent(MainActivity.

this

, FuctionActivity.

class

);

40

startActivity(intent);

41

}

42

}

43

//

进程函数

44

private

void

inProcess(){

45

Intent intent =

new

Intent(MainActivity.

this

, HelloteacherService.

class

);

46

startService(intent);

47

Intent intent2 =

new

Intent(MainActivity.

this

, HelloteacherService2.

class

);

48

startService(intent2);

49

}

50

private

final

class

StartOnClickListener

implements

View.OnClickListener{

51

52

@Override

53

public

void

onClick(View v) {

54

55

}

56

}

57

58

59

}

2.HelloteacherService.java

1

package

com.example.teacherService;

2

3

import

com.example.Receiver.Alarmreceiver;

4

import

com.example.helloteacher.R;

5

6

import

android.app.AlarmManager;

7

import

android.app.Notification;

8

import

android.app.PendingIntent;

9

import

android.app.Service;

10

import

android.content.Intent;

11

import

android.os.IBinder;

12

import

android.os.SystemClock;

13

import

android.util.Log;

14

15

public

class

HelloteacherService

extends

Service {

16

HelloteacherService2 hs2;

17

private

String TAG="HelloteacherService"

;

18

@Override

19

public

void

onCreate() {

20

super

.onCreate();

21

Log.i(TAG, "-->>onCreate"

);

22

}

23

24

@Override

25

public

int

onStartCommand(Intent intent,

int

flags,

int

startId) {

26

Log.i(TAG, "-->>onStartCommand-->>"+

startId);

27

flags =

START_STICKY;

28

29

//

启用前台服务,主要是startForeground()

30

Notification notification =

new

Notification(R.drawable.ic_launcher, "用电脑时间过长了!白痴!"

31

, System.currentTimeMillis());

32

notification.setLatestEventInfo(

this

, "快去休息!!!"

,

33

"一定保护眼睛,不然遗传给孩子,老婆跟别人跑啊。",

null

);

34

//

设置通知默认效果

35

notification.flags =

Notification.FLAG_SHOW_LIGHTS;

36

startForeground(1

, notification);

37

38

AlarmManager manager =

(AlarmManager) getSystemService(ALARM_SERVICE);

39

//

读者可以修改此处的Minutes从而改变提醒间隔时间

40

//

此处是设置每隔55分钟启动一次

41

//

这是55分钟的毫秒数

42

int

Minutes = 55 * 60 * 1000

;

43

//

SystemClock.elapsedRealtime()表示1970年1月1日0点至今所经历的时间

44

long

triggerAtTime = SystemClock.elapsedRealtime() +

Minutes;

45

//

此处设置开启AlarmReceiver这个Service

46

Intent i =

new

Intent(

this

, Alarmreceiver.

class

);

47

PendingIntent pi = PendingIntent.getBroadcast(

this

, 0, i, 0

);

48

//

ELAPSED_REALTIME_WAKEUP表示让定时任务的出发时间从系统开机算起,并且会唤醒CPU。

49

manager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, triggerAtTime, pi);

50

51

return

super

.onStartCommand(intent, flags, startId);

52

}

53

//

监听服务2实现函数

54

55

56

@Override

57

public

IBinder onBind(Intent arg0) {

58

Log.i(TAG, "-->>onBind"

);

59

//

TODO Auto-generated method stub

60

return

null

;

61

}

62

@Override

63

public

void

onDestroy() {

64

Log.i(TAG, "-->>onDestroy"

);

65

super

.onDestroy();

66

67

}

68

}

3.BootReceiver.java

1

package

com.example.Receiver;

2

3

import

android.app.AlarmManager;

4

import

android.app.PendingIntent;

5

import

android.content.BroadcastReceiver;

6

import

android.content.Context;

7

import

android.content.Intent;

8

import

android.os.SystemClock;

9

10

public

class

BootReceiver

extends

BroadcastReceiver {

11

12

/*

要接收的intent源

*/

13

static

final

String ACTION = "android.intent.action.BOOT_COMPLETED"

;

14

15

public

void

onReceive(Context context, Intent mintent)

16

{

17

if

(Intent.ACTION_BOOT_COMPLETED.equals(mintent.getAction())) {

18

//

启动完成

19

Intent intent =

new

Intent(context, Alarmreceiver.

class

);

20

intent.setAction("arui.alarm.action"

);

21

PendingIntent sender = PendingIntent.getBroadcast(context, 0

,

22

intent, 0

);

23

long

firstime =

SystemClock.elapsedRealtime();

24

AlarmManager am =

(AlarmManager) context

25

.getSystemService(Context.ALARM_SERVICE);

26

27

//

10秒一个周期,不停的发送广播

28

am.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, firstime,

29

10 * 1000

, sender);

30

}

31

}

32

33

34

}

4.Alarmreceiver.java

1

package

com.example.Receiver;

2

3

import

com.example.teacherService.HelloteacherService;

4

5

import

android.content.BroadcastReceiver;

6

import

android.content.Context;

7

import

android.content.Intent;

8

9

public

class

Alarmreceiver

extends

BroadcastReceiver {

10

11

@Override

12

public

void

onReceive(Context context, Intent intent) {

13

//

TODO Auto-generated method stub

14

if

(intent.getAction().equals("arui.alarm.action"

)) {

15

Intent i =

new

Intent();

16

i.setClass(context, HelloteacherService.

class

);

17

//

启动service

18

//

多次调用startService并不会启动多个service 而是会多次调用onStart

19

context.startService(i);

20

}

21

}

22

23

}

5.配置文件

AndroidManifest.xml

下面是添加在配置文件中的部分代码:

1

<

activity

android:name

="com.example.helloteacher.FuctionActivity"

/>

2

<

service

android:name

="com.example.teacherService.HelloteacherService"

android:process

=":HelloteacherService"

/>

3

<

service

android:name

="com.example.teacherService.HelloteacherService2"

/>

4

<

uses-permission

android:name

="android.permission.RECEIVE_BOOT_COMPLETED"

>

uses-permission

>

5

<

receiver

android:name

="com.example.Receiver.BootReceiver"

>

6

<

intent-filter

>

7

<

action

android:name

="android.intent.action.BOOT_COMPLETED"

/>

8

intent-filter

>

9

receiver

>

10

<

receiver

android:name

="com.example.Receiver.Alarmreceiver"

>

11

<

intent-filter

>

12

<

action

android:name

="arui.alarm.action"

/>

13

intent-filter

>

14

receiver

>

通过以上的配置,就可以实现Service的前台运行!下面附上效果图:

20b81a4ecc55b294c6171959e1054504.gif

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值