Reputation: 705
I've looked at some of the other questions here on SO and none seem to be answering my question. I have a main activity with a simple button. Right now it calls startService(new Intent(MainActivity.this, BluetoothScanner.class)
which runs until it finds another bluetooth device. When this is done, I want the BluetoothScanner to report that it is complete and return something (a string perhaps) to the main activity, so I can create a popup or something that notifies the user that a bluetooth device has been seen in the vicinity. How do I best go about this?
The button looks like:
public void onClick(View v) {
switch(on) {
case 0:
startService(new Intent(this, BluetoothScanner.class));
on = 1;
break;
case 1:
stopService(new Intent(...);
on = 0;
break;
}
}
});
There seems to be some alternatives, like global variables (bad), resultReceivers,bundling stuff in intents. But I'm not sure how to do this. What would you suggest solves my problem?
Regards
Upvotes: 0
Views: 54
Reputation: 8774
There are many ways to do this, which is best depends on your particular circumstances. One simple solution with no external dependencies is to use a BroadcastReceiver
in your Activity
, override onReceive()
and do whatever you want to do there, e.g. pop up a Dialog
displaying some String
returned by your Service
. In your Service
then you would do what you need to do and when you're finished, use the LocalBroadcastManager
to send a broadcast with sendBroadcast
.
Here's a minimal example (MCVE that shows how you could do this (without the Bluetooth part, from your question it seems that's not your problem):
Example ActionBarActivity
:
public class MainActivity extends ActionBarActivity {
private Dialog dialog;
private BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
dialog = new AlertDialog.Builder(MainActivity.this)
.setTitle("Some title")
.setMessage(intent.getExtras().getString("payload"))
.setPositiveButton("OK", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
}
})
.create();
dialog.show();
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
LinearLayout layout = new LinearLayout(this);
Button button = new Button(this);
button.setText("Click!");
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
startService(new Intent(MainActivity.this, MyService.class));
}
});
layout.addView(button);
setContentView(layout);
LocalBroadcastManager.getInstance(this).registerReceiver(broadcastReceiver, new IntentFilter("MyAction"));
}
@Override
public void onDestroy() {
super.onDestroy();
LocalBroadcastManager.getInstance(this).unregisterReceiver(broadcastReceiver);
if (dialog != null && dialog.isShowing())
dialog.dismiss();
}
}
Example Service
:
public class MyService extends Service {
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
@Override
public void run() {
LocalBroadcastManager.getInstance(MyService.this).sendBroadcast(new Intent("MyAction").putExtra("payload", "Some string"));
stopSelf();
}
}, 3000);
return START_NOT_STICKY;
}
}
Example AndroidManifest.xml
:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.testso" >
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="TestSO"
android:theme="@style/Theme.AppCompat" >
<activity
android:name=".MainActivity"
android:label="TestSO" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service
android:name=".MyService"
android:exported="false" />
</application>
</manifest>
Upvotes: 1
Reputation: 1007369
I would recommend using an event bus. Have the service post a BluetoothScanCompletedEvent
or some such. Have your activity subscribe on the bus to listen for such events and do work when the event arrives.
My personal preference is greenrobot's EventBus. LocalBroadcastManager
is in the Android Support package and would also fill the role. Square's Otto is the third major event bus for Android, but its threading approach is probably not ideal for your use case.
This directory contains sample projects demonstrating all three event bus implementations.
Upvotes: 3