码迷,mamicode.com
首页 > 移动开发 > 详细

Android——服务

时间:2015-11-06 12:45:37      阅读:349      评论:0      收藏:0      [点我收藏+]

标签:

服务默默的在后台工作着,执行着不需要和用户交互的工作。

服务依赖于应用程序进程而存活

作为四大组件之一,服务具备共同的特点——需要在AndroidManifest中注册

Android多线程编程

 需要注意的是——一定不要在子线程中进行UI操作,否则会阻塞主线程出现异常

 1     /** 主要的逻辑是在这里完成,但是考虑到:服务默认是在主线程执行的,如果在这里进行比较费时的操作<br/>
 2      * 就容易出现ANR(Application Not Responding).<br/>
 3      * 所以标准的写法是在这里新建一个子线程执行逻辑处理<br/>
 4      * 但是:这样做了之后,必须要使用stopService或stopSelf才能停得下来
 5      */
 6     @Override
 7     public int onStartCommand(Intent intent, int flags, int startId) {
 8         Log.d("test", "service onStartCommand");
 9         new Thread(new Runnable() {
10             
11             @Override
12             public void run() {
13                 // 逻辑处理——不能进行UI更新
14                 // ...
15                 // 这里处理完之后调用停止服务
16                 stopSelf();
17                 
18             }
19         }).start();
20         return super.onStartCommand(intent, flags, startId);
21     }

 

通过异步消息处理机制进行UI操作

在主线程定义一个handler

    public static final int SHOW_RESPONSE = 0;
    private Handler handler = new Handler() {

        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
            case SHOW_RESPONSE:
                String response = (String) msg.obj;
                // 进行UI更新:根据子线程换回来的msg.obj的值和msg.what的值break;

            default:
                break;
            }
        }

    };

 

子线程通过handler发送数据

        new Thread(new Runnable() {

            @Override
            public void run() {try {
// 将获取到的数据交给Handler处理
                    Message msg = new Message();
                    msg.what = SHOW_RESPONSE;
                    msg.obj = 对象; 
                    handler.sendMessage(msg);
                } catch (IOException e) {
                    e.printStackTrace();
                } finally {
                    }
                }

            }
        }).start();

 

技术分享

1.在主线程中创建Handler(处理者)对象,重写handMessage()方法,在该方法中进行UI操作

2.当子线程需要UI更新时,new一个Message(消息)对象,通过handler发送这个消息,包括.what,.obj等

3.消息会被发送到消息队列中,Looper(消息队列管家)会循环从队列中尝试取出消息,并转给handler

4.handler收到消息后,就会调用handMessage方法,进行UI更新操作

使用AsyncTask

主要方法

1.onPreExecute(),在execute(Params... params)被调用后立即执行,一般用来在执行后台任务前对UI做一些标记。

2.doInBackground(Params... params),在onPreExecute()完成后立即执行,用于执行较为费时的操作,此方法将接收输入参数和返回计算结果。在执行过程中可以调用publishProgress(Progress... values)来更新进度信息。

3.onProgressUpdate(Progress... values),在调用publishProgress(Progress... values)时,此方法被执行,直接将进度信息更新到UI组件上。

4.onPostExecute(Result result),当后台操作结束时,此方法将会被调用,计算结果将做为参数传递到此方法中,直接将结果显示到UI组件上。

后续待看

在doInBackground中进行耗时逻辑操作,在onProgressUpdate中进行UI操作

服务的基本用法

定义服务

public class MyService extends Service {

    @Override
    public IBinder onBind(Intent intent) {
        // 当活动与服务绑定的时候,这个方法就会被执行
        return null;
    }

    @Override
    public void onCreate() {
        // 主要初始化
        super.onCreate();
        Log.d("test", "service onCreate");
    }

    /** 主要的逻辑是在这里完成,但是考虑到:服务默认是在主线程执行的,如果在这里进行比较费时的操作,
     * 就容易出现ANR(Application Not Responding).<br/>
     * 所以标准的写法是在这里新建一个子线程执行逻辑处理<br/>
     * 但是:这样做了之后,必须要使用stopService或stopSelf才能停得下来
     */
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.d("test", "service onStartCommand");
        new Thread(new Runnable() {
            
            @Override
            public void run() {
                // 逻辑处理
                // ...
                // 处理完之后调用停止服务
                stopSelf(); 
            }
        }).start();
        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    public void onDestroy() {
        // 摧毁前调用
        super.onDestroy();
        Log.d("test", "service onDestroy"); 
    }
    

}

 

开启服务——和活动很相似!!

            intent = new Intent(MainActivity.this, MyService.class);
            // 启动服务
            startService(intent);

 

停止服务

            intent = new Intent(MainActivity.this, MyService.class);
            // 暂停服务,也可用stopSelf()
            stopService(intent);

 

注册服务——在application中

<service android:name="com.example.servicetest.MyService"></service>

 

活动与服务的通信——Binder

通常要做到:活动要让服务干活了,说一下立马行动;活动要知道服务的活干的怎么样了,服务要能立马汇报

1.在服务中定义一个Binder对象,该对象具有干活的方法

2.在onBind方法中,将改对象返回

3.在活动中也定义一个该Binder对象,用于接收onBind返回的对象

4.活动中定义一个ServiceConnection对象,重写onServiceConnected,onServiceDisconnected方法,并在onServiceConnected中为Binder对象赋值

5.调用bindService(intent, conn, BIND_AUTO_CREATE)绑定,绑定之后,就可以通过binder对象干活了

技术分享
  1 package com.example.servicetest;
  2 
  3 import com.example.servicetest.MyService.DownloadBinder;
  4 
  5 import android.app.Activity;
  6 import android.content.ComponentName;
  7 import android.content.Intent;
  8 import android.content.ServiceConnection;
  9 import android.os.Bundle;
 10 import android.os.IBinder;
 11 import android.util.Log;
 12 import android.view.View;
 13 import android.view.View.OnClickListener;
 14 import android.widget.Button;
 15 import android.widget.Toast;
 16 
 17 
 18 public class MainActivity extends Activity implements OnClickListener{
 19 
 20     private Button startButton;
 21     private Button stoptButton;
 22     private Button bindButton;
 23     private Button unbindButton;
 24     private Button workButton;
 25     private Button progressButton;
 26     private Button intentServiceButton;
 27     private MyService.DownloadBinder downloadBinder = null;
 28     private  ServiceConnection conn = new ServiceConnection() {
 29         
 30         @Override
 31         public void onServiceDisconnected(ComponentName name) {
 32             // 连接意外丢失时
 33             
 34         }
 35         
 36         @Override
 37         public void onServiceConnected(ComponentName name, IBinder service) {
 38             // 连接成功时
 39             downloadBinder = (DownloadBinder) service;
 40             
 41         }
 42     };
 43     
 44     @Override
 45     protected void onCreate(Bundle savedInstanceState) {
 46         super.onCreate(savedInstanceState);
 47         setContentView(R.layout.activity_main);
 48         
 49         startButton = (Button) findViewById(R.id.start);
 50         stoptButton = (Button) findViewById(R.id.stop);
 51         bindButton = (Button) findViewById(R.id.bind);
 52         unbindButton = (Button) findViewById(R.id.unbind);
 53         workButton = (Button) findViewById(R.id.start_work);
 54         progressButton = (Button) findViewById(R.id.re_progress);
 55         intentServiceButton = (Button) findViewById(R.id.start_intent_service);
 56         startButton.setOnClickListener(this);
 57         stoptButton.setOnClickListener(this);
 58         bindButton.setOnClickListener(this);
 59         unbindButton.setOnClickListener(this);
 60         workButton.setOnClickListener(this);
 61         progressButton.setOnClickListener(this);
 62         intentServiceButton.setOnClickListener(this);
 63         
 64     }
 65 
 66     @Override
 67     public void onClick(View v) {
 68         Intent intent;
 69         switch (v.getId()) {
 70         case R.id.start:
 71             intent = new Intent(this, MyService.class);
 72             // 启动服务
 73             startService(intent);
 74             break;
 75         case R.id.stop:
 76             intent = new Intent(this, MyService.class);
 77             // 暂停服务
 78             stopService(intent);
 79             break;
 80         case R.id.bind:
 81             intent = new Intent(this, MyService.class);
 82             // 绑定服务——BIND—_AUTO_CREATE标志位,表示活动与服务绑定后自动创建服务,调用服务的onCreate方法,但不调用onStartCommand
 83             bindService(intent, conn, BIND_AUTO_CREATE);
 84             break;
 85         case R.id.unbind:
 86             // 解除绑定服务
 87             unbindService(conn);
 88             break;
 89         case R.id.start_work:
 90             // 让服务开始干活——这里的判断条件还不明白
 91             if(downloadBinder!=null){
 92                 downloadBinder.startDownload();
 93             }else {
 94                 Toast.makeText(this, "ensure binded?", Toast.LENGTH_SHORT).show();
 95             }
 96             break;
 97         case R.id.re_progress:
 98             // 让服务汇报进度
 99             if(downloadBinder!=null){
100                 downloadBinder.getProgress();
101             }else {
102                 Toast.makeText(this, "ensure binded?", Toast.LENGTH_SHORT).show();
103             }
104             break;
105         case R.id.start_intent_service:
106             // 让intentservice服务工作
107             Log.d("test", "MainActivity Thread name:"+Thread.currentThread().getName());
108             Intent intent2 =new Intent(this, MyIntentService.class);
109             startService(intent2);
110             break;
111 
112         default:
113             break;
114         }
115         
116     }
117 
118 }
MainActivity
技术分享
 1 package com.example.servicetest;
 2 
 3 
 4 import android.app.Notification;
 5 import android.app.PendingIntent;
 6 import android.app.Service;
 7 import android.content.Intent;
 8 import android.os.Binder;
 9 import android.os.IBinder;
10 import android.support.v4.app.NotificationCompat;
11 import android.support.v4.app.NotificationCompat.Builder;
12 import android.util.Log;
13 
14 
15 public class MyService extends Service {
16     private DownloadBinder mBinder = new DownloadBinder();
17     class DownloadBinder extends Binder{
18         public void startDownload(){
19             Log.d("test", "startDownload is work  by DownloadBinder");
20             
21         }
22         public int getProgress(){
23             Log.d("test", "getProgress is work  by DownloadBinder");
24             return 0;
25         }
26     }
27     @Override
28     public IBinder onBind(Intent intent) {
29         // TODO Auto-generated method stub
30         return mBinder;
31     }
32 
33     @Override
34     public void onCreate() {
35         // 主要初始化
36         // 这里创建一个前台服务:后台服务可能会因系统内存不足而回收,如果希望一直运行,可以考虑前台服务,类似通知
37         super.onCreate();
38         NotificationCompat.Builder mbuilder = new NotificationCompat.Builder(this);
39         mbuilder
40         .setTicker("this is ticker")
41         .setWhen(System.currentTimeMillis())
42         .setContentTitle("this is title")
43         .setContentText("this is content")
44         .setSmallIcon(R.drawable.ic_launcher)
45         .setContentIntent(PendingIntent.getActivity(this, 0, new Intent(this, MainActivity.class), 0));
46         
47         Notification notification = mbuilder.build();
48         startForeground(1, notification);// 将MyService变成一个前台服务!!
49         Log.d("test", "service onCreate");
50     }
51 
52     /** 主要的逻辑是在这里完成,但是考虑到:服务默认是在主线程执行的,如果在这里进行比较费时的操作,
53      * 就容易出现ANR(Application Not Responding).<br/>
54      * 所以标准的写法是在这里新建一个子线程执行逻辑处理<br/>
55      * 但是:这样做了之后,必须要使用stopService或stopSelf才能停得下来
56      */
57     @Override
58     public int onStartCommand(Intent intent, int flags, int startId) {
59         Log.d("test", "service onStartCommand");
60         new Thread(new Runnable() {
61             
62             @Override
63             public void run() {
64                 // 逻辑处理
65                 // ...
66                 // 处理完之后调用停止服务
67                 stopSelf();
68                 // 但是如果再这里调用了停止服务的话,新的服务请求将得不到执行,因为服务将会停止
69                 
70             }
71         }).start();
72         return super.onStartCommand(intent, flags, startId);
73     }
74 
75     @Override
76     public void onDestroy() {
77         // 摧毁前调用
78         super.onDestroy();
79         Log.d("test", "service onDestroy");
80         
81     }
82     
83 
84 }
MyService.java
技术分享
 1 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 2     android:layout_width="match_parent"
 3     android:layout_height="match_parent"
 4     android:orientation="vertical" >
 5 
 6     <Button
 7         android:id="@+id/start"
 8         android:layout_width="match_parent"
 9         android:layout_height="wrap_content"
10         android:text="start service" />
11 
12     <Button
13         android:id="@+id/stop"
14         android:layout_width="match_parent"
15         android:layout_height="wrap_content"
16         android:text="stop service" />
17 
18     <Button
19         android:id="@+id/bind"
20         android:layout_width="match_parent"
21         android:layout_height="wrap_content"
22         android:text="Bind service" />
23 
24     <Button
25         android:id="@+id/unbind"
26         android:layout_width="match_parent"
27         android:layout_height="wrap_content"
28         android:text="Unbind service" />
29 
30     <Button
31         android:id="@+id/start_work"
32         android:layout_width="match_parent"
33         android:layout_height="wrap_content"
34         android:text="let service do work!" />
35 
36     <Button
37         android:id="@+id/re_progress"
38         android:layout_width="match_parent"
39         android:layout_height="wrap_content"
40         android:text="See the progress of service" />
41 
42     <Button
43         android:id="@+id/start_intent_service"
44         android:layout_width="match_parent"
45         android:layout_height="wrap_content"
46         android:text="let IntentService go work" />
47 
48 </LinearLayout>
activity_main.xml

 

注意:

MyService可以和应用程序内的任何活动进行绑定

服务的生命周期

当startService(...)时

onCreate()——只会执行一次,服务若已创建,则不再执行

onStartCommand()——startService一次就执行一次

当stopService()或stopSelf()时

onDestroy()会被执行

当binService()时

 

前台服务

IntentService

最佳实例——后台定时执行任务

 

Android——服务

标签:

原文地址:http://www.cnblogs.com/erhai/p/4942229.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!