Reputation: 1295
I am currently trying to write a simple chat application on Android.
It takes speech, converts it into text, then sends it to the server.
I want to be able to use TextToSpeech to read the response that the server gives.
I keep getting java.lang.NullPointerException: Attempt to invoke interface method 'void {MYAPPNAME}.MyCallback.callbackCall()' on a null object reference
. I have looked at other questions with similar answers, but they are conflicting, as they say "the interface should be instantiated first" or "you don't instantiate interfaces", etc., and is confusing me.
The receiver:
public class MainActivity extends ActionBarActivity implements TextToSpeech.OnInitListener, MyCallback {
...
private void sendToServer(String msg) {
cThread = new ClientThread();
cThread.msg = msg;
Thread thread = new Thread(cThread);
thread.start();
}
@Override
public void callbackCall() {
Log.d("CALLBACK", cThread.serverResponseSaved);
// Do the speaking here.
}
}
The actual code responsible for messages:
interface MyCallback {
public void callbackCall();
}
public class ClientThread implements Runnable {
String address = "XXX.XXX.X.XX";
int port = YYYYY;
boolean connected = false;
String msg = "";
private String serverResponse;
String serverResponseSaved;
MyCallback callback;
@Override
public void run() {
try {
Socket socket = new Socket(address, port);
this.connected = true;
while(connected) {
try {
PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())), true);
out.println(this.msg);
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
if ((serverResponse = in.readLine()) != null) {
serverResponseSaved = serverResponse;
Log.i("server says", serverResponseSaved);
callback.callbackCall();
}
} catch (Exception e) {
e.printStackTrace();
}
}
} catch (IOException e) {
e.printStackTrace();
this.connected = false;
}
}
}
Is the way I'm implementing the interface wrong?
EDIT:
Trying to instantiate it by:
callback = new MyCallback();
Gives me a 'MyCallback is abstract. Cannot be instantiated.'
error.
The use of interface is based on: Here
Upvotes: 1
Views: 801
Reputation: 1177
You are not setting callback
anywhere. You define it as MyCallback
and give it a name callback
but it still has nothing assigned to it, hence the NullPointerException
when you hit callback.callbackCall();
I'm assuming you want to set it to the MainActivity
you linked, so you will have to pass that into ClientThread
through a constructor like:
public class ClientThread implements Runnable {
public ClientThread(MyCallback callback){
this.callback = callback;
}
}
then change:
cThread = new ClientThread();
to
cThread = new ClientThread(this);
however if your callback function wants to do any UI related things, or anything that should run on the main thread, you will have to use a handler to post it to the main thread. If you want to do that, it would be easiest to pass in a Context
into ClientThread
and do something like this:
public class ClientThread implements Runnable {
/*your things*/
Context mCtx;
public ClientThread(Context context){
this.mCtx = context;
if(context instanceof MainActivity){
this.callback = (MainActivity) callback;
}
}
}
Then change the callback bit to:
Handler mainHandler = new Handler(mCtx.getMainLooper());
mainHandler.post(new Runnable() {
@Override
public void run() {
callback.callbackCall();
}
});
Upvotes: 1