I am new in Android so I hope you can excuse my ignorance
I made an activity to control some bluetooth devices with my telephone, now that everything is working I would like to generate a new class from this activity, a class to take care of all bluetooth communication.
I have some questions:
First: In my activty I employed one broadcast receiver to listen to some actions of the Bluetooth Adapter like STATE_ON, BOND_BONDED... Using this actions I update my views, I call some methods and so on.
So, it is possible to keep listening to this broadcast receiver inside my class and then send the changes to my main activity to update the views and so on?
Second: I really need to send information from my bluetooth class to my main activity, information that I read from my devices, information from the broadcast receiver... so, which is the best way to pass information between a class and the main activity?
Well, thanks a lot for your help :)
The onReceive() method of your BroadcastReceiver is called from the main thread:
"This method is always called within the main thread of its process" (http://developer.android.com/reference/android/content/BroadcastReceiver.html#onReceive(android.content.Context, android.content.Intent)).
That means you can update your ui from the onReceive() method. All you need to do is use a local class like so:
BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
// update the ui
}
};
Register this receiver programmatically (instead of defining it in the manifest) and you're good to go:
Context.registerReceiver(android.content.BroadcastReceiver, android.content.IntentFilter)
Related
Is it possible to send an intent from a service to an Application class? Not Activity?
I wouldn't know what activity would be running at a particular time, so I am adding a boolean flag in the activity class that detects the activity and sends the appropriate data based on the broadcast received.
If your Service is active, then your Application class is active as well.
Otherwise you wouldn't be able to use getApplicationContext().
Although I'm skeptic about a service that runs forever there is a very clean way to make the Service communicate with a certain Activity, should the last one be currently active.
Such clean way is called LocalBroadcastManager.
The Activity meant to receive the data should register a BroadcastReceiver in onResume() and unregister it in onPause().
You instantiate your BroadcastReceiver in your Activity's onCreate()
this.localBroadcastReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
// Do what you have to do here if you receive data from the Service.
}
}
You create a Filter so your Activity only listens to a certain type of signals.
private IntentFilter notifIntentFilter new IntentFilter("com.you.yourapp.MY_SIGNAL");
in onResume()
LocalBroadcastManager.getInstance(getApplicationContext()).registerReceiver(this.localBroadcastReceiver, notifIntentFilter);
in onPause()
LocalBroadcastManager.getInstance(getApplicationContext()).unregisterReceiver(this.localBroadcastReceiver);
Now whenever you want to send data to your Activity, your Service can call:
final Intent intent = new Intent();
intent.setAction("com.you.yourapp.MY_SIGNAL");
// put your data in intent
LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(intent);
If your Activity is awake, it will respond to the signal. Otherwise, if it's in the background, or it is not instantiated it won't.
You can apply this pattern to as many Activities as you wish.
Still, I have never used this inside the Application class. But you can try to register your receiver there. It might work, since if the Application class is destroyed, the BroadcastReceiver is destroyed too and thus probably unregistered as well.
The point is, if your Application gets destroyed, your Service will be killed as well. Unless you launched it in another process. But then it will have it's own instance of Application; and this is a complex thing you probably do not want to get into details now...
Important: since the Application class is not tied to any UI component, you can do whatever you need directly inside your service. If you need to manipulate the UI, then the pattern described above will work for you.
Please read about new Android's background limitations.
Edit:
Oh yeah right, if you need your Service to call a function declared in your Application class, you can just do
((MyApplication) getApplication()).myFunctionToHandleData(Intent intent);
I didn't really understand your question though, but either of the methods described above should work for you.
I have an activity that starts a background service. Once it is started, it runs forever.
Lets say the background service needs the activity that started it to update something. Then how can I start the activity again "If it is not started" however if it is already started then send a broadcast?
Thanks
You would have to bind to the service in your activity. Then, in the service, implement the onBind and onUnbind methods to set a boolean "bound". Check the boolean to see whether the activity is active.
With activity you mean the service's process. If the service is started forever, then its process its started foerever (except when the system kill its for recovering memory purpose and recreates it later). That doesnt mean the rest of activities/fragments/services are not kill. A service is just an entry point for your application and it gives your process a position into the process priority ladder.
Its hard to say, since I don't know the details of your app, but I think that you may want to consider a bit of a redesign.
As you have noticed, Activities are ephemeral. Generally speaking, a service should not (cannot) depend on a particular Activity being active.
In fact, a well-designed service should not depend on any particular activity at all.
I'm not sure I completely follow your question. However, when communicating from a Service to an Activity I use a broadcast receiver in the Activity class.
This can be created as follows:
// register the BroadcastReceiver in your activity class
this.receiver = new NotificationReceiver();
IntentFilter filter = new IntentFilter();
filter.addAction("com.example.LISTENER");
registerReceiver(receiver, filter);
// insert in your activity class
class MyReceiver extends BroadcastReceiver{
#Override
public void onReceive(Context context, Intent intent) {
if(intent.hasExtra("command")) {
if(intent.getStringExtra("command").equals("userRegistered")) {
// insert code to do something when this intent is received
}
}
}
}
// insert in your service class to send message
Intent i = new Intent("com.example.LISTENER");
i.putExtra("command", "userRegistered");
sendBroadcast(i);
I have a BroadcastReceiver, and the onReceive is called from two different postExecute methods in two different asyncTasks, in two different Activities.
I have a third activity that is running all the time called HomeActivity, and I want to publish some text to the HomeActivity's UI from the onReceive method.
Is it possible? I know that the context parameter is the context of the activity who raised the onReceive, but I want to access the HomeActivity's UI.
Here is the code
public class MyBroadcastReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
// here I want to publish some text to the HomeActivity
}
}
any ideas? thanks in advance
You want to change text in your running activity based on what you receive in the onReceive of the BroadcastReceiver? Right? One way is that you can use LocalBroadcast. See LocalBroadcast Manager.
For how to implement is, there is a great example on how to use LocalBroadcastManager?.
LocalBroadcast Manager is a helper to register for and send broadcasts of Intents to local objects within your process. The data you are broadcasting won't leave your app, so don't need to worry about leaking private data.`
Your HomeActivity can registers for this local broadcast. From the MyBroadcastReceiver you send a LocalBroadcast from within the onReceive (saying that hey, I received a message. Do you want to do something now activity). Then inside your Activity you can listen to the broadcast. This way if the activity is in the forefront/is active, it will receive the broadcast otherwise it won't. So, whenever you receive that local broadcast, you may change the text etc, if activity is open.
I have a application that has just two activities, the main activity and a PreferenceActivity. When there is a change in states (Aeroplane mode being turned on or off, the GPS being turned on and off, etc ), I want to update both activities.
I need to update some variables and the UI only when the app is active so I guess it is better to register the receivers in code rather than in the application manifest.
As I dont want to replicate code in each activity, I tried putting the BroadcastReceiver in its own class. However then I find I am not able to register the BroadcastReceiver. Is there a way around this problem?
Thankyou, Mel
public class melsBigListener {
IntentFilter intentFilter = new IntentFilter("android.intent.action.SERVICE_STATE");
BroadcastReceiver receiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
//TO DO Update both my main activity and the preference activity
//TO DO deal with different intents via switch statement...
}
};
//registering as receiver(like below) can not work
//registerReceiver(receiver, intentFilter);}
Relevant post:RegisterBroadcastReceiver in Manifest.xml setting or by implement source code
registerReceiver(receiver, intentFilter); should be in some method.
melsBigListener should extends activity or you need to pass Activity Context to this class and use it for registerReceiver.
Instead of doing this silly stuff it is better to write register receiver in menifest file.
I suggest registering the receiver in the manifest and use it to alter variables stored in a preferences file (whether the app is running or not) and then query the preferences for state when needed.
But you could extend Application and register the receiver in code in the Application.onCreate() method.
BroadcastReceivers should work as an extended class that is registered to the phone using the manifest file. I'm not too sure how it will work as an instantiated class inside an activity. judging by your code so far, the intent will never even be received by the Activity and your BigListener class because the intent filter was never declared in the manifest.
To solve your problem:
1. create a myBroadcastReceiver, extending from BroadcastReceiver, declaring the necessary intents in the manifest
2. create a myApplication, extending from Application
3. use your Activities' onCreate, onDestroy, onStartCmd, onPause etc to manage the "only when the app is active" part, by toggling a variable in myApplication.
4. use myBroadcastReceiver to read off the variable in (3) whenever the intent is received, to decide if you "need to update some variables" and update accordingly. Since these variables are shared by your 2 Activities, the variables should be put inside the myApplication class
I have an application that get/send data from/to a remote DB on internet.
I need to get my application working in background mode, then i supose that i have to put all the send/get remote data in a service.....
but.... How can this service change values of variables and UI textfields of my activities?
i can't find any information about this, all the tutorials i am finding are of simple services that doesn't do something like that
can someone explain me how to do it please?
Use a BroadcastReceiver
In your Activity place the following code:
private BroadcastReceiver onBroadcast = new BroadcastReceiver() {
#Override
public void onReceive(Context ctxt, Intent i) {
// do stuff to the UI
}
};
Register the receiver in your onResume():
registerReceiver(onBroadcast, new IntentFilter("mymessage"));
Be sure to unregister in onPause():
unregisterReceiver(onBroadcast);
In your Service, you can post the message to the Application, which will be heard by your Activity:
getApplicationContext().sendBroadcast(new Intent("mymessage"));
If you need to, you can add data to the Intent's bundle to pass to your Activity as well.
my suggestion to you is, create a handler for the UI part which updates the text field or UI components.
Secondly, have notifications from the service to the activity by way of interface class.