I am trying to use the LocalBroadcastManager inside an android service.
public class WebSocketService extends Service {
private static final String TAG = "WebSocketService";
private WebSocketClient mWebSocketClient;
public WebSocketService() {
connectWebSocket();
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
private void connectWebSocket() {
URI uri;
try {
uri = new URI("wss://echo.websocket.org");
} catch (URISyntaxException e) {
e.printStackTrace();
return;
}
mWebSocketClient = new WebSocketClient(uri) {
@Override
public void onOpen(ServerHandshake serverHandshake) {
Log.i(TAG, "Websocket Opened");
mWebSocketClient.send("Hello from " + Build.MANUFACTURER + " " + Build.MODEL);
}
@Override
public void onMessage(String message) {
Log.i(TAG, "Websocket Received: " + message);
Intent broadcastIntent = new Intent("custom-event");
broadcastIntent.putExtra("message", message);
LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(broadcastIntent);
}
@Override
public void onClose(int code, String reason, boolean remote) {
Log.i(TAG, "Websocket closed: " + reason);
}
@Override
public void onError(Exception ex) {
Log.i(TAG, "Websocket error");
}
};
}
public void sendMessage(String message) {
mWebSocketClient.send(message);
}
}
The main Activity where the websocket gets created.
public class MainActivity extends Activity {
private WebSocketService webSocketService;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
webSocketService = new WebSocketService();
}
public void send(View view) {
webSocketService.sendMessage("socket message");
}
}
and its xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.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">
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button"
android:onClick="send"
tools:layout_editor_absoluteX="166dp"
tools:layout_editor_absoluteY="288dp" />
</androidx.constraintlayout.widget.ConstraintLayout>
The above does no compile with exception
After changing LocalBroadcastManager.getInstance(this).sendBroadcast(broadcastIntent);
to
LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(broadcastIntent);
I get the error
Error Attempt to invoke virtual method 'android.content.Context android.content.Context.getApplicationContext()' on a null object reference
My question is whether its possible to pass the context while creating
mWebSocketClient = new WebSocketClient(uri) {
}
such that the LocalBroadcastManager can be used or not?
The question in general is, is it possible to get the applicationContext inside an annoymous namespace.
To get an outerScope this inside an annoymous method / inner class of any java class you can either call WebSocketService.this
LocalBroadcastManager.getInstance(WebSocketService.this).sendBroadcast(broadcastIntent);
or declare a private helper method for the same
private WebSocketService getOuterWebSocketService() {
return this;
}
Now you can use this method inside onMessage as below
@Override
public void onMessage(String message) {
Log.i(TAG, "Websocket Received: " + message);
Intent broadcastIntent = new Intent("custom-event");
broadcastIntent.putExtra("message", message);
LocalBroadcastManager.getInstance(getOuterWebSocketService()).sendBroadcast(broadcastIntent);
}