本地service【Android】

本地service是一个应用组件,它用来在后台完成一个时间跨度较大的工作且没有关联任何界面

一 服务的特点:

  • Service在后台运行,不用与用户进行交互
  • 即使用户退出,服务也不会停止
  • 在默认情况下,Service运行在应用程序进程的主线程中,如果需要在Service中处理一些网络连接等耗时的操作,那么应该将这些任务放在分线程中处理,避免阻塞用户界面

二 Service和Activity的区别:

Activity:

  • Activity对应一个界面
  • 应用退出时,Activity对象就会死亡
  • 应用再次进入,启动的Activity对象是重新创建的

Service

  • 不用任何界面关联
  • 应用退出,Service仍在运行
  • 应用再次进入,启动的Service还是前面运行的Service对象

三 Service和Thread的区别

Service

  • 用来在后台完成一个时间跨度比较大的工作的应用组件
  • Service的生命周期方法运行在主线程,如果Service想做持续时间比较长的工作,需要启动一个分线程(Thread)
  • 应用退出:Service不会停止
  • 应用再次进入:可以与正在运行的Service进行通信

Thread

  • 用来开启一个分线程的类,做一个长时间的工作
  • Thread对象的run()在分线程执行
  • 应用退出:Thread不会停止
  • 应用再次进入:不能再控制前面启动的Thread对象

四 Service的分类

Local Service(本地服务)

Service对象与Service的启动者在同个进程中运行,两者的通信时进程内的通信

Remote Service(远程服务)

Service对象与Service的启动者不在同一个进程中进行,这时存在一个进程间通信的问题,Android专门为此设计了AIDL来实现进程间通信

五 Service的使用

1.需要定义一个类继承于Service类

2.在AndroidMainfest.xml中配置Service

<span style="font-size:14px;"><Service android:name=".test.MyService">
	<intent-filter>
		<action android:name="随便一个字符串"/>
	</intent-filter>
</service></span>

六 启动与停止Service

1.方式一:  一般启动与停止

context.startService(Intentintent)

context.stopService(Intentintent)

2.方式二 : 绑定启动与解绑

context.bindService(Intentintent, ServiceConnectionconnection)

context.unbindService(ServiceConnectionconnection)

七  Service的生命周期:

 注意:每次startService都会调用Service的onStartCommand()

八  什么时候会用到反射?

     1). 功能清单清单文件: 配置应用组件的全类名
     2). 布局文件 : 视图标签
     3). 显式意图: 指定类的Class对象
     4). 调用系统隐藏的API : 使用Class.forName("全类名")调用
     哪些情况使用了反射?
          1. 指定类名/全类名字符串
          2. 使用反射相关API:  Class | Method | Field

九  AIDL理解

每个应用程序都运行在自己的独立进程中,并且可以启动另一个应用进程的服务,而且经常需要在不同的进程间传递数据对象

在Android平台,一个进程不能直接访问另一个进程的内存空间,所以要想对话,需要将对象分解成操作系统可以理解的基本单元,并且有序的通过进程边界。

AIDL(Android Interface Definition Language)

用于生成可以在Android设备上两个进程之间进行进程间通信(interprocess communication, IPC)的代码。

如果在一个进程中(例如Activity)要调用另一个进程中(例如Service)对象的操作,就可以使用AIDL生成可序列化的参数。

八 定义一个AIDL接口,如果需要使用自定义类型的数据对象比如(student)把student进行封装时需要实现Parelable接口,并且需要创建一个跟此对象一样名字的AIDL文件student.aidl

package com.atguigu.service.test.remote;
parcelable Student;	
十  案列-----开启两个进程,一个进程和另一个建立连接后,这个进程在输入框中输入id后,会显示出该学生的相关信息

主要通过service和activity通信

第一步:需要在被连接的进程(新建的项目Remote)中封装一个类student需要实现Parelable接口

package shangguigu.java.remote;

import android.os.Parcel;
import android.os.Parcelable;
import android.util.Log;

/**
 * Created by Dell on 2016/8/6.
 */
public class Student implements Parcelable{
    int id;
    String name;
    int age;

    public Student(int id, String name, int age) {
        this.id = id;
        this.name = name;
        this.age = age;
    }

    @Override
    public String toString() {
        return "Student{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", age=" + age +
                '}';
    }

    public int getId() {
        return id;
    }

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

    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

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

    public Student() {

    }

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

    //打包
    @Override
    public void writeToParcel(Parcel dest, int flags) {
        Log.i("tag","打包");
        dest.writeInt(id);
        dest.writeString(name);
        dest.writeInt(age);
    }

    public static final Parcelable.Creator<Student> CREATOR = new Creator<Student>() {
        @Override
        public Student createFromParcel(Parcel source) {
            Log.i("tag","解包");
            //解包
            int id = source.readInt();
            String name = source.readString();
            int age = source.readInt();
            return new Student(id,name,age);
        }

        //返回指定大小的容器
        @Override
        public Student[] newArray(int size) {
            return new Student[size];
        }
    };
}
第二步需要创建一个student.adil,然后运行一下点击这个键

package shangguigu.java.remote;
parcelable Student;

第三步  需要创建一个aidl如MyService.aidl里面需要使用Student虽然两个在一个包下,但是还得继续导入包删去没用的代码

// MyService.aidl
package shangguigu.java.remote;
import shangguigu.java.remote.Student;
// Declare any non-default types here with import statements

interface MyService {
    Student getStudentById(int id);
}

第四步:需要创建一个Service

package shangguigu.java.remote;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;

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

    @Override
    public IBinder onBind(Intent intent) {
        Log.i("tag","onBind()");
        return new StudentService();
    }

    @Override
    public boolean onUnbind(Intent intent) {
        Log.i("tag","onUnbind()");
        return super.onUnbind(intent);
    }

    class StudentService extends MyService.Stub {

        @Override
        public Student getStudentById(int id) throws RemoteException {
            Log.i("tag","service getStudentById()");
            return new Student(1,"hahah",10);
        }
    }
}

以及需要在mainfest中进行注册

<service android:name=".RemoteService">
            <intent-filter>
                <action android:name="fanny"/>//这里的name可以随意写,但是需要记住,以后会需要
            </intent-filter>
        </service>
第五步:新建一个新的项目,ServiceClient

需要将第一个项目里的aidl相关的文件复制到这个项目里,注意:包名也必须一样有student    student.aidl   MyService.aidl

需要在布局文件中写布局文件,主要有一个文本编辑框TextView   3个Button一个用于连接Service一个用于断开连接,最后一个用于显示

在mainActivity的主文件中编写代码

package shangguigu.java.serviceclient;

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

import shangguigu.java.remote.MyService;
import shangguigu.java.remote.Student;


public class MainActivity extends AppCompatActivity {

    private EditText et_main;
    private  MyService myService;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        et_main = (EditText) findViewById(R.id.et_main);
    }

    public void ConnectService (View v) {
        Intent intent = new Intent("fanny");//需要连接的Service再mainfest注册时填写的的

        if (conn == null) {
            conn = new ServiceConnection() {
                @Override
                public void onServiceConnected(ComponentName name, IBinder service) {
                    Log.i("tag","onServiceConnected");
                    myService = MyService.Stub.asInterface(service);

                }
                @Override
                public void onServiceDisconnected(ComponentName name) {

                }
            };
            bindService(intent,conn,BIND_AUTO_CREATE);
            Toast.makeText(this,"绑定service",Toast.LENGTH_SHORT).show();
        } else {
            Toast.makeText(this,"已经绑定service",Toast.LENGTH_SHORT).show();
        }
    }
    private ServiceConnection conn;
    public void SelectStudent (View v) throws RemoteException {
        if (conn !=null) {
            if (myService!=null) {
                int id = Integer.parseInt(et_main.getText().toString());
                Log.i("tag",id+"");
                Student student = myService.getStudentById(id);
                int _id = student.getId();
                if ((id+"").equals(_id+"")) {
                    Toast.makeText(this,student.toString(),Toast.LENGTH_SHORT).show();
                }else {
                    Toast.makeText(this,"没有这条信息",Toast.LENGTH_SHORT).show();
                }
            } else {
                Toast.makeText(this,"没有这条信息",Toast.LENGTH_SHORT).show();
            }
        } else {
            Toast.makeText(this,"没有绑定service",Toast.LENGTH_SHORT).show();
        }

    }
    public void disConnectService (View v) {
        if (conn != null) {
            unbindService(conn);
            conn = null;
            Toast.makeText(this,"解除绑定",Toast.LENGTH_SHORT).show();
        } else {
            Toast.makeText(this,"没有绑定",Toast.LENGTH_SHORT).show();
        }
    }
}













  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值