Android AIDL iBinder NullPointerException

时间:2016-02-28 15:36:15

标签: android uibinder aidl

目的:使用AIDL来传达两个应用程序(一个称为服务,一个称为客户端)

条件:IDE:Android Studio,在服务中,我定义了一个IPerson.aidl(在此文件中我定义了一个名为queryPerson的接口),AS将在GENERATED目录中生成IPerson.java。我还在main中添加了IntentFilter(action,category)AndroidMainfest.xml。我创建了一个AIDLService来扩展IPerson.Stub并实现接口queryPerson。之后,我创建另一个名为client的应用程序与服务进行通信但是得到了NOPOINTER异常

这里是服务代码: IPerson.aidl:

// IPerson.aidl
package com.example.jason.aidldemo;

// Declare any non-default types here with import statements

interface IPerson {
    /**
     * Demonstrates some basic types that you can use as parameters
     * and return values in AIDL.
     */

    String queryPerson(int num);
}

AIDLService.java:

package com.example.jason.aidldemo;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;

public class AIDLService extends Service {

    private IBinder iBinder=new PersonQueryBinder();

    private String [] names={"Apple","Banana","peach"};

    private String query(int num)
    {
        if(num>0 && num<4)
        {
            return names[num-1];
        }
        return null;
    }
    public AIDLService() {
    }

    private final class PersonQueryBinder extends IPerson.Stub
    {
        @Override
        public String queryPerson(int num) throws RemoteException {
            return query(num);
        }
    }
    @Override
    public IBinder onBind(Intent intent) {
        // TODO: Return the communication channel to the service.
        return null;
    }
}

AndroidMainfest.xml:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.jason.aidldemo" >

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name=".MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

        <service
            android:name=".AIDLService"
            android:enabled="true"
            android:exported="true" >
            <intent-filter>
                <action android:name="android.intent.action.AIDLService"/>
                <category android:name="android.intent.category.DEFAULT"/>
            </intent-filter>
        </service>
    </application>

</manifest>

在客户端:

活性-main.xml中:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".MainActivity">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/hello_world"
        android:id="@+id/textView" />
    <EditText
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/edit_num"
        android:layout_below="@+id/textView"
        android:layout_alignParentStart="true" />

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Query"
        android:id="@+id/btn_query"
        android:layout_below="@+id/edit_num"
        android:layout_alignParentStart="true"
        android:layout_marginTop="26dp" />
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/tx_name"
        android:layout_marginTop="20dp"
        android:layout_below="@+id/btn_query" />
</RelativeLayout>

MainActivity.java:

package com.example.jason.aidlclient;

import android.app.Activity;
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.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;

import com.example.jason.aidldemo.IPerson;


public class MainActivity extends Activity implements View.OnClickListener {

    private IPerson iPerson;
    private Button btn_query;
    private TextView tx_name;
    private EditText edit_name;
    private PersonConnection pconn=new PersonConnection();


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

        bindView();
        //bind remoted service
        Intent service=new Intent("android.intent.action.AIDLService");
        service.setPackage("com.example.jason.aidldemo");
        bindService(service,pconn,BIND_AUTO_CREATE);

    }

    private void bindView()
    {
        edit_name= (EditText) findViewById(R.id.edit_num);
        btn_query= (Button) findViewById(R.id.btn_query);
        tx_name= (TextView) findViewById(R.id.tx_name);
        btn_query.setOnClickListener(this);
    }

    /**
     * Called when a view has been clicked.
     *
     * @param v The view that was clicked.
     */
    @Override
    public void onClick(View v) {
        switch (v.getId())
        {
            case  R.id.btn_query:
                String number=edit_name.getText().toString();
                int num=Integer.valueOf(number);
                try{
                    String temp=iPerson.queryPerson(num);
                    tx_name.setText(temp);
                } catch (RemoteException e) {
                    e.printStackTrace();
                }
                edit_name.setText("");
                break;
        }
    }

    private final class PersonConnection implements ServiceConnection{


        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            iPerson= (IPerson.Stub) IPerson.Stub.asInterface(service);
        }

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

}

我希望Demo像这样运行:

enter image description here

但问题是NOPOINTER 希望有人教我!谢谢!

1 个答案:

答案 0 :(得分:1)

您的服务正在返回空绑定器。你必须像这样返回AIDL接口存根:

@Override
public IBinder onBind(Intent intent) {
    // TODO: Return the communication channel to the service.
    return new IPerson.Stub(){
             @Override
             public String queryPerson(int num) throws RemoteException {
                 return query(num);
             } 
        }
}