我正在使用带有进程间通信(IPC)的绑定服务编写程序。目标是使用Messenger和Hanler将生成的数据从服务发送到mainActivity的线程(DataExchange)。当数据从run方法放入消息队列时,我无法在activityHandler(mainActivity)中接收它。幸运的是,我可以在serviceHandler(本地通信)中接收数据,但是当我尝试从serviceHandler(服务)向activityHandler(mainActivity)发送相同的消息时,我得到了一个致命的例外
java.lang.NullPointerException:尝试调用虚方法' void android.os.Messenger.send(android.os.Message)'在空对象引用上
有人请帮忙
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
private static final String TAG = MainActivity.class.getSimpleName();
private static final int WRITE = 2;
private static final int READ = 3;
private static final int SEND = 4;
private static final int UPDATE = 5;
TextView textView;
Messenger activityMessenger;
boolean bound = false;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textView = (TextView)findViewById(R. id. textView);
Intent bindBtService = new Intent(this, BluetoothService.class);
bindService(bindBtService, serviceConnection, Context.BIND_AUTO_CREATE);
}
private ServiceConnection serviceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
activityMessenger = new Messenger(service);
bound = true;
}
@Override
public void onServiceDisconnected(ComponentName name) {
unbindService(serviceConnection);
activityMessenger = null;
bound = false;
}
};
//Send a command to the service requesting data update
public void getMessage(View view) {
String button_text = (String) ((Button)view).getText();
if (button_text.equals("Message from the service")){
//create a message object
Message msg = Message.obtain(null, WRITE);
//specify the reply handler
msg.replyTo = new Messenger(new activityHandler());
try {
activityMessenger.send(msg);
} catch (RemoteException e) {
e.printStackTrace();
}
}
}
/*To process Incoming massages from the service*/
class activityHandler extends Handler{
@Override
public void handleMessage(Message msg) {
String received;
switch (msg.what){
case READ:
received = msg.getData().getString("response_message");
Log.i(TAG, "From ButtonClick " + received);
textView.setText(received);
break;
case UPDATE:
received = msg.getData().getString("update");
//for debugging
Log.i(TAG, "From Run Method " + received);
textView.setText(received);
break;
default:
super.handleMessage(msg);
}
}
}
@Override
protected void onDestroy() {
unbindService(serviceConnection);
activityMessenger = null;
bound = false;
super.onDestroy();
}
}
import android.app.Service;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;
import android.os.SystemClock;
import android.util.Log;
import java.util.Random;
public class BluetoothService extends Service {
private static final String TAG = BluetoothService.class.getSimpleName();
private static final int MAC_ADDRESS = 1;
private static final int WRITE = 2;
private static final int READ = 3;
private static final int SEND = 4;
private static final int UPDATE = 5;
private String Data = " ";
private String incomingData;
private DataExchange dataExchange;
private Rand randomize;
//Messenger serviceMessenger;
Messenger serviceMessenger = new Messenger(new ServiceHandler());
public BluetoothService() {
//Log.i(TAG, "Inside CONSTRUCTOR");
incomingData = Data;
}
@Override
public void onCreate() {
super.onCreate();
//Log.i(TAG, "Inside ONCREATE");
//serviceMessenger = new Messenger(new ServiceHandler());
//create a new thread with a serviceHandler object
dataExchange = new DataExchange(new ServiceHandler());
dataExchange.start();
}
/*Setter and Getter to set the data from the Rand Thread class
* to be retrieved in the serviceHandler class
*/
private synchronized void setIncomingData(String rando){
incomingData = rando;
}
public synchronized String getIncomingData(){
return incomingData;
}
/*Pass the binding object Messenger with a reference of the serviceHandler
*to perform IPC communication
*/
@Override
public IBinder onBind(Intent intent) {
return serviceMessenger.getBinder();
}
class ServiceHandler extends Handler{
Messenger mess;
Message message;
String response = " ";
Bundle bundle = new Bundle();
@Override
public void handleMessage(Message msg) {
switch (msg.what){
/*Process the request from the activity and send data to update
*the textView on mainActivity
*/
case WRITE:
randomize = new Rand();
randomize.start();
while (getIncomingData().equals(" "));
//Log for debug proposes
//Log.i(TAG, "Random Number: " + getIncomingData());
response = getIncomingData();
message = Message.obtain(null, READ);
bundle.putString("response_message", response);
message.setData(bundle);
try {
msg.replyTo.send(message);
} catch (RemoteException e) {
e.printStackTrace();
}
break;
/*GET THE DATA FROM RUN METHOD AND SEND IT TO mainActivity*/
case SEND:
response = msg.getData().getString("message");
//Log for debug proposes
//Log.i(TAG, "Random Number: " );
/*Initiate message object with a identifier*/
message = Message.obtain(null, UPDATE);
//Put the and a keyword and the string message into a bundle
bundle.putString("update", response);
//Pass the bundle to the message object
message.setData(bundle);
try {
/* place the message into the message queue
* replyTo returns a reference from the receive Handler
* in this case the receive handler is the activityHandle
*/
msg.replyTo.send(message);
} catch (RemoteException e) {
e.printStackTrace();
}
default:
super.handleMessage(msg);
}
}
}
/*USING GETTER AND SETTER TO PASS DATA TO THE SERVICE HANDLER*/
private class Rand extends Thread{
public Rand() {
//Log for debug proposes
//Log.i(TAG, "Inside the thread");
}
@Override
public void run() {
//generate random numbers
Random random = new Random();
int number = random.nextInt(10) + 1;
//converts integer to string
String rando = String.valueOf(number);
//Log for debug proposes
Log.i(TAG, "Random Number has been set to :" + rando);
//Set data to be collected into the serviceHandler class
setIncomingData(rando);
SystemClock.sleep(50);
setIncomingData(" ");
}
}
/*USING HANDLER FOR COMMUNICATION*/
private class DataExchange extends Thread implements Runnable{
Handler serviceHandler;
public DataExchange(ServiceHandler serviceHandler) {
super();
//new object of the handler class to process communication
this.serviceHandler = serviceHandler;
}
@Override
public void run() {
for (int i = 0; i < 100; i++){
String val = String.valueOf(i);
try {
Thread.sleep(1000);
Message msg = prepareMessage(val);
//place message on the messageQueue
//serviceHandler.sendMessage(msg);
try {
serviceMessenger.send(msg);
} catch (RemoteException e) {
e.printStackTrace();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
/*prepare the message with a identifier, a key word and a string message
* id : UPDATE and key word :update defines a message to be sent
* to the mainActivity (Inter Process Communication "IPC")
* id : SEND and key word :message defines a message to be sent
* to the serviceHandler (Local communication)
* */
private Message prepareMessage(String string){
Bundle dataBundle = new Bundle();
/*For IPC communication*/
//Message result = serviceHandler.obtainMessage(UPDATE);
//dataBundle.putString("update", string);
/*For LOCAL communication*/
Message result = serviceHandler.obtainMessage(SEND);
dataBundle.putString("message", string);
result.setData(dataBundle);
return result;
}
}
/*
@Override
public void onDestroy() {
super.onDestroy();
serviceMessenger = null;
dataExchange = null;
}
*/
}
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="16dp"
android:layout_marginTop="32dp"
android:textSize="36sp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:text=" "
tools:textSize="30sp" />
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="48dp"
android:layout_marginEnd="148dp"
android:layout_marginLeft="148dp"
android:layout_marginRight="148dp"
android:layout_marginStart="148dp"
android:layout_marginTop="128dp"
android:onClick="getMessage"
android:text="Message from the service"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:text="Message" />
</android.support.constraint.ConstraintLayout>
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.seber.lisah">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service
android:name=".BluetoothService"
android:enabled="true"
android:exported="true"></service>
</application>
</manifest>
06-08 16:53:14.466 2072-2072/com.seber.lisah E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.seber.lisah, PID: 2072
java.lang.NullPointerException: Attempt to invoke virtual method 'void android.os.Messenger.send(android.os.Message)' on a null object reference
at com.seber.lisah.BluetoothService$ServiceHandler.handleMessage(BluetoothService.java:111)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5221)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:899)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694)