Android中怎么启动关闭Service及功能解释 ._mlj1668956679的博客-程序员ITS203

技术标签: Android Service  

什么是Service?

         解惑:

                1、  Service不是分离开的进程,除非其他特殊情况,它不会运行在自己的进程,而是作为启动运行它的进程的一部分。

                2、  Service不是线程,这意味着它将在主线程里劳作。

        启动service有两种方法:

             1、  Context.startService()

                    调用者与服务之间没有关联,即使调用者退出,服务仍可运行

             2、  Context.bindService()

                    调用者与服务绑定在一起,调用者一旦退出,服务也就终止

Service的生命周期

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

         控制service运行的主要方式有两种,主要是根据onStartCommand方法返回的数值。方法:

         1、START_STICKY

         2、START_NOT_STICKY or START_REDELIVER_INTENT

         这里主要解释这三个变量的意义:

 这里主要解释这三个变量的意义:

          1、  START_STICKY

                 在运行onStartCommand后service进程被kill后,那将保留在开始状态,但是不保留那些传入的intent。不久后service就会再次尝试重新创建,因为保留在开始状态,在创建     service后将保证调用onstartCommand。如果没有传递任何开始命令给service,那将获取到null的intent

  2、  START_NOT_STICKY

                 在运行onStartCommand后service进程被kill后,并且没有新的intent传递给它。Service将移出开始状态,并且直到新的明显的方法(startService)调用才重新创建。因为如果没有传递任何未决定的intent那么service是不会启动,也就是期间onstartCommand不会接收到任何null的intent。

           3、  START_REDELIVER_INTENT

                在运行onStartCommand后service进程被kill后,系统将会再次启动service,并传入最后一个intent给onstartCommand。直到调用stopSelf(int)才停止传递intent。如果在被kill后还有未处理好的intent,那被kill后服务还是会自动启动。因此onstartCommand不会接收到任何null的intent。

          客户端也可以使用bindService来保持跟service持久关联。谨记:如果使用这种方法,那么将不会调用onstartCommand(跟startService不一样,下面例子注释也有解析,大家可试试)。客户端将会在onBind回调中接收到IBinder接口返回的对象。通常IBinder作为一个复杂的接口通常是返回aidl数据。

         Service也可以混合start和bind一起使用。

权限

         要运行service,首先必须在AndroidManifest.xml里申明<service>标签。

         Service能够保护个人的IPC调用,所以在执行实现该调用时前先使用checkCallingPermission(String) 方法检查是否有这个权限。

进程生命周期

         当service运行在低内存的环境时,将会kill掉一下存在的进程。因此进程的优先级将会很重要:

         1、  如果service当前正在执行onCreate、onStartCommand、onDestroy方法,主进程将会成为前台进程来保证代码可以执行完成避免被kill

         2、  如果service已经启动了,那么主进程将会比其他可见的进程的重要性低,但比其他看不见的进程高。因为只有少部分进程始终是用户可见的,因此除非在极度低内存的时候,不然 service是不会被kill的。

         3、  如果有客户端关联到service,那么service永远比客户端重要。也就是说客户端可见,那么service也可见(我理解这里的可见并不是可以看到,而是重要性,因为可见往往就表示重要性高)。

         4、  Service可以使用startForeground API将service放到前台状态。这样在低内存时被kill的几率更低,但是文档后面又写了,如果在极度极度低内存的压力下,该service理论上还是会被kill掉。但这个情况基本不用考虑。

         当然如果service怎么保持还是被kill了,那你可以通过重写onStartCommand返回变量来设置它的启动方式。比如:START_STICKY、START_REDELIVER_INTENT等等,前面已经讨论了它们的作用,这里就不再累赘了

        另外:

        service 的onCreate和onStartCommand 是运行在主线程的,所以如果里面有处理耗时间的任务。两种处理:

1、  请将它们都挪到新的线程里。 

2、  用系统提供的IntentService,它继承了Service,它处理数据是用自身新开的线程。

启动关闭service实例

 

===================main文件========================

package com.services.coms;

import java.io.FileFilter;

import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.text.Html;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;

public class MainService extends Activity {
    private TextView textviewService;
    private Button buttonStart ,buttonStop;
    public static final int CMD_STOP_SERVICE = 0;
    DataReceiver dateReceiver;
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        textviewService=(TextView)findViewById(R.id.textservice);
        buttonStart=(Button)findViewById(R.id.buttonstart);
        buttonStop=(Button)findViewById(R.id.buttonstop);
        buttonStart.setOnClickListener(buttonClick);
        buttonStop.setOnClickListener(buttonClick);
    }
    
    private View.OnClickListener buttonClick =new View.OnClickListener() {
  @Override
  public void onClick(View v) {
   if(v==buttonStart){
    Intent intentService=new Intent(MainService.this,MyService.class);
    startService(intentService);
    Log.i("onStartCommand", "OnClickListener=");
   }else if(v==buttonStop){
    Intent intent=new Intent();
    intent.setAction("AAAAA");
    intent.putExtra("cmd",CMD_STOP_SERVICE);
    sendBroadcast(intent);
   }
   
  }
 };
 private class DataReceiver extends BroadcastReceiver{
  
  @Override
  public void onReceive(Context context, Intent intent) {
   Log.i("onStartCommand", "接受要更新的广播数据="+intent.getStringExtra("data"));
   String Date=intent.getStringExtra("data");
   textviewService.setText(Html.fromHtml("<font color='#0066CC'><u>"+"Service的数据为:"+Date+"</font>"));
  }
 }
 @Override
 protected void onStart() {
  dateReceiver=new DataReceiver();
  IntentFilter intentfilter=new IntentFilter();// 创建IntentFilter对象
  intentfilter.addAction("AAAAA");
  registerReceiver(dateReceiver, intentfilter);// 注册Broadcast Receiver
  super.onStart();
 }
 @Override
 protected void onStop() {
  unregisterReceiver(dateReceiver);// 取消注册Broadcast Receiver
  super.onStop();
 }
 
 
}

===================service文件===================

package com.services.coms;

import java.util.UUID;

import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.res.Configuration;
import android.os.IBinder;
import android.util.Log;

 

public class MyService extends Service {

  CommandReceiver cmdReceiver;
  boolean flag;
 
 @Override
 public void onConfigurationChanged(Configuration newConfig) {
  // TODO Auto-generated method stub
  super.onConfigurationChanged(newConfig);
 }

 @Override
 public void onCreate() {
  cmdReceiver=new CommandReceiver();
  flag=true;
  Log.i("onStartCommand", "onCreate=");
  super.onCreate();
 }

 @Override
 public void onDestroy() {
  this.unregisterReceiver(cmdReceiver);// 取消BroadcastReceiver
  super.onDestroy();
 }

 @Override
 public void onLowMemory() {
  // TODO Auto-generated method stub
  super.onLowMemory();
 }

 @Override
 public void onRebind(Intent intent) {
  // TODO Auto-generated method stub
  super.onRebind(intent);
 }

 @Override
 public void onStart(Intent intent, int startId) {
  // TODO Auto-generated method stub
  super.onStart(intent, startId);
 }

 @Override
 public int onStartCommand(Intent intent, int flags, int startId) {
  Log.i("onStartCommand", "onStartCommand=");
  IntentFilter intentFilter=new IntentFilter();
  intentFilter.addAction("AAAAA");
  registerReceiver(cmdReceiver, intentFilter);
  doJob();// 调用方法启动线程
  
  return super.onStartCommand(intent, flags, startId);
 }

 @Override
 public boolean onUnbind(Intent intent) {
  // TODO Auto-generated method stub
  return super.onUnbind(intent);
 }

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

 //接受广播
 private class CommandReceiver extends BroadcastReceiver{

  @Override
  public void onReceive(Context context, Intent intent) {
   int cmd=intent.getIntExtra("cmd", -1);
   if(cmd==MainService.CMD_STOP_SERVICE){//如果等于0
     flag=false;//停止线程
     stopSelf();//停止服务
   }
  }
  
 }
 public void doJob(){
  new Thread(){
   @Override
   public void run() {
    while(flag){//如果==true执行发送广播
     try {
      Thread.sleep(1000);//休眠1秒
     } catch (InterruptedException e) {
      e.printStackTrace();
     }
     Log.i("onStartCommand", "run=");
     Intent intent=new Intent();
     intent.setAction("AAAAA");
     intent.putExtra("data",UUID.randomUUID()+"");
     sendBroadcast(intent);//发送广播名称aaaaa 参数名字data
     
    }
   }
  }.start();
 }
}


==================layout文件=====================

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    >
<TextView  
    android:layout_width="fill_parent" 
    android:layout_height="wrap_content" 
    android:text="@string/hello"
    />
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:id="@+id/textservice"
></TextView>
<Button
android:id="@+id/buttonstart"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="启动服务"
android:gravity="center"
></Button>
<Button
android:id="@+id/buttonstop"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="停止服务"
android:gravity="center"
></Button>    
</LinearLayout>


版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/mlj1668956679/article/details/8969732

智能推荐

大中型企业的天网:Apache Geode_weixin_33743880的博客-程序员ITS203

2016年11月21日,Apache软件基金会(the Apache Software Foundation,ASF)宣布 Apache Geode已从Apache孵化器毕业成为顶级项目(Top-Level Project),表明该项目的社区和产品已根据ASF的精英流程和原则得到良好管理。 \初识Apache Geode\Apache Geode是一个相当成熟、强健的的数据管理平台,提供实时的、一...

分析:苹果iCloud战略意义大于iPhone 5_iteye_2060的博客-程序员ITS203

苹果计划发布最新版iPhone,但iCloud的发布更有战略意义。如果对苹果发布产品的重要性进行排名,其顺序应该是:iCloud、iOS 5,然后才是iPhone 5。苹果iCloud自WWDC大会上亮相后,似乎已经成为旧闻,该服务有可能腾飞。随着苹果发布iCloud,苹果由一家关注PC的厂商向关注多种设备厂商转型的时代即将到来。如果iCloud半途而废或出现其它问题,将是苹果辉煌史上的一个污点...

WPF 获得控件的父控件_87222643hxq的博客-程序员ITS203_wpf 获取父控件

通过VisualTreeHelper去取就行了。代码参考:前台: 后台: private void btn_Click(object sender, RoutedEventArgs e) { Button btn = sender as Button;

电脑怎么录屏,什么录屏软件最好_qq_43173244的博客-程序员ITS203

因为工作或者是娱乐,我们经常需要使用电脑去录制屏幕视频。那么如何录屏呢,使用什么软件可以录屏呢?其实电脑录屏整体来说还是比较容易的,有一款录屏软件就能轻松驾驭了,比如说windows自带的录屏软件,下面小编便教大家如何录制电脑屏幕。  使用方法  一、如果录制的是一些比较简单的视频,比如就几秒长短的视频,我们可以使用windows自带录屏软件。首先我们win+r,调出运行窗口。  二、然...

python循环语句while教案_零基础学习 Python 之 while 循环语句_weixin_39727976的博客-程序员ITS203

写在之前大家好,这是发布在我微信公众号「Python空间」的第 19 篇文章,欢迎关注,期待和你的交流。大家好,这里是零基础学习 Python 系列,在这里我将从最基本的Python 写起,然后再慢慢涉及到高阶以及具体应用方面。我是完全自学的 Python,所以很是明白自学对于一个人的考验,所以在这里我会尽我最大的努力,把 Python 尽可能简单的表述清楚,让更多想要学习 Python 的朋友能...

入门经典-5.2.4映射:map-113-uva156反片语-string排序,map难度:1_费马最后定理的博客-程序员ITS203

#include&amp;lt;cstdio&amp;gt;#include&amp;lt;iostream&amp;gt;#include&amp;lt;map&amp;gt;#include&amp;lt;vector&amp;gt;#include&amp;lt;cstring&amp;gt;#include&amp;lt;algorithm&amp;gt;using namespace std;map&amp;lt;string,int&amp;gt; cnt;vector&amp

随便推点

任正非:华为是世界上最穷的高科技公司,比任何一个公司都穷_lin000001的博客-程序员ITS203

近日任正非接受了CNN采访,当被问及是否对华为未来的生存及盈利担心时,任正非表示我们对华为的生存是不会担心的。近日华为的第一季度的财报已经发布了,我们看到了华为恐怖的增长,总营销达到了1700多亿元,在接受采访的时候任正非也表示,他们已经感到今年的增长非常的猛,要控制合理的增长。在本次接受采访的时候,任正非表示华为要像苹果学习,要把产品的价格在做高一点,让所有的竞争对手都有生存空间,而不是...

iOS-runtime_Maybe贰货的博客-程序员ITS203

什么是Objective-C runtime?简单来说,Objective-C runtime是一个实现Objective-C语言的C库。对象可以用C语言中的结构体表示,而方法(methods)可以用C函数实现。事实上,他们 差不多也是这么干了,另外再加上了一些额外的特性。这些结构体和函数被runtime函数封装后,Objective-C程序员可以在程序运行时创建,检 查,修改类,对象和它

jdbc如何到连接teradata,hive,db2,gbase数据库,示例._阿弥陀佛大帝的博客-程序员ITS203

在java开发中,我们可能要对不同的数据库进行操作.这里给出了jdbc连接各常用数据库的配置.   一.jdbc连接DB2数据库:1,需要的驱动包:下载地址:http://download.csdn.net/detail/csdn1152789046/96334842.连接配置示例:db2.driver=com.ibm.db2.jcc.DB2Driverdb2.url=jdbc

街头篮球一直提示服务器维护怎么解决,街头篮球为什么进不去 街头篮球进不去怎么办..._科技挖掘机的博客-程序员ITS203

街头篮球手游为什么进不去?街头篮球手游进不去解决办法是什么?今天小编要来好好的给大家说说关于街头篮球手游无法进入的原因已经解决办法。街头篮球手游无法进入游戏的原因无法就两种,一是游戏官方的问题、而是玩家的问题,今天小编就根据这两个方面来说说。街头篮球手游官方问题1、游戏维护:正常游戏在维护期间都是无法登入的,维护也分为:停机和停机。就像本次维护(12月20日)就是停机维护。官方在游戏维护前一天都会...

Java泛型的作用及优点有哪些_deppbluesky的博客-程序员ITS203_java泛型的作用

Java泛型是J2 SE1.5中引入的一个新特性,其本质是参数化类型,也就是说所操作的数据类型被指定为一个参数这种参数类型可以用在类、接口和方法的创建中,分别称为泛型类、泛型接口、泛型方法。作用第一是泛化。可以用T代表任意类型Java语言中引入泛型是一个较大的功能增强不仅语言、类型系统和编译器有了较大的变化,以支持泛型,而且类库也进行了大翻修,所以许多重要的类,比如集合框架,都已经成为泛型化的了,这带来了很多好处。第二是类型安全。泛型的一个主要目标就是提高Java程序的类型安全,使用泛型可以

php宝宝起名,宝宝在线起名取名大全_weixin_39983051的博客-程序员ITS203

宝宝在线起名测名大全是yw11易名网为大家精心准备的宝宝在线起名和宝宝在线测名大全。宝宝在线起名大全在线起名也就是通过网络在线提供起名测名服务,易名网综合多年起名测名经验,根据姓名学理论,结合宝宝生辰八字,周易五行,名字三才五格综合开发的在线免费起名测名系统,您只需要输入宝宝的出生时间,性别,姓氏,在线起名机器人并可以根据您输入的宝宝生辰八字,喜用神,来自动生成三才五格得分80分以上的好名字供您宝...

推荐文章

热门文章

相关标签