问答文章1 问答文章501 问答文章1001 问答文章1501 问答文章2001 问答文章2501 问答文章3001 问答文章3501 问答文章4001 问答文章4501 问答文章5001 问答文章5501 问答文章6001 问答文章6501 问答文章7001 问答文章7501 问答文章8001 问答文章8501 问答文章9001 问答文章9501

android开发怎么让个推服务不被手机系统杀掉

发布网友 发布时间:2022-04-21 05:44

我来回答

1个回答

热心网友 时间:2022-06-18 07:23

服务是一个应用程序组件,可以在后台执行长时间运行的操作,不提供用户界面。一个应用程序组件可以启动一个服务,它将继续在后台运行,即使用户切换到另一个应用程序。此外,一个组件可以绑定到一个服务与它交互,甚至执行进程间通信(IPC)。例如,一个服务可能处理网络通信,播放音乐,执行文件I/O,或与一个内容提供者交互,都在后台执行。
一个服务本质上讲有两种形式:
Started 启动的
started 形式的服务是指当一个应用组件(比如 activity )通过startService()方法开启的服务。一旦开启,该服务就可以 无限期 地在后台运行,哪怕开启它的组件被销毁掉。
通常,开启的服务执行一个单独的操作且并不向调用者返回一个结果。
比如,可能从网络进行下载或者上传一个文件。当任务完成,服务就该自我停止。
Bound 绑定的
bound 形式的服务是指一个应用组件通过调用 bindService() 方法与服务绑定。一个绑定的服务提供一个客户-服务端接口,以允许组件与服务交互,发送请求,获得结果,甚至执行进程间通信。一个绑定的服务只和与其绑定的组件同时运行。多个组件可以同时绑定到一个服务,但当全部接触绑定后,服务就被销毁。
虽然分这两类,但是一个服务可以同时使用这两种方式——可以用 started 无限期的运行,同时允许绑定。只需要在服务中实现两个回调方法: onStartCommand() 允许组件开启服务, onBind() 允许绑定。
不论应用程序是怎么起服务的, 任何 应用程序都可以用这个服务。同样的,任何组件可以使用一个 Activity 通过传递 Intent 开启服务。你也可以在配置文件设置服务为私有来防止其他应用访问该服务。
注意: 一个服务在进程中的主线程运行——一个服务 不会 创建自己的线程,也 不会 在另外的进程运行(除非另外指定)。这意味着,如果服务需要做一些频繁占用CPU的工作或者会发生阻塞的操作,你需要在服务中另开线程执行任务。这可以降低产生ANR的风险,提高用户体验。
基础
创建一个服务需要建立一个 Service 相关的子类,然后需要实现一些回调方法,好在不同的生命周期内做对应处理和绑定服务,比较重要的方法如下:
onStartCommand()
当其他组件,如 activity 请求服务启动时,系统会调用这个方法。一旦这个方法执行,服务就开始并且无限期的执行。如果实现这个方法,当这个服务完成任务后,需要你来调用 stopSelf() 或者 stopService() 停掉服务。如果只想提供绑定,不需要自己实现这个方法。
onBind()
当有其他组件想通过 bindService() 方法绑定这个服务时系统就会调用此方法。在实现的方法里面,必须添加一个供客户端使用的接口通过返回一个 IBinder 来与服务通信,这个方法必须实现。当然不想允许绑定的话,返回 null 即可。
onCreate()
服务第一次建立的时候会调用这个方法,执行一次性设置程序,在上面2个方法执行前调用。如果服务已存在,则不执行该方法。
onDestroy()
服务不再使用则使用该方法。服务应该实现这个方法来清理诸如线程,注册的*等资源。这是最后调用的方法。
安卓系统只会在内存占用很高,必须恢复系统资源供当前运行程序的情况下强制停掉一个运行中的服务。如果服务绑定在当前运行的程序中,就几乎不会被杀掉,如果服务声明了在前台运行(其实在后台,只是给系统一个错的信息来提高优先级),就几乎不会被杀掉。另外,如果一个服务正在运行,且运行了很久,系统就会根据运行时间把其排在后台任务列表的后面,则这个服务很容易被杀掉。根据onStartCommand() 的返回值设置,服务被杀掉后仍可以在资源充足的条件下立即重启。
是用一个服务好还是开一个线程好
一个服务就是一个可以忽略交互,在后*立运行的组件,如果你需要这样就用服务
如果你需要在用户与程序交互时在主线程外执行任务,那就开个线程吧。
比如想播放音乐,但只在程序运行时播放,你可能在 onCreate() 开一个线程,在 onStart() 中开启它,在 onStop() 停止它。也可以考虑使用 AsyncTask 或者HandlerThread 取代一般的线程。
记住,如果使用一个服务,它还是默认在主线程中运行,如果会发生阻塞,还是要在服务中另开线程的。
在 manifest 文件声明服务
要使用服务就必须在 manifest 文件声明要用的所有服务,只用在<application> 标签内添加子标签 <service> 即可。
<manifest ...>
...
<application ...>
<service android:name=".ExampleService"
android:enabled=["true" | "false"]
android:exported=["true" | "false"]
android:isolatedProcess=["true" | "false"]
android:label="string resource"
android:icon="drawable resource"
android:permission="string"
android:process="string" >
...
</service>
</application>
</manifest>

下面对 service 标签属性做说明
android:name
你所编写的服务类的类名,可填写完整名称,包名+类名,如com.example.test.ServiceA ,也可以忽略包名,用 . 开头,如 .ServiceA,因为在 manifest 文件开头会定义包名,它会自己引用。
一旦你发布应用,你就不能改这个名字(除非设置 android:exported="false"),另外 name 没有默认值,必须定义。
android:enabled
是否可以被系统实例化,默认为 true
因为父标签 <application> 也有 enable 属性,所以必须两个都为默认值true 的情况下服务才会被激活,否则不会激活。
android:exported
其他应用能否访问该服务,如果不能,则只有本应用或有相同用户ID的应用能访问。当然除了该属性也可以在下面 permission 中*其他应用访问本服务。
这个默认值与服务是否包含意图过滤器 intent filters 有关。如果一个也没有则为 false
android:isolatedProcess
设置 true 意味着,服务会在一个特殊的进程下运行,这个进程与系统其他进程分开且没有自己的权限。与其通信的唯一途径是通过服务的API(binding and starting)。
android:label
可以显示给用户的服务名称。如果没设置,就用 <application> 的 lable 。不管怎样,这个值是所有服务的意图过滤器的默认 lable 。定义尽量用对字符串资源的引用。
android:icon
类似 label ,是图标,尽量用 drawable 资源的引用定义。
android:permission
是一个实体必须要运行或绑定一个服务的权限。如果没有权限,startService() , bindService() 或 stopService() 方法将不执行,Intent 也不会传递到服务。
如果属性未设置,会由 <application> 权限设置情况应用到服务。如果两者都未设置,服务就不受权限保护。
android:process
服务运行所在的进程名。通常为默认为应用程序所在的进程,与包名同名。<application> 元素的属性 process 可以设置不同的进程名,当然组件也可设置自己的进程覆盖应用的设置。
如果名称设置为冒号 : 开头,一个对应用程序私有的新进程会在需要时和运行到这个进程时建立。如果名称为小写字母开头,服务会在一个相同名字的全局进程运行,如果有权限这样的话。这允许不同应用程序的组件可以分享一个进程,减少了资源的使用。
创建“启动的”服务
启动的(started)服务由 startService(Intent) 方法启动,在服务中的onStartCommand() 方法里获得 Intent 信息。关闭则由服务自己的方法 stopSelf() 或者由启动服务的地方调用 stopService(Intent) 方法来关闭。并不会因为启动服务的应用程序销毁而关闭。
示例,一个应用需要保存数据到远程数据库,这时启动一个服务,通过创建启动的服务给服务传递数据,由服务执行保存行为,行为结束再自我销毁。因为服务跟启动它的应用在一个进程的主线程中,所以对于耗时的操作要起一个新的线程去做。
//activity中
Intent intent = new Intent(MainActivity.this, ServiceA.class);
intent.putExtra("name", strName);
startService(intent);
//service中
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
// TODO Auto-generated method stub
// 获取数据
String strName = intent.getStringExtra("name");
// ... 数据库操作
new Thread(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
耗时的操作
}
}).run();
return Service.START_STICKY;
}

写服务有2种,继承 service 或者 IntentService 。后者是前者的子类。前者包含上面介绍的各种方法,用于普通的服务。后者可以自己开一个工作线程一个接一个处理多个请求。
继承IntentService
大多数服务不需要同时处理多个请求,继承 IntentService 是最好的选择
IntentService处理流程
创建默认的一个 worker 线程处理传递给 onStartCommand() 的所有 intent ,不占据应用的主线程
创建一个工作队列一次传递一个 intent 到你实现的 onHandleIntent() 方法,避免了多线程
在所以启动请求被处理后自动关闭服务,不需要调用 stopSelf()
默认提供 onBind() 的实现,并返回 null
默认提供 onStartCommand() 的实现,实现发送 intent 到工作队列再到你的onHandleIntent() 方法实现。
这些都加入到 IntentService 中了,你需要做的就是实现构造方法和onHandleIntent() ,如下:
public class HelloIntentService extends IntentService {
/**
* A constructor is required, and must call the super IntentService(String)
* constructor with a name for the worker thread.
*/
public HelloIntentService() {
super("HelloIntentService");
}
/**
* The IntentService calls this method from the default worker thread with
* the intent that started the service. When this method returns, IntentService
* stops the service, as appropriate.
*/
@Override
protected void onHandleIntent(Intent intent) {
// Normally we would do some work here, like download a file.
// For our sample, we just sleep for 5 seconds.
long endTime = System.currentTimeMillis() + 5*1000;
while (System.currentTimeMillis() < endTime) {
synchronized (this) {
try {
wait(endTime - System.currentTimeMillis());
} catch (Exception e) {
}
}
}
}
}

如果需要重写其他回调方法,如 onCreate() , onStartCommand() 等,一定要调用super() 方法,保证 IntentService 正确处理 worker 线程,只有 onHandleIntent()和 onBind() 不需要这样。如:
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Toast.makeText(this, "service starting", Toast.LENGTH_SHORT).show();
return super.onStartCommand(intent,flags,startId);
}

继承Service
继承 Service 就可以实现对请求多线程的处理,前面介绍了 service 的生命周期,可以按照生命周期实现方法。就不放示例了。
onStartCommand() 的返回值
返回一个整型值,用来描述系统在杀掉服务后是否要继续启动服务,返回值有三种:
START_NOT_STICKY
系统不重新创建服务,除非有将要传递来的 intent 。这是最安全的选项,可以避免在不必要的时候运行服务。
START_STICKY
系统重新创建服务并且调用 onStartCommand() 方法,但并不会传递最后一次传递的 intent ,只是传递一个空的 intent 。除非存在将要传递来的 intent ,那么就会传递这些 intent 。这个适合播放器一类的服务,不需要执行命令,只需要独自运行,等待任务。
START_REDELIVER_INTENT
系统重新创建服务并且调用 onStartCommand() 方法,传递最后一次传递的intent 。其余存在的需要传递的intent会按顺序传递进来。这适合像下载一样的服务,立即恢复,积极执行。
如果想从服务获得结果,可以用广播来处理
创建“绑定的”服务
用 bindService() 方法将应用组件绑定到服务,建立一个长时间保持的联系。
如果需要在 activity 或其他组件和服务交互或者通过进程间通信给其他应用程序提供本应用的功能,就需要绑定的服务。
建立一个绑定的服务需要实现 onBind() 方法返回一个定义了与服务通信接口的IBinder 对象。其他应用程序组件可以调用 bindService() 方法获取接口并且调用服务上的方法。
创建一个绑定的服务,第一件事就是定义一个说明客户端与服务通信方式的接口。这个接口必须是 IBinder 的实现,并且必须要从 onBind() 方法返回。一旦客户端接收到了 IBinder ,就可以通过这个接口进行交互。
多个客户端可以绑定到一个服务,可以用 unbindService() 方法解除绑定,当没有组件绑定在服务上,这个服务就会被销毁。
//activity中
private ServiceConnection connB = new ServiceConnection() {

@Override
public void onServiceDisconnected(ComponentName name) {
// TODO Auto-generated method stub
Log.v(tag, "Service B disconnected");
}

@Override
public void onServiceConnected(ComponentName name, IBinder service) {
// TODO Auto-generated method stub
Log.v(tag, "Service B connected");
MyBinderB binder = (MyBinderB) service;
ServiceB SB = binder.getService();
SB.showLog();
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

findViewById(R.id.button1).setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
Intent a = new Intent(MainActivity.this, ServiceB.class);
bindService(a, connB, BIND_AUTO_CREATE);
}
}

//ServiceB
public class ServiceB extends Service {
public void showLog() {
Log.i(tag, "serviceB-->showLog()");
}

public class MyBinderB extends Binder {

public ServiceB getService() {
return ServiceB.this;
}
}

private MyBinderB myBinderB = new MyBinderB();

@Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return myBinderB;
}
}

启动前台服务
前台服务是被认为是用户已知的正在运行的服务,当系统需要释放内存时不会优先杀掉该进程。前台进程必须发一个 notification 在状态栏中显示,直到进程被杀死。因为前台服务会一直消耗一部分资源,但不像一般服务那样会在需要的时候被杀掉,所以为了能节约资源,保护电池寿命,一定要在建前台服务的时候发notification ,提示用户。当然,系统提供的方法就是必须有 notification 参数的,所以不要想着怎么把 notification 隐藏掉。
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
// TODO Auto-generated method stub
Intent notificationIntent = new Intent(this, MainActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);
Notification noti = new Notification.Builder(this)
.setContentTitle("Title")
.setContentText("Message")
.setSmallIcon(R.drawable.ic_launcher)
.setContentIntent(pendingIntent)
.build();
startForeground(12346, noti);
return Service.START_STICKY;
}

startForeground() 方法就是将服务设为前台服务。参数12346就是这个通知唯一的id,只要不为0即可。
android push 推送服务 如何做到app进程被清理掉还能收到推送 我看有少...

在国内 Android 生态中,推送通道都是由终端与云端之间的长链接来维持,严重依赖于应用进程的存活状态,软件推出后台运行后会接受不到消息推送。针对这个问题,如今一些手机厂家会在自家 rom 中做系统级别的推送通道,再由系统分发给各个 app,以此提高在自家 rom 上的推送送达率 极光推送率先和国内包括华为...

为什么第三方Android推送SDK要互相唤醒app?

据我所知,凡是使用个推的App推送链路会共享,程序被一键杀掉后能通过用户自动打开高频应用从而使其他App推送链路畅通。这不仅实现了各个应用之间的互相看护,还大大减少了应用对手机电量以及流量的消耗。普通的推送技术采用的是每个应用单独一个通道,一旦进程被杀死,应用就会和服务器失去连接。通道被单方面...

安卓sdk版本用哪个好?

方法/步骤:在网站上下载android-sdk的最新版本,小编下载的是android-sdk_r2版本的,然后直接解压到磁盘目录下面.完成android-sdk的下载安装工作后,我们打开Eclipse软件,会出现一个需要安装android-sdk的提示。Android应用开发一般情况下的话,SDK测试的时候用的都是最低版本,开发的时候用的是最新的版本,...

国内有哪些第三方 Android 推送服务平台?

5、个推。推荐可以使用极光推送服务平台。深圳市和讯华谷信息技术有限公司(极光 Aurora Mobile,纳斯达克股票代码:JG)在2011年成立,是中国领先的开发者服务提供商,专注于为开发者提供稳定高效的消息推送、一键认证以及流量变现等服务,助力开发者的运营、增长与变现。同时,极光的行业应用已经拓展至市场洞...

Android 上开发国内应用都用什么推送? 海外可以用 GCM, 国内呢?_百 ...

我现在的解决方案是用小米来推动所有的手机,不要用华为的手机。这样,MIUI和emui都有自己的体系级推送,然后其他应用程序运用小米来推送,也能够调用我的push通道,这也很脏。然后把它们放进jar包里。目前国内比较有名的就是这几个了。其实国外的比国内的要好很多,但是既然你只想要国产的,那我只能给...

android 推送服务个推和极光哪个好

两个都挺不错的相对来说,极光更适合选择。极光全新打造的标志性产品,极光UMS(统一消息系统)不仅整合了APP、微信公众号、微信小程序、短信、邮件、支付宝生活号、钉钉7大消息通道,并且通过灵活的发送路由策略进行发送;在保证消息送达及时准确的同时,降低了对用户的打扰以及单纯使用短信通知造成的高昂...

android push 是代表着什么意思?

1、C2DM内置于Android的2.2系统上,无法兼容老的1.6到2.1系统;2、必须运行android,并且安装Market,至少有一个登录的google账号。3、C2DM需要依赖于Google官方提供的C2DM服务器,由于国内的网络环境,这个服务经常不可用,是消息阻塞,不能对送到终端。方案二:利用MQTT协议,broker做代理服务器,但是...

消息推送 - 极光 VS 个推

即使后台服务时也不容易被系统杀死,也就实现触达率更高更精确。iOS 端的推送是基于苹果推送 APNs 通道,需要在第三方推送平台上配置苹果的推送证书,进而转推到苹果服务器来实现业务消息通知。苹果端 App 也不存在长驻内存这种情况,但在不开应用的情况下可以实现离线推送。苹果的推送精准率要高于安卓。

消息推送选择什么方案对服务器压力最小?

接入他们第三方推送对服务器压力最小。开发者可以节省 90% 的成本,而用户在推送上每月平均只会花掉 0.8-1.2M 的流量,是个流量和耗电量都可控的推送。自主开发的推送在用户到达一定规模后容易让服务器面临不可控的压力,甚至崩溃。第三方推送建议用极光推送,极光推送作为较成熟的推送平台,通过集成...

如何实现消息推送功能

消息推送(Push)就是通过服务器把内容主动发送到客户端的过程。运营人员通过自己的产品或第三方工具对用户移动设备进行主动消息推送。完成推送后,消息通知会展示在移动设备的锁定屏幕及通知栏上,用户点击通知即可去往相应页面。现在流行的消息推送实现方式,主要为长链接方式实现。其原理是客户端主动和服务器...

用kotlin开发android android开发用什么语言 android开发框架 android开发三大框架 android开发小项目 Android app开发 android开发应用语言 android新开发语言 android开发语言选择
声明声明:本网页内容为用户发布,旨在传播知识,不代表本网认同其观点,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。E-MAIL:11247931@qq.com
2012 安徽省庐江县各所高中今年的中考预计录取分数线 庐江县一中二中三中招多少新生 庐江中考639分能上二中吗2011年 刚开通4g飞享套餐,但这个要钱么 梦见好几条小蛇爬进了屋里面还有一条爬到了自己腿上然后被吓醒了, 阿尔赛纳·温格5%信任 阿尔赛纳·温格经典语录 阿尔赛纳·温格个人经历 阿尔赛纳·温格温格 谁知男儿半夜心 出自哪里?有没有形容女人的类似诗句?谢谢 APP推广android推广有哪些? android手机推荐! android个推推送,设置别名 android个推怎么关闭推送 Android 个推推送 通知栏是什么原理 Android app消息推送 百度 极光 个推 信鸽哪个好一些 android应用如何进行推广 android push 是代表着什么意思? android 五大应用开发框架是什么 android 推送服务个推和极光哪个好 花5元购买腾讯电影单片 付款后不能看,怎么解决? 同学聚会照片曝光,画面无法描述,家人能放心吗? 新年的多种习俗 邀请家人聚餐怎么通知 元旦和家人聚餐的说说 森林里再次聚会连续五张怎么画? 从腊月二十三到过年的顺口溜 元旦家庭聚会创意小游戏 数字一怎么画 中秋节吃月饼怎么画? 404 Not Found 安卓手机怎么上推啊? android怎么接收个推平台发过来的推送消息 android个推推送什么时候获取到clientid android 个推自定义通知栏怎么做 学习android推荐是有什么书? 如何推广自己开发的&nbsp;Android&nbsp;应用? android 百度推聊如何标识不同的用户 企业微信会议没有添加参与人能进入吗 企业微信直接在工作台发起会议谁会收到 iphone 6s plus屏幕进了消毒液 上海苹果iPhone6s plus屏幕里面有进灰尘怎么办 iphone6s的屏幕会进灰吗进灰怎么办 iphone6s plus屏幕里面进灰尘怎么办? 苹果6splus进水后屏幕失灵怎么办? 苹果6s plus屏幕进灰,怎么办? iphone6s plus屏幕进水会怎么样 苹果6s plus怎么设置显示在屏幕上? 苹果6splus屏幕进汽油有什么好办法 6splus显示住屏幕不能运行