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_sdk\build-tools\23.0.2\aidl.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


今天就写到这,其实这都是我今天学习的,做一个笔记供以后翻阅。








  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要在 Android 中实现进程调用 Toast,您需要使用 AIDL(Android 接口定义语言)来定义一个接口,该接口将允许其他应用程序与您的应用程序进行通信。然后,您可以在您的应用程序中实现此接口,并将其公开为服务。其他应用程序可以绑定到您的服务,并使用该接口调用 Toast 方法,从而在您的应用程序中显示 Toast。 以下是一个简单的示例代码: 1. 在您的应用程序中创建一个 AIDL 文件,例如 IToast.aidl,其中包含以下内容: ``` interface IToast { void showToast(String message); } ``` 2. 实现该接口并将其公开为服务: ``` public class ToastService extends Service { private final IBinder mBinder = new ToastBinder(); @Override public IBinder onBind(Intent intent) { return mBinder; } private void showToast(String message) { Toast.makeText(this, message, Toast.LENGTH_SHORT).show(); } private class ToastBinder extends IToast.Stub { @Override public void showToast(String message) { ToastService.this.showToast(message); } } } ``` 3. 在您的应用程序中启动服务: ``` Intent intent = new Intent(this, ToastService.class); startService(intent); ``` 4. 在其他应用程序中绑定到您的服务,并使用 AIDL 接口调用 showToast 方法: ``` private IToast mToastService; private ServiceConnection mConnection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { mToastService = IToast.Stub.asInterface(service); } @Override public void onServiceDisconnected(ComponentName name) { mToastService = null; } }; private void showToast(String message) { try { if (mToastService != null) { mToastService.showToast(message); } } catch (RemoteException e) { e.printStackTrace(); } } ``` 请注意,为了使此代码正常工作,您需要确保您的应用程序和其他应用程序都具有相应的权限。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值