Service中传递自定义类的问题分析

来源:互联网 发布:java 线程怎么实线的 编辑:程序博客网 时间:2024/06/06 04:37

Service中传递自定义类的问题分析

这两天自学利用AIDL传递自定义类发现在Android studio中一直出现编译问题,两天时间寝食不安,吃东西还过敏。。哎。不过总算研究出来了,也是让人欣慰的一件事情。

问题描述:在路径,设置都没错误的情况下,Android studio中编译一直不能通过,总会出现同一个问题,然后aidl.exe 关闭退出:

Information:Gradle tasks [:app:assembleDebug]:app:preBuild UP-TO-DATE:app:preDebugBuild UP-TO-DATE:app:checkDebugManifest:app:preReleaseBuild UP-TO-DATE:app:prepareComAndroidSupportAppcompatV72221Library UP-TO-DATE:app:prepareComAndroidSupportSupportV42221Library UP-TO-DATE:app:prepareDebugDependencies:app:compileDebugAidlThis application has requested the Runtime to terminate it in an unusual way.Please contact the application's support team for more information.**terminate called after throwing an instance of 'std::logic_error'  what():  basic_string::_S_construct null not validError:Execution failed for task ':app:compileDebugAidl'.> com.android.ide.common.process.ProcessException: org.gradle.process.internal.ExecException: Process 'command 'E:\sdk\build-tools\23.0.0-preview\aidl.exe'' finished with non-zero exit value 3Information:BUILD FAILED**Information:Total time: 4.379 secsInformation:1 errorInformation:0 warningsInformation:See complete output in console

解决过程:查了很多网站,发现遇到的都是aidl is missing,好像没有遇到我这个问题的。他们的解决办法是右键选择app->open module setting-> 改变Build Tools Version 的版本。可能是因为编译器和sdk的版本不兼容的问题。参照[http://blog.csdn.net/songjinshi/article/details/46351851]

解决问题方案:
经过反复的新建项目,复制代码,改配置。突然发现一个问题。在Eclipse中自定义类可以不用添加包名,就可以编译成功。然后在Android Studio中就不行。
最后的解决办法就是在Person和Pet中添加包名就不会再有编译问题了。
这里写图片描述

值得说一句的是,在Android Studio中添加aidl文件,需要建立一个和java文件夹并列的aidl文件夹,然后包名也要一样。其实如果你通过右键点击创建aidl文件的时候,一般会自动创建这个目录结构。
接口IPet.aidl和Person.aidl,Pet.aidl自定义类放在一个目录中,Person和Pet的类文件,放在java文件夹下面。不得不说这样的分类结构还是很清晰明了的。本示例的代码是同一个应用程序中访问服务,然后返回某个人的宠物。大家也可以新建一个app,然后访问这个app的service。不多说了,上代码。

Pet.aidl

package com.x.myapplication;parcelable Pet;

Person.aidl

package com.x.myapplication;parcelable Person;

IPet.aidl

// IPet.aidlpackage com.x.myapplication;import com.x.myapplication.Person;import com.x.myapplication.Pet;interface IPet {    List<Pet> getPets(in Person owner);}

Person.java

package com.x.myapplication;import android.os.Parcel;import android.os.Parcelable;/** * Description: * <br/>网站: <a href="http://www.crazyit.org">疯狂Java联盟</a> * <br/>Copyright (C), 2001-2012, Yeeku.H.Lee * <br/>This program is protected by copyright laws. * <br/>Program Name: * <br/>Date: * @author  Yeeku.H.Lee kongyeeku@163.com * @version  1.0 */public class Person implements Parcelable {    private Integer id;    private String name;    private String pass;    public Person() {    }    public Person(Integer id, String name, String pass) {        super();        this.id = id;        this.name = name;        this.pass = pass;    }    public Integer getId() {        return id;    }    public void setId(Integer id) {        this.id = id;    }    public String getName() {        return name;    }    public void setName(String name) {        this.name = name;    }    public String getPass() {        return pass;    }    public void setPass(String pass) {        this.pass = pass;    }    @Override    public int hashCode() {        final int prime = 31;        int result = 1;        result = prime * result + ((name == null) ? 0 : name.hashCode());        result = prime * result + ((pass == null) ? 0 : pass.hashCode());        return result;    }    @Override    public boolean equals(Object obj) {        if (this == obj)            return true;        if (obj == null)            return false;        if (getClass() != obj.getClass())            return false;        Person other = (Person) obj;        if (name == null) {            if (other.name != null)                return false;        } else if (!name.equals(other.name))            return false;        if (pass == null) {            if (other.pass != null)                return false;        } else if (!pass.equals(other.pass))            return false;        return true;    }    @Override    public int describeContents() {        return 0;    }    @Override    public void writeToParcel(Parcel dest, int flags) {        //把该对象所包含的数据写到Parcel        dest.writeInt(id);        dest.writeString(name);        dest.writeString(pass);    }    // 添加一个静态成员,名为CREATOR,该对象实现了Parcelable.Creator接口    public static final Creator<Person> CREATOR            = new Creator<Person>() {        @Override        public Person createFromParcel(Parcel source) {            // 从Parcel中读取数据,返回Person对象            return new Person(source.readInt(), source.readString()                    , source.readString());        }        @Override        public Person[] newArray(int size) {            return new Person[size];        }    };}

Pet.java

import android.os.Parcel;import android.os.Parcelable;public class Pet implements Parcelable{    private String name;    private double weight;    public Pet()    {    }    public Pet(String name, double weight)    {        super();        this.name = name;        this.weight = weight;    }    public String getName()    {        return name;    }    public void setName(String name)    {        this.name = name;    }    public double getWeight()    {        return weight;    }    public void setWeight(double weight)    {        this.weight = weight;    }    @Override    public int describeContents()    {        return 0;    }    /* (non-Javadoc)     * @see android.os.Parcelable#writeToParcel(android.os.Parcel, int)     */    @Override    public void writeToParcel(Parcel dest, int flags)    {        //把该对象所包含的数据写到Parcel        dest.writeString(name);        dest.writeDouble(weight);    }    // 添加一个静态成员,名为CREATOR,该对象实现了Parcelable.Creator接口    public static final Creator<Pet> CREATOR            = new Creator<Pet>()    {        @Override        public Pet createFromParcel(Parcel source)        {            // 从Parcel中读取数据,返回Person对象            return new Pet(source.readString()                    , source.readDouble());        }        @Override        public Pet[] newArray(int size)        {            return new Pet[size];        }    };    @Override    public String toString()    {        return "Pet [name=" + name + ", weight=" + weight + "]";    }}

ComplexService.java

package com.x.myapplication;import java.util.ArrayList;import java.util.HashMap;import java.util.List;import java.util.Map;import android.app.Service;import android.content.Intent;import android.os.IBinder;import android.os.RemoteException;public class ComplexService extends Service {    private PetBinder petBinder;    private static Map<Person, List<Pet>> pets            = new HashMap<Person, List<Pet>>();    static {        // 初始化pets Map集合        ArrayList<Pet> list1 = new ArrayList<Pet>();        list1.add(new Pet("旺财", 4.3));        list1.add(new Pet("来福", 5.1));        pets.put(new Person(1, "sun", "sun"), list1);        ArrayList<Pet> list2 = new ArrayList<Pet>();        list2.add(new Pet("kitty", 2.3));        list2.add(new Pet("garfield", 3.1));        pets.put(new Person(2, "bai", "bai"), list2);    }    // 继承Stub,也就是实现额IPet接口,并实现了IBinder接口    public class PetBinder extends IPet.Stub {        @Override        public List<Pet> getPets(Person owner) throws RemoteException {            // 返回Service内部的数据            return pets.get(owner);        }    }    @Override    public void onCreate() {        super.onCreate();        petBinder = new PetBinder();    }    @Override    public IBinder onBind(Intent arg0) {        /* 返回catBinder对象         * 在绑定本地Service的情况下,该catBinder对象会直接         * 传给客户端的ServiceConnection对象         * 的onServiceConnected方法的第二个参数;         * 在绑定远程Service的情况下,只将catBinder对象的代理         * 传给客户端的ServiceConnection对象         * 的onServiceConnected方法的第二个参数;         */        return petBinder;    }    @Override    public void onDestroy() {    }}

MainActivity.java

import android.app.Service;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.ActionBarActivity;import android.os.Bundle;import android.util.Log;import android.view.View;import android.widget.ArrayAdapter;import android.widget.Button;import android.widget.EditText;import android.widget.ListView;import java.util.List;public class MainActivity extends ActionBarActivity {    private IPet petService;    private Button get;    EditText personView;    ListView showView;    private ServiceConnection conn;    @Override    public void onCreate(Bundle savedInstanceState)    {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        personView = (EditText) findViewById(R.id.person);        showView = (ListView) findViewById(R.id.show);        get = (Button) findViewById(R.id.get);        // 创建所需绑定服务的Intent        Intent intent = new Intent();        intent.setAction("COMPLEX_SERVICE1");        conn = new ServiceConnection()        {            @Override            public void onServiceConnected(ComponentName name, IBinder service)            {                // 获取远程Service的onBind方法返回的对象的代理                Log.i("TAG", "Service is Connected");                petService = IPet.Stub.asInterface(service);            }            @Override            public void onServiceDisconnected(ComponentName name)            {                Log.i("TAG", "Service is Disconnected");                petService = null;            }        };        // 绑定远程服务        bindService(intent, conn, Service.BIND_AUTO_CREATE);        get.setOnClickListener(new View.OnClickListener()        {            @Override            public void onClick(View arg0)            {                try                {                    String personName = personView.getText().toString();                    Log.i("TAG", "personName is "+personName);                    // 调用远程Service的方法                    Log.i("TAG", "petService is " + petService);                    List<Pet> pets = petService.getPets(                            new Person(1, personName , personName));                    // 将程序返回的List包装成ArrayAdapter                    ArrayAdapter<Pet> adapter = new ArrayAdapter<Pet>(                            MainActivity.this                            , android.R.layout.simple_list_item_1                            , pets);                    showView.setAdapter(adapter);                }                catch (RemoteException e)                {                    e.printStackTrace();                }            }        });    }    @Override    public void onDestroy()    {        super.onDestroy();        // 解除绑定        this.unbindService(conn);    }}

AndroidManifest.xml

<service android:name=".ComplexService">
<intent-filter >
<action android:name="COMPLEX_SERVICE1"/>
</intent-filter>
</service>

0 0