Android Activity与远程Service的通信学习总结

本文详细介绍了Android中Activity与远程Service的跨进程通信,通过AIDL实现 Binder 机制。首先讲解了如何定义远程服务端,包括创建aidl文件、实现Service,并在AndroidManifest中声明。接着阐述了本地Activity如何绑定远程Service,强调了IPC调用的同步性质和避免阻塞UI线程的重要性。最后,以挂断电话为例展示了AIDL的实际应用,涉及反射调用和权限申请。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

当一个Service在androidManifest中被声明为 process=":remote", 或者是另一个应用程序中的Service时,即为远程Service, 远程的意思是和当前程序不在同一个进程中运行。Activity和远程Service的跨进程通信(IPC)通过Binder机制,使用AIDL服务实现。


一.  定义远程服务端


1.新建一个工程,工程目录如下



2. 文件内容

aidl传递复杂对象时,需要该对象实现Parcelable或Serializable接口,并在aidl文件中声明


Student.java

package com.example.aidl;

import java.util.Locale;

import android.R.integer;
import android.os.Parcel;
import android.os.Parcelable;

public class Student implements Parcelable {

	public static final int SEX_MALE = 1;  
    public static final int SEX_FEMALE = 2; 

	public int sno;
	public String name;
	public int sex;
	public int age;

	public Student() {
	}

	private Student(Parcel in) {
		readFromParcel(in);
	}

	public void readFromParcel(Parcel in) {
		sno = in.readInt();
		name = in.readString();
		sex = in.readInt();
		age = in.readInt();
	}

	@Override
	public void writeToParcel(Parcel dest, int flags) {
       dest.writeInt(sno);
       dest.writeString(name);
       dest.writeInt(sex);
       dest.writeInt(age);
	}

	public static final Parcelable.Creator<Student> CREATOR = new Parcelable.Creator<Student>() {

		@Override
		public Student createFromParcel(Parcel in) {
			return new Student(in);
		}

		@Override
		public Student[] newArray(int size) {
			return new Student[size];
		}
	};

	@Override
	public int describeContents() {
		return 0;
	}
	
	@Override  
    public String toString() {  
        return String.format(Locale.ENGLISH, "Student[ %d, %s, %d, %d ]", sno, name, sex, age);  
    } 

}


Student.aidl

package com.example.aidl;

parcelable Student;


 

IService.aidl

package com.example.aidl;

import com.example.aidl.Student;

 interface IMyService{
 
    List<Student> getStudent();
    void addStudent(in Student student); //in标记为输入类型
  }


然后再写远程服务类StudentService.java

package com.example.remote_service;

import java.util.LinkedList;
import java.util.List;

import com.example.aidl.IMyService;
import com.example.aidl.Student;

import android.R.integer;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.Parcel;
import android.os.RemoteException;
import android.util.Log;

public class StudentService extends Service {

	private static final String TAG = "StudentService";
	
	private static final String PACKAGE_PEMISSION = "com.yjq.service";  
	
	private LinkedList<Student> studentList = new LinkedList<Student>();
		
	@Override
	public IBinder onBind(Intent intent) {
		Log.d(TAG, String.format("on bind,intent = %s", intent.toString()));  
		return mBinder;
	}

	   //继承由AIDL生成的抽象类 
//	实现aidl里的接口的方法 ,以供调用
	//这里实现了aidl中的抽象函数  
    private final IMyService.Stub mBinder = new IMyService.Stub() { 

		@Override
		public List<Student> getStudent() throws RemoteException {
			return studentList;
		}

		@Override
		public void addStudent(Student student) throws RemoteException {
			if (student != null) {
				synchronized (studentList) {
					studentList.add(student);
				}
			}
		}		
		
		//在这里可以做权限认证,return false意味着客户端的调用就会失败,比如下面,只允许包名为 PACKAGE_PEMISSION 的客户端通过,  
        //其他apk将无法完成调用过程  
		@Override
        public boolean onTransact(int code, Parcel data, Parcel reply, int flags)  
                throws RemoteException {  
            String packageName = null;  
            String[] packages = StudentService.this.getPackageManager().  
                    getPackagesForUid(getCallingUid());  
            if (packages != null && packages.length > 0) {  
                packageName = packages[0];  
            }  
            Log.d(TAG, "onTransact: " + packageName);  
            if (!PACKAGE_PEMISSION.equals(packageName)) {  
                return false;  
            }  
            return super.onTransact(code, data, reply, flags);  
        }  
		
	};

	@Override
	public void onCreate() {
		super.onCreate();
	    Log.d(TAG, "student服务创建");
	    
	    synchronized (studentList) {  
            for (int i = 1; i < 6; i++) {  
                Student student = new Student();  
                student.name = "student#" + i;  
                student.age = i * 5;  
                studentList.add(student);  
            }  
        }  
	    
	}

	
	@Override
	public int onStartCommand(Intent intent, int flags, int startId) {
                Log.d(TAG, "student服务启动");
		return super.onStartCommand(intent, flags, startId);
	}

	@Override
	public void onDestroy() {
		Log.d(TAG, "student服务结束");
		super.onDestroy();
	}

	
}



Stub这个内部类是一个实现了IMyService接口的Binder抽象类

onTransact()是通过应用程序的包名来限制权限的,通过验证的程序才能绑定。 允许绑定的客户端程序 的包名,可在客户端的androidManifist中查看。


并注意在androidManifest中声明

<service    
    android:name="com.example.remote_service.StudentService"  
    android:process=":remote"  
    >  
    <intent-filter >  
        <!-- 这里的action是隐式bindService时用到的  -->  
        <action  android:name="com.example.remoteservice" />  
        <category android:name="android.intent.category.DEFAULT" />   
    </intent-filter>  
      
</service> 

要声明action以供隐式bindService


二. 本地Activity如何绑定远程Service

新建一个项目作为绑定远程Service的客户端,将上面的aidl所在包复制到src中,注意整个包名和文件名都要完全一样,否则无法远程绑定

再写MainActivity.java来进行绑定操作

package com.yjq.local_service;

import java.util.List;

import com.example.aidl.IMyService;
import com.example.aidl.Student;
import com.yjq.local_service.MyService.MyBinder;
import com.yjq.service.R;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;

public class MainActivity extends Activity {

	private static final String TAG = "MainActivity_local";

//绑定远程Service的action
	public static final String BIND_REMOTE_SERVICE_ACTION = "com.example.remoteservice";

	// 远程服务 , 服务的类是在aidl中定义的
	private IMyService mRemoteService;

	private Button bindRemoteServiceButton;

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

		bindRemoteServiceButton =(Button)findViewById(R.id.bind_remote_service);

                              bindRemoteServiceButton.setOnClickListener( new OnClickListener() {
			@Override
			public void onClick(View v) {
				bindRemoteService();
			}
		});
	}


	/**
	 * 创建并绑定远程Service
	 * */
	private void bindRemoteService() {
		Intent intentService = new Intent(BIND_REMOTE_SERVICE_ACTION);
		intentService.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
		bindService(intentService, remoteServiceConnection, BIND_AUTO_CREATE);
	}

	
	

	/**
	 * 绑定远程服务的ServiceConnection类
	 */
	ServiceConnection remoteServiceConnection = new ServiceConnection() {

		@Override
		public void onServiceDisconnected(ComponentName name) {
			mRemoteService = null;
		}

		@Override
		public void onServiceConnected(ComponentName name, IBinder serv
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值