我是靠谱客的博主 温婉冰棍,最近开发中收集的这篇文章主要介绍android 跨进程调用service学习(二),觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

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学习(二)所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(24)

评论列表共有 0 条评论

立即
投稿
返回
顶部