概述
1.前面讲了跨进程调用service,传递基础数据类型,今天来说说传递自定义类型,顺便把楼主遇到的错误说下。
2. 第一步:自定义一个类名称叫person。实现parcelable接口。其中特意要注意的是:实现parcelable接口,必须要在这个类中声明一个Creator 静态变量的,然后实现它的一些方法。person类中的属性的get/set方法在这里我就不介绍了。具体看如下代码:
package com.example.lenovo.aidltest3;
import android.os.Parcel;
import android.os.Parcelable;
/**
* Created by lenovo on 12/6/2016.
*/
public class Person implements Parcelable{
private int id;
private String name;
private String password;
public Person(int id, String name, String password)
{
this.id=id;
this.name=name;
this.password=password;
}
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 String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
//创建CREATOR对象,该对象是静态final类型的
public static final Creator<Person>CREATOR=new Creator<Person>()
{
@Override
public Person createFromParcel(Parcel source) {
return new Person(source.readInt(), source.readString(),source.readString());
}
@Override
public Person[] newArray(int size) {
return new Person[size];
}
};
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(id);
dest.writeString(name);
dest.writeString(password);
}
}
我需要着重说下:writeToParcel方法和createFromParcel方法,这俩个最开始我没有重写,
结果最后在运行的的时候报空指针错误,对这俩个方法,我其实用的也不多,只知道writeToParcel(),方法是把值写入Parcel的dest对象中,然后在createFormParcel中根据这个Parcel 对象source回去传入的值,具体的请看这个博客
http://blog.csdn.net/u010142437/article/details/24112457。
Person类写好了之后,我们就开始建立IMyAidlInterface aidl文件接口,不知道请看博主上一篇关于跨进程调用service的文章。然后再接口中定义方法,这里定义getpet(Person p)方法,(我随便写的),因为这里用到了Person 非基础类型的数据,因此我们还要另外做一些操作:
1.建立Person.aidl文件。代码如下:
package com.example.lenovo.aidltest3;
parcelable Person;
注意了这里有一个让我纠结了几个小时的问题:
在IMyaidlInterface接口中我的代码如下:
<span style="background-color: rgb(255, 255, 51);">package com.example.lenovo.aidltest3;</span>
<span style="background-color: rgb(255, 255, 51);">import com.example.lenovo.aidltest3.Person;</span>
interface IMyAidlInterface {
Person getpet(in Person p);
void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat,
double aDouble, String aString);
}
必须要导入上面画颜色的代码。否则在无法生成java接口,因为错误:产生的问题原因
Error:Execution failed for task ':app:compileDebugAidl'.
> java.lang.RuntimeException: com.android.ide.common.process.ProcessException: org.gradle.process.internal.ExecException: Process 'command 'F:android_studio_sdkbuild-tools23.0.2aidl.exe'' finished with non-zero exit value 1
这个错误楼主在百度上找了半天没找到,最后无意间找到了,该问题产生的原因是:
没有 “import com .example.lenovo.aidltest3.Person” 这句话
2.定义一个Service,这里我写的是MyService 具体代码如下:
package com.example.lenovo.aidltest3;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
public class MyService extends Service {
public MyService() {
}
@Override
public IBinder onBind(Intent intent) {
return new MyPerson();
}
class MyPerson extends IMyAidlInterface.Stub{
@Override
public Person getpet(Person p) throws RemoteException {
p.setId(10);
p.setName(p.getName() + " " + "这是自定义的aidl");
p.setPassword(p.getPassword()+" "+"这是自定义的aidl");
return p;
}
@Override
public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString) throws RemoteException {
}
}
}
一切搞定后 然后再make project 。然后在Mainfest文件中声明这个Service,这里我是这样生声明的:
<service
android:name=".MyService"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.aidlservice"/>
</intent-filter>
</service>
run as project 将这个server端的应用 安装到手机。
3.调用这个service: 在new 一个project项目。把前一个项目的aidl文件夹直接copy到这个项目中: 注意:copy到这个项目中的时候,as会自动把包名改动。因此我们需要手动再把包名改回来,和前一个项目的aidl文件夹要一摸一样。
又要注意了:改动包名还是一个次要,还要把 Person类也要copy到这个项目中,所在的包名也要和上一个项目中的包名要一摸一样。这里我就把我建立的client端,目录结构给大家看下。
这些配置搞定之后,然后就可以在主activity代码中启动service了具体代码如下:
package com.example.lenovo.ipcclient2;
import android.app.Service;
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.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
import com.example.lenovo.aidltest3.IMyAidlInterface;
import com.example.lenovo.aidltest3.Person;
public class MainActivity extends AppCompatActivity {
public ServiceConnection connection=new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
IMyAidlInterface im=IMyAidlInterface.Stub.asInterface(service);
try {
<span style="background-color: rgb(255, 255, 51);"> Person p= im.getpet(new Person(5, "123", "789"));
Toast.makeText(MainActivity.this,p.getName(),Toast.LENGTH_SHORT).show();</span>
} catch (RemoteException e) {
e.printStackTrace();
}
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
};
Button but;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
but=(Button)findViewById(R.id.start);
but.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent=new Intent();
<span style="background-color: rgb(255, 255, 51);"> intent.setPackage("com.example.lenovo.aidltest3");
intent.setAction("android.intent.action.aidlservice");</span>
bindService(intent,connection, Service.BIND_AUTO_CREATE);
}
});
}
}
注意:intent 必须要设置package名称,否则会出现intent不确切的错误。
这样 我们就可以调用另外一个应用的service了。
提供一个demo:http://download.csdn.net/detail/wuyuxing24/8912699#comment
今天就写到这,其实这都是我今天学习的,做一个笔记供以后翻阅。
最后
以上就是温婉冰棍为你收集整理的android 跨进程调用service学习(二)的全部内容,希望文章能够帮你解决android 跨进程调用service学习(二)所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复