Skip to content

Latest commit

 

History

History
207 lines (168 loc) · 7.84 KB

3.6.md

File metadata and controls

207 lines (168 loc) · 7.84 KB

Service学习

Service介绍

Service是安卓非常重要的一个部分,Activity主要是用来显示界面,但是它并不能长期运行,而且,当系统的内存比较少的时候,系统很可能就会把Activity给杀死。而Service主要用来解决这个问题,它可以长期在后台运行,比如说:后台下载、音乐播放、推送服务等,都是用Service在后台默默进行的。

而Service有两种方式,一种是启动Service,一种是绑定Service。对于启动Service这种方式,Activity和Service无法实现交互,也就是说Service只是启动起来,但是无法给Activity返回信息。而绑定方式的则可以正常和Activity交互。我们这里只介绍绑定Service。

绑定一个服务

首先,我们先创建一个工程叫做:BindService,并创建一个类TestService,让它继承自Service,此时,我们发现需要重写一个onBind的方法,返回一个IBinder的对象,这个I就是Interface的缩写,也就是IBinder是一个接口,它有很多方法,如果直接写的话需要把这些方法都补充全,不过它有一个叫Binder的实现类,我们创建一个类直接继承自Binder就好了。

package com.example.kalen.bindservice;

import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.support.annotation.Nullable;

public class TestService extends Service{
    MyBinder binder = new MyBinder();

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return binder;
    }

    public class MyBinder extends Binder {

    }
}

Service也是安卓的基本组件,我们需要在manifest文件里对它进行注册,在AndroidManifest.xml中添加service标签。

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

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
    <service android:name=".TestService"/>
</application>

写到这块之后我们再回到Activity那块来尝试绑定这个服务。绑定服务需要使用bindService这个方法。先看看bindService需要的参数。
bindService(Intent service, ServiceConnection conn, int flags)

这里第一个参数是一个Intent类型,和startActivity需要的Intent类似,我们需要设置绑定哪一个Service,需不需要传些参数(通过putExtra)。

第二个参数中,ServiceConnection是一个接口类型,它有两个方法,一个是onServiceConnected,onServiceDisconnected。其中onServiceConnected可以拿到我们在Service中写的onBind方法返回过来的对象。拿到这个对象,我们就可以对Service进行一些操作了。

第三个参数其实就是个flag,一般用BIND_AUTO_CREATE,也就是绑定并创建这个Service。

先完成一下MainActivity,如下:

package com.example.kalen.bindservice;

import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.IBinder;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;

public class MainActivity extends AppCompatActivity {

    TestService.MyBinder myBinder;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Intent intent = new Intent();
        intent.setClass(MainActivity.this, TestService.class);
        bindService(intent, new ServiceConnection() {
            @Override
            public void onServiceConnected(ComponentName name, IBinder service) {
                System.out.println("绑定TestService成功");
                myBinder = (TestService.MyBinder) service;
            }

            @Override
            public void onServiceDisconnected(ComponentName name) {

            }
        }, BIND_AUTO_CREATE);
    }

}

现在,相当于绑定了一个空的服务,它什么都不做。我们现在给它加点功能,让Service记录一下绑定成功到现在的一共过去了多少秒。

这里首先在MyBinder中创建一个整型变量,然后创建一个线程,让这个整形变量每秒钟+1。(其实可以直接获取创建的时间戳,然后和当前时刻的时间戳相减,这里主要以模拟为目的)

package com.example.kalen.bindservice;

import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.support.annotation.Nullable;


public class TestService extends Service{
    MyBinder binder = new MyBinder();

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        new Thread(new Runnable() {

            @Override
            public void run() {
                while (true) {
                    binder.setSecond(binder.getSecond() + 1);
                    try {//睡眠1秒
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }).start();
        return binder;
    }

    public class MyBinder extends Binder {
        private int second = 0;

        public int getSecond() {
            return second;
        }

        public void setSecond(int second) {
            this.second = second;
        }
    }
}

最后,我们在MainActivity中添加一个Button,点击之后获取秒数。

package com.example.kalen.bindservice;

import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.IBinder;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity {

    TestService.MyBinder myBinder;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Intent intent = new Intent();
        intent.setClass(MainActivity.this, TestService.class);
        bindService(intent, new ServiceConnection() {
            @Override
            public void onServiceConnected(ComponentName name, IBinder service) {
                System.out.println("绑定TestService成功");
                myBinder = (TestService.MyBinder) service;
            }

            @Override
            public void onServiceDisconnected(ComponentName name) {

            }
        }, BIND_AUTO_CREATE);

        findViewById(R.id.button).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (myBinder != null) {
                    Toast.makeText(MainActivity.this,
                            myBinder.getSecond() + "秒",
                            Toast.LENGTH_SHORT).show();
                }
            }
        });
    }

}

运行后,我们可以看到成功显示了秒数:


当我们回到主页,打开其他应用时,TestService仍然会继续在后台运行,读者可以试试直接在Activity里创建一个线程获取秒数,看看当我们打开其他应用后再打开BindService会怎么样?

补充

除了绑定同一个程序的Service之外,还可以绑定其他程序的Service,如果读者感兴趣可以看看AIDL。

链接