Android核心基础-11.Android四大组件之Service

11.1.什么是服务

  • Service是一个可以长期在后台运行, 没有界面的组件.
  • 它可以被其他组件绑定, 可以在进程之间通信.

11.2.创建Service

  • 定义类继承Service, 实现回调函数.
  • 在清单文件中声明<service>
public class MyService extends Service {

    @Override
    public void onCreate() {
        System.out.println("onCreate");
        super.onCreate();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        System.out.println("onStartCommand");
        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    public IBinder onBind(Intent intent) {
        System.out.println("onBind");
        return null;
    }

    @Override
    public void onDestroy() {
        System.out.println("onDestroy");
        super.onDestroy();
    }
}

Service生命周期
service_lifecycle

11.3.启动服务,停止服务

  • 在其他组件中可以调用startService()方法启动一个服务, 可以调用stopService()方法停止一个服务
  • 在服务中可以使用stopSelf()方法停止服务
  • 如果不传任何参数, 就是立即停止, 无论是否还有其他未执行结束的, 都会立即停止
  • 传入startId则是等到所有其他的start()执行结束后再停止服务
public class MainActivity extends Activity {

    private Intent intent;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        intent = new Intent(this, MyService.class);
    }

    public void start(View v) {
        startService(intent); // 启动服务, onStartCommand()
    }

    public void stop(View v) {
        stopService(intent); // 停止服务, onDestroy()
    }
}
  • 1.点击“启动服务”按钮,执行生命周期:
    onCreate()->onStartCommand()
  • 2.以后再点击“启动服务”按钮,执行
    onStartCommand()
  • 3.点击“停止服务”按钮,执行生命周期:
    onDestroy()
    示例源码->百度网盘

11.4.耗时操作

  • 如果需要在服务中做耗时的操作, 那么也需要开启新的线程.
  • 如果希望服务长期运行, 即使在内存不足的时候也不要被杀, 那么可以设置为前台服务. startForeground()
    新建一个通知,调用startForeground()将服务设置为前台服务
public class MyService extends Service {

    @Override
    public void onCreate() {
        System.out.println("onCreate");
        super.onCreate();

        Notification n = new Notification(R.drawable.ic_launcher, "MyService", System.currentTimeMillis());
        Intent intent = new Intent();
        intent.setClassName("net.dxs.service", "net.dxs.service.MainActivity");
        PendingIntent pi = PendingIntent.getActivity(this, 0, intent, 0);   
        n.setLatestEventInfo(this, "MyService", "MyService在后台长期运行", pi);                

        startForeground(Process.myPid(), n);
    }

    @Override
    public int onStartCommand(Intent intent, int flags, final int startId) {
        System.out.println("onStartCommand");

        new Thread() {
            public void run() {
                for (int i = 0; i < 10; i++) {
                    System.out.println(i);
                    SystemClock.sleep(1000);
                }
                // stopSelf();      // 无论调用了多少次start(), 都停止服务
                stopSelf(startId);  // 标记当前的这次start()停止, 等到所有start()都停止的时候, 停止服务
            }
        }.start();
        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    public IBinder onBind(Intent intent) {
        System.out.println("onBind");
        return null;
    }

    @Override
    public void onDestroy() {
        System.out.println("onDestroy");
        super.onDestroy();
    }
}

11.5.绑定服务

11.5.1.应用内部绑定

  • i.定义接口, 声明要提供的方法
  • ii.Service中定义一个类继承Binder(IBinder的子类), 实现自定义接口, 实现业务方法, 在onBind()方法中返回该类对象
  • iii.Activity中调用bindService()绑定服务, 传递一个ServiceConnection用来接收onBind()方法返回的IBinder, 强转为接口类型, 即可调用方法

定义一个接口InvokeInterface.java

public interface InvokeInterface {
    /**
     * 服务要提供的方法事先写在接口中
     */
    public void pay();
    public void play();
}

定义服务MyService.java

public class MyService extends Service {

    @Override
    public void onCreate() {
        System.out.println("onCreate");
        super.onCreate();
    }

    @Override
    public IBinder onBind(Intent intent) { // bindService()时会执行
        System.out.println("onBind");
        return new MyBinder();
    }

    @Override
    public boolean onUnbind(Intent intent) {
        System.out.println("onUnbind");
        return super.onUnbind(intent);
    }

    @Override
    public void onDestroy() {
        System.out.println("onDestroy");
        super.onDestroy();
    }

    private class MyBinder extends Binder implements InvokeInterface {
        public void pay() {
            System.out.println("进行网络支付!");
        }

        public void play() {
            System.out.println("进行音乐播放");
        }
    }
}

Activity中调用服务MainActivity.java

public class MainActivity extends Activity {
    private InvokeInterface ii;

    private ServiceConnection conn = new ServiceConnection() {

        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            ii = (InvokeInterface) service; // 绑定成功的时候执行, IBinder就是onBind()方法返回的对象
        }

        @Override
        public void onServiceDisconnected(ComponentName name) { // 在服务被杀的时候执行(解绑时不会执行)
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        bindService(new Intent(this, MyService.class), conn, BIND_AUTO_CREATE); // 绑定服务, bindService(), 得到IBinder
    }

    public void pay(View v) {
        ii.pay(); // 通过IBinder, 调用Service中的支付
        ii.play();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        unbindService(conn); // 解绑服务, unbindService()
    }
}

生命周期:
1,调用服务的MainActivity一启动:
onCreate()->onBind()
2,点击支付按钮:
执行接口中的方法pay()、play()
3,关闭调用服务的MainActivity:
onUnbind()->onDestroy()

示例源码->百度网盘

11.5.2.应用之间绑定

  • i.使用AIDL定义接口, 刷新工程, Eclipse会自动生成一个Java接口
  • ii.Service中定义一个类继承Stub类, 实现抽象方法
  • iii.Activity中收到IBinder之后调用Stub.asInterface()方法把IBinder转为接口类型

定义aidl文件InvokeInterface.aidl

package net.dxs.remoteservice.invokeinterface;

interface InvokeInterface {
    /**
     * 服务要提供的方法事先写在接口中
     */
    void pay();
}

定义服务RemoteService.java

package net.dxs.remoteservice;

import net.dxs.remoteservice.invokeinterface.InvokeInterface.Stub;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;

public class RemoteService extends Service {

    @Override
    public void onCreate() {
        System.out.println("Remote onCreate");
        super.onCreate();
    }

    @Override
    public IBinder onBind(Intent intent) { // bindService()时会执行
        System.out.println("Remote onBind");
        return new MyBinder();
    }

    @Override
    public boolean onUnbind(Intent intent) {
        System.out.println("Remote onUnbind");
        return super.onUnbind(intent);
    }

    @Override
    public void onDestroy() {
        System.out.println("Remote onDestroy");
        super.onDestroy();
    }

    private class MyBinder extends Stub {
        public void pay() throws RemoteException {
            System.out.println("进行网络支付!");
        }
    }
}

远程Activity中调用服务,远程MainActivity.java

package net.dxs.remoteactivity;

import net.dxs.remoteservice.invokeinterface.InvokeInterface;
import net.dxs.remoteservice.invokeinterface.InvokeInterface.Stub;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.view.View;

public class MainActivity extends Activity {
    private InvokeInterface ii;

    private ServiceConnection conn = new ServiceConnection() {

        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            ii = Stub.asInterface(service); // Stub.asInterface() 可以把IBinder转为接口类型
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {// 在服务被杀的时候执行(解绑时不会执行)
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        bindService(new Intent("dxs.service.REMOTE_SERVICE"), conn, BIND_AUTO_CREATE); // 绑定服务, bindService(), 得到IBinder
    }

    public void pay(View v) throws RemoteException {
        ii.pay(); // 通过IBinder, 调用Service中的支付
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        unbindService(conn); // 解绑服务, unbindService()
    }
}

示例源码->百度网盘
示例源码->百度网盘

11.5.3.aidl中使用自定义类型

  • aidl中默认只支持基本数据类型和String以及CharSequences
  • 如果需要使用自定义类型, 那么该类需要实现Parcelable, 需要实现writeToParcel()方法, 需要定义CREATOR对象
  • 再根据这个类定义一个同名的aidl
  • 在aidl接口中使用自定义类型作为参数的时候需要加上in

定义aidl文件InvokeInterface.aidl

package net.dxs.remoteservice.invokeinterface;

import net.dxs.remoteservice.bean.Person;

interface InvokeInterface {

    /**
     * 服务要提供的方法事先写在接口中
     */
    boolean pay(in Person p, int amount);
}

定义服务RemoteService.java

package net.dxs.remoteservice;

import net.dxs.remoteservice.bean.Person;
import net.dxs.remoteservice.invokeinterface.InvokeInterface.Stub;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;

public class RemoteService extends Service {

    @Override
    public void onCreate() {
        System.out.println("Remote onCreate");
        super.onCreate();
    }

    @Override
    public IBinder onBind(Intent intent) { // bindService()时会执行
        System.out.println("Remote onBind");
        return new MyBinder();
    }

    @Override
    public boolean onUnbind(Intent intent) {
        System.out.println("Remote onUnbind");
        return super.onUnbind(intent);
    }

    @Override
    public void onDestroy() {
        System.out.println("Remote onDestroy");
        super.onDestroy();
    }

    private class MyBinder extends Stub {

        @Override
        public boolean pay(Person p, int amount) throws RemoteException {
            System.out.println("向" + p.getName() + "支付" + amount);
            return amount < 100;
        }
    }
}

远程Activity中调用服务,远程MainActivity.java

package net.dxs.remoteactivity;

import net.dxs.remoteservice.bean.Person;
import net.dxs.remoteservice.invokeinterface.InvokeInterface;
import net.dxs.remoteservice.invokeinterface.InvokeInterface.Stub;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.view.View;

public class MainActivity extends Activity {
    private InvokeInterface ii;

    private ServiceConnection conn = new ServiceConnection() {

        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            ii = Stub.asInterface(service); // Stub.asInterface() 可以把IBinder转为接口类型
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {// 在服务被杀的时候执行(解绑时不会执行)
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        bindService(new Intent("dxs.service.REMOTE_SERVICE"), conn, BIND_AUTO_CREATE); // 绑定服务, bindService(), 得到IBinder
    }

    public void pay(View v) throws RemoteException {
        System.out.println(ii.pay(new Person(101, "深情小建", 29), 150));   // 通过IBinder, 调用Service中的支付
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        unbindService(conn); // 解绑服务, unbindService()
    }
}

我们的Person类接口Person.aidl

package net.dxs.remoteservice.bean;
parcelable Person;

我们的Person类Person.java

package net.dxs.remoteservice.bean;

import android.os.Parcel;
import android.os.Parcelable;

public class Person implements Parcelable {
    private Integer id;
    private String name;
    private Integer age;

    public Person() {
        super();
    }

    public Person(Integer id, String name, Integer age) {
        super();
        this.id = id;
        this.name = name;
        this.age = age;
    }

    @Override
    public String toString() {
        return "Person [id=" + id + ", name=" + name + ", age=" + age + "]";
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel parcel, int flags) {
        parcel.writeInt(id);
        parcel.writeString(name);
        parcel.writeInt(age);
    }

    public static final Parcelable.Creator<Person> CREATOR = new Parcelable.Creator<Person>() {
        public Person createFromParcel(Parcel parcel) {
            return new Person(parcel.readInt(), parcel.readString(), parcel.readInt());
        }

        public Person[] newArray(int size) {
            return new Person[size];
        }
    };
}

附:提供给第三方调用的服务,要把aidl接口文件及javabean文件一块提供,且文件的包名要一致。

实例源码->百度网盘
实例源码->百度网盘

  • 1
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值