Android的服务——Service和IntentService

  Service,服务,Android的四大组件之一。服务一般用于去执行需要长期运行,很少于用户交互的任务。服务一般都是后台运行的。下面我们就来学习一下Service服务。

创建一个服务

  创建一个服务很简单。看步骤:
1. 创建一个类MyService,然后继承Service。
  我们可以看到,当我们创建一个服务之后,需要重写onBind()方法,这是Service中唯一个抽象的方法。

public class MyService extends Service {

    @Override
    public IBinder onBind(Intent intent) {
        throw new UnsupportedOperationException("Not yet implemented");
    }
}

  
2. 在AndroidManifext.xml注册。
  创建服务之后,要想使用它,必须在AndroidManifext.xml文件中注册。

 <service android:name=".MyService"></service>

  这样一个服务就是创建完成了,我们就可以开启服务并使用了,在使用之前我们首先要了解一下Service的生命周期。

服务的生命周期

  服务的生命周期我们要分两种介绍:启动类型服务周期和绑定类型服务周期。我们可以先看下图:
  
这里写图片描述

启动类型服务的周期 

  一个组件调用startService()方法创建服务,然后服务无限期的运行,并且必须通过调用stopSelf()方法来终止自己。其他组件也能够通过调用stopService()方法来终止这个服务。当服务被终止,系统就会把它销毁。如上图左边周期。
  这种方式我们通过Activity启动服务,服务在启动后与活动就没有了关系。Activity无法在控制服务中运行的是什么。

绑定类型服务的周期 

  一个组件(客户端)调用bindService()方法创建服务,客户端通过IBinder接口与服务通信。客户端能够调用unbindService()方法来关闭与服务连接。多个客户端能够绑定到同一个服务,并且当所有的都解绑以后,系统就会销毁这个服务(服务不需要终止自己)。这一块知识点老师没有给我们提及,我记得我当时问老师问什么不讲,老师说现在很少有用绑定服务的,一般都是通过发送广播来实现服务与活动的联系。所以在这里我也就不再讲绑定服务了,因为我也不会……
  
  我们通过例子来学习一下服务的简单使用……

开启和关闭服务

1. 创建一个服务并注册。
MyService类:

public class MyService extends Service {
    public MyService() {
    }

    @Override
    public void onCreate() {
        super.onCreate();
        Log.d("data", "onCreate ");
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.d("data", "onStartCommand ");
        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        Log.d("data", "onDestroy ");       
    }

    @Override
    public IBinder onBind(Intent intent) {
        throw new UnsupportedOperationException("Not yet implemented");
    }
}

在AndroidMainfest.xml中注册:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.lishuang.administrator.servicedemo">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme">
        <activity
            android:name=".MainActivity"
            android:label="@string/app_name">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

        <service android:name=".MyService"></service>

    </application>
</manifest>     

2. 在Activity的布局文件,定义两个按钮,启动和关闭服务。

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity">


    <Button
        android:id="@+id/button_start_service"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="启动服务" />

    <Button
        android:id="@+id/button_stop_service"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="关闭服务" />
</LinearLayout>       

3. 在Activity中通过使用Intent启动和关闭服务。

public class MainActivity extends Activity implements View.OnClickListener {
    private Button mButtonStartService;
    private Button mButtonStopService;

    private MyDownLoadReceiver myDownLoadReceiver;
    public  static final String DOWNLOAD_RECEIVER="com.example.receiver";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mButtonStartService = (Button) findViewById(R.id.button_start_service);
        mButtonStopService = (Button) findViewById(R.id.button_stop_service);

        mButtonStartService.setOnClickListener(this);
        mButtonStopService.setOnClickListener(this);
    }

    @Override
    public void onClick(View view) {
        switch (view.getId()) {
            case R.id.button_start_service:
                Intent intent = new Intent(getApplicationContext(), MyService.class);
                startService(intent);//启动服务
                break;
            case R.id.button_stop_service:
                Intent intent1 = new Intent(getApplicationContext(), MyService.class);
                stopService(intent1);//关闭服务
                break;       
            default:
                break;
        }
    }

Service应用——下载

功能需求:

  定义一个下载任务,通过进度条显示其下载进度。

功能分析:

  通常我们的下载是在程序退出之后也可以进行的,所以下载不能定义在活动中,我们可以将其定义在服务中。

实现思路:

1. 在Activity中开启一个Service
2. 在Service中发送一个广播,将下载的进度发送给Activity。但是我们需要知道Service中不能进行耗时操作,所以我们在一个线程中完成。
3. 在Activity中接收广播,并设置进度条。

这里写图片描述

代码实现:

  1. 定义布局。
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity">

    <Button
        android:id="@+id/button_stop_service"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="关闭下载" />

    <Button
        android:id="@+id/button_start_download"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="开始下载" />

    <ProgressBar
        android:id="@+id/progressBar"
        style="?android:attr/progressBarStyleHorizontal"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:max="100"
        />
</LinearLayout>

2. 在Activity中启动下载服务。

public class MainActivity extends Activity implements View.OnClickListener {
    public  static final String DOWNLOAD_RECEIVER="com.example.receiver";

    private Button mButtonStopService;
    private Button mButtonStartDownload;
    private ProgressBar mProgressBar;

    private MyDownLoadReceiver myDownLoadReceiver;//定义服务

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mButtonStopService = (Button) findViewById(R.id.button_stop_service);
        mButtonStartDownload = (Button) findViewById(R.id.button_start_download);
        mProgressBar = (ProgressBar) findViewById(R.id.progressBar);

        mButtonStopService.setOnClickListener(this);
        mButtonStartDownload.setOnClickListener(this);

        //注册一个广播
        myDownLoadReceiver = new MyDownLoadReceiver();
        IntentFilter filter = new IntentFilter();
        filter.addAction(DOWNLOAD_RECEIVER);
        registerReceiver(myDownLoadReceiver, filter);
    }

    //取消注册
    @Override
    protected void onDestroy() {
        super.onDestroy();
        unregisterReceiver(myDownLoadReceiver);
    }

    @Override
    public void onClick(View view) {
        switch (view.getId()) {
            case R.id.button_stop_service:
                Intent intent1 = new Intent(getApplicationContext(), MyIntentService.class);
                stopService(intent1);
                break;
            case R.id.button_start_download:
                Intent intent2 = new Intent(getApplicationContext(), MyIntentService.class);
                startService(intent2);
                break;
            default:
                break;
        }
    }
    class MyDownLoadReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            int count = intent.getIntExtra("count",0);
            mProgressBar.setProgress(count);
        }
    }
}

3. 定义一个服务,在服务中发送广播,将下载的进度发送给Activity。

public class MyService extends Service {

    private int count = 0;

    public MyService() {
    }

    @Override
    public void onCreate() {
        super.onCreate();
        Log.d("data", "onCreate ");
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.d("data", "onStartCommand ");
        //发送一个广播
        new Thread(new Runnable() {

            @Override
            public void run() {
                while (true) {
                    if (count > 100) {
                        count = 0;
                    }
                    count++;
                    Intent intent = new Intent();
                    intent.setAction(MainActivity.DOWNLOAD_RECEIVER);
                    intent.putExtra("count", count);
                    sendBroadcast(intent);
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }).start();
        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    public void onDestroy() {
        Log.d("data", "onDestroy ");
        super.onDestroy();
    }

    @Override
    public IBinder onBind(Intent intent) {
        throw new UnsupportedOperationException("Not yet implemented");
    }
}

4. 在AndroidManifest.xml中注册。

IntentService应用——下载优化 ## 

  在之前我们就说过,主线程中是不允许有耗时操作的,Service服务中的内容是默认运行在主线程中的。因此,在服务中定义下载我们必须开启一个子线程来完成这项工作。
  我们通过比较Service和IntentService来学习一下IntentService:Service中使用子线程必须自己重新定义,而IntentService服务中自己包含一个子线程,不需要我们在去重新定义;Service服务开启后必须调用stopService()方法或者stopSelf()方法才可以将服务停止,而IntentService服务只要服务内容运行结束就会自己停止。
  IntentService中包含一个任务的堆栈,每次我们在开启服务时, 如果当前服务没有运行结束,就会就会将启动的服务添加到任务堆栈中,直到当前服务运行结束,才会将后启动的服务从堆栈中取出来,然后运行。

  了解完了IntentService,我们可以使用IntentService来优化一下刚才讲的Service的下载应用。
1. 定义布局文件。跟刚才的是相同的,我们这里不在贴出。
2. 在Activity中启动下载服务。

public class MainActivity extends Activity implements View.OnClickListener {
    private Button mButtonStopService;
    private Button mButtonStartDownload;
    private ProgressBar mProgressBar;

    private MyDownLoadReceiver myDownLoadReceiver;//定义一个广播
    public  static final String DOWNLOAD_RECEIVER="com.example.receiver";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mButtonStopService = (Button) findViewById(R.id.button_stop_service);
        mButtonStartDownload = (Button) findViewById(R.id.button_start_download);
        mProgressBar = (ProgressBar) findViewById(R.id.progressBar);

        mButtonStartService.setOnClickListener(this);
        mButtonStopService.setOnClickListener(this);
        mButtonStartDownload.setOnClickListener(this);

        //注册一个广播
        myDownLoadReceiver = new MyDownLoadReceiver();
        IntentFilter filter = new IntentFilter();
        filter.addAction(DOWNLOAD_RECEIVER);
        registerReceiver(myDownLoadReceiver, filter);
    }

    //取消注册
    @Override
    protected void onDestroy() {
        super.onDestroy();
        unregisterReceiver(myDownLoadReceiver);
    }

    @Override
    public void onClick(View view) {
        switch (view.getId()) {
            case R.id.button_stop_service:
                Intent intent1 = new Intent(getApplicationContext(), MyIntentService.class);
                stopService(intent1);//关闭服务
                break;
            case R.id.button_start_download:
                Intent intent2 = new Intent(getApplicationContext(), MyIntentService.class);
                startService(intent2);//开启定义的IntentService服务
                break;
            default:
                break;
        }
    }
    class MyDownLoadReceiver extends BroadcastReceiver {

        @Override
        public void onReceive(Context context, Intent intent) {
            int count = intent.getIntExtra("count",0);
            mProgressBar.setProgress(count);
        }
    }
}

  这里将启动的服务修改为自定义的IntentService服务。
3. 定义一个IntentService服务,在服务中发送广播,将下载的进度发送给Activity。

public class MyIntentService extends IntentService {
    private static final String TAG = "data";
    private int count = 0;
    private boolean running = true;

    /*
    必须定义一个无参的构造器,调用父类的有参构造器
     */
    public MyIntentService() {
        super("MyIntentService");
    }

    @Override
    public void onCreate() {
        Log.d(TAG, "运行了……onCreate ");
        super.onCreate();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.d(TAG, "运行了……onStartCommand ");
        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    public void onDestroy() {
        Log.d(TAG, "运行了……onDestroy ");
        running = false;
        super.onDestroy();
    }

    //将服务执行的内容写在该方法中。
    @Override
    protected void onHandleIntent(Intent intent) {
        Log.d(TAG, "运行了……onHandleIntent ");
        while (running) {
            if (count > 100) {
                count = 0;
                Toast.makeText(getApplicationContext(), "开始下载", Toast.LENGTH_SHORT).show();
            }
            Toast.makeText(getApplicationContext(), "开始下载", Toast.LENGTH_SHORT).show();
            count++;
            Intent intent1 = new Intent();
            intent1.setAction(MainActivity.DOWNLOAD_RECEIVER);
            intent1.putExtra("count", count);
            sendBroadcast(intent1);
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

这里写图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小_爽

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值