I have an activity class that contains a button. When I click the button it starts a service that will populate my SQLite database in a separate thread. Once the service completes I would like a textview in my activity class to display a new value from the database.
I have everything set up correctly and my database is storing the correct info. The only thing I am still confused on is how do I tell my activity class that the service is complete?
You can send a broadcast when your service completes.
In your activity onResume
IntentFilter intentFilter = ; //Look up how to make an intent filter with an action as specified in the below service code
receiver =new BroadcastReceiver();
this.registerReceiver(receiver, intentFilter);
In your activity onPause
this.unregisterReceiver(receiver);
In your service.
Intent broadcastIntent = new Intent();
broadcastIntent.setAction("com.blablablaablla.ACTION_REFRESH");
this.sendBroadcast(broadcastIntent);
Create an Intent with your own action name "mike.intent.DB_POPULATE_DONE" or something... it's just a string you can examine in onNewIntent() if you choose to.
Send an Intent from the Service by calling Context.startActivity().
To receive the Intent, implement Activity.onNewIntent()
Related
So I have broadcast receiver that is getting started on boot. I have an activity that using the information being collected by the broadcast receiver. I want the activity to be able to update its recycler view every time the broadcast receiver is called, the problem is the activity has no reference to the broadcast receiver. Is there a way that I can have my activity listen for the broadcasts and update itself?
The only thing I can think of is having the activity run a repeating task that will try to update itself with new information. This doesn't seem like a good solution to me.
the best approach is to register a BroadcastReceiver - see documentation on this. In your case you'd want to Programmatically register a broadcast receiver so that the onReceive(Context context, Intent intent) from inside the Activity class. In this way, you can then update the Recyclerview as you desire. Something like:
public void onCreate(Bundle savedInstanceState){
...
IntentFilter filter = new IntentFilter();
//you may want to set whatever filters here...
//define the broadcast receiver
receiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
//here you can update the RecyclerView as you desire using intent's data
}
};
//register the broadcast receiver
registerReceiver(receiver, filter);
}
I strongly recommend that you go through this nice BroadcastReceiver tutorial.
Enjoy.
The broadcast receiver registered for BOOT_COMPLETED action has nothing to do with the activity, it's a separate component. So, yes, you don't have a reference to your activity and you should not run any periodical task.
What I would do is to write the collected data to the database or shared preferences and then read it when your activity is actually on the screen.
If you use an SQLite database you can use a ContentObserver to notify your activity about changes to the underlying data. This works great with loaders.
In case of shared preferences you can use a OnSharedPreferenceChangeListener registered in your activity.
The task is to process somehow "share" intent in already running service.
As far as ACTION_SEND is an activity action we have to pick up intent in activity and broadcast it to service.
The problem is that it's logically to implement all "share intent" processing in service and use activity only for broadcasting intent.
So the service have to receive the intent (which previously received and broadcasted by activity) so we can call getType() and get****Extra***() to it in order to know what was actually shared and process this data somehow.
The intent we received in activity has the action ACTION_SEND (or ACTION_SEND_MULTIPLE), right? So logically we can change action with calling setAction() to intent object and broadcast it to our service which is already listening to this particular action.
public class HandleShareIntentActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Intent intent = getIntent();
Intent broadcastIntent = new Intent(intent);
// If I initialize empty intent there is no problem,
// I'll receive it in service
// Intent broadcastIntent = new Intent();
broadcastIntent.setAction(Constants.ACTION_SHARE);
broadcastIntent.setFlags(0);
sendBroadcast(broadcastIntent);
finish();
}
// ...
}
But that is not working, I'm not receiving this intent in service.
If I don't copy intent I got and broadcast an empty one, I do receive it in my service.
What I'm doing wrong?
First, to start a service, call startService(), not sendBroadcast(). There is no reason to have the service respond to broadcasts, and you are adding security problems to your app by doing so.
Second, you have to call startService() on an Intent that will identify your service (e.g., new Intent(this, ThisIsTheService.class)). In your case, you are taking an Intent identifying an activity, using a copy constructor to make a copy of it, changing the action string, and then trying to use that.
And, since an Intent is Parcelable, you could just add it as an extra to a service-specific Intent:
startService(new Intent(this, ThisIsTheService.class).putExtra(EXTRA_SEND, getIntent()));
and your service can pick EXTRA_SEND out in onHandleIntent() (if it is an IntentService) or onStartCommand() (if it is not). This code snippet assumes that you define EXTRA_SEND to be some string somewhere.
I am developing an android application. This application architecture is divided into 5 modules with 2 modules having multiple features. To develop this app, I am creating 2 process with multiple threads in them as required and 3 other threads. I have a some questions regarding this implementation:
Is this a good model? If not, why not? Right now I am considering only modularity.
I need to send a message from broadcast receiver in process1 to Service thread in process2, what is the best way to do it?
what is the best IPC mechanism in android? I tried to use this link, http://androidapps.org.ua/androidintro_ipc_intent.html which suggests startActivity and startActivityForResult, but these options are not available in broadcast receiver and service does not have startActivityForResult option.
Thank you.
Use Custom BroadcastReceiver
Write this in ActivityA.java
Intent intent = new Intent();
intent.putExtra("message","hi");
intent.setAction("com.android.activity.SEND_DATA");
sendBroadcast(intent);
Write this in ServiceA.java
private BroadcastReceiver mMessageReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
// Extract data included in the Intent
String message = intent.getStringExtra("message");
Log.d("receiver", "Got message: " + message);
}
};
Now register Receiver
LocalBroadcastManager.getInstance(mContext).registerReceiver(mMessageReceiver,
new IntentFilter("com.android.activity.SEND_DATA"));
Just create an Intent in the BroadcastReceiver, add your data as extras, can call startService() with the Intent:
Intent intent = new Intent(context, MyService.class);
intent.putExtra("message", "whatever data you need to pass to the service");
context.startService(intent);
The method onStartCommand() will be called in your service with the passed Intent.
To answer your other question "what is the best IPC method", the answer (as always) is "that depends". Using Intents is the easiest method, as it is supported for all components out-of-the-box. If you need more complicated interaction between components you can look at using AIDL which will allow you to do remote method calls in a Service. If that still isn't enough, then just implement your own socket protocol between the 2 components.
First of all, trying to understand your terminologies. By process, I presume you mean activity and "service thread", I presume you mean a service.
If you want to send a message from onReceive() broadcast receiver, running in context of Activity 1, to a service which is already active, you can try one of the below:
1) Create a new intent (service class name as the class) and call startService() with the intent. Add the additional parameters you need as intent extras. It does not matter if your service is already active, the onStartCommand() is still called, you can have special parameters as intent extras to differentiate a onStartCommand() from onReceive.
2) If your scenario allows this, consider registering to same broadcast event in both your activity and service and act appropriately (then no need to pass messages)
3) Write another broadcast receiver in your service and call sendBroadcast() from the Activity's broadcast receiver
I'm developing a subway guide app, when reaching a new station, a notification will pop up, and the map shown in the main activity will refresh. I put the guide code in a service so that users can run other apps while being guided. But the main activity needs to be refreshed when reaching a new station, how can the service make some changes to the view in the main activity?
There are a couple of ways to do this.
You can bind the service with the activity.
You can send broadcast messages to the activity (the activity need to register with the Broadcast Reciever)
There are lot of discussions on this topic. You can go through them.
In your activity, you should register a receiver
Declare the receiver first
public class ReceiverTest extends BroadcastReceiver
{
#Override
public void onReceive(Context context, Intent intent)
{
// extras from service
int key = intent.getIntExtra("key", 0);
//do things here
}
}
Register it in OnCreate of your activity
ReceiverTest mReceiver = new ReceiverTest();
IntentFilter filter;
filter = new IntentFilter("packagename.dosomething");
registerReceiver(mReceiver, filter);
Then, in your service, broadcast the event
Intent i = new Intent("packagename.dosomething");
// You could put the information in extras, then get the value in receiver
i.putExtra("key", 123);
context.sendBroadcast(i);
The best way to share data between the Service S and Activity A
Use the local binding pattern and have Activity A bind to Service S, then call the service's exposed API to retrieve whatever is needed.
How can the external activity B communicate with the Service S to determine if it has completed with all its preprocessing, and the Activity A is ready to be invoked?
Use the remote binding pattern and AIDL. Activity B would register an AIDL-defined callback with Service S, which the service would invoke when appropriate. See here and here for an example.
I'm just getting into Android development, and I have a question about communicating between a receiver class and an activity class. I'm very new to JAVA and Android so I hope I don't sound too stupid. I'm developing an application where I intercept an SMS message and then based on various elements of that SMS I might delete it once it's been saved to the inbox. I have a receiver class that intercepts the txt message, and I am also able to delete messages from my inbox with code in the activity class using a button at the moment. The problem I have is communicating between the receiver class and the activity class where the code to delete a message resides. I tried putting that code directly into the receiver class but as I'm sure most of you already know the BroadcastReceiver class doesn't seem to support what I need to delete messages. I've been searching for an answer to this for a while, but haven't been able to find anything. Honestly I'm not sure I know enough about JAVA and Android to even recognize a solution if I saw it.
If you need to complete a job without an interface look into creating a Service, if you need user interface just start an Activity
You can use the Context parameter of the onReceive method of the receiver to start a new service/activity
You can use Extras to pass params between context. So you can put as extra the message id or entire message and pass it to your service/activity and deal it there.
You could implement the handling messages logic using an IntentService. When your receiver gets the new incomming message, start the IntentService passing an intent with the message data.
Receiver
onReceive(Context context, Intent intent) {
//Setup Intent
Intent i = new Intent(context, MyIntentService.class);
i.setAction(MyIntentService.HANDLE_MESSAGE);
//Pass data to intent
i.putExtra(MyIntentService.MESSAGE_DATA, data);
//Start Intent Service
context.startService(i);
}
MyIntentService
onHandleIntent(Intent i){
String action = i.getAction();
if(action != null && action.equals(MyIntentService.HANDLE_MESSAGE){
//Get data and implement message logic
}
}
Hope it helps.