two services in android and one connected file? - android

In android i am using two services and i want to move some details from one to another service. Becouse of this i create new class Settings with set and get methods but i don't know how to connect two services with this one class file that i can move details from one service to another and remember each one.
for example:
i want to transfer property Boolean from service 1 to service 2 and then in service 2 check if this property is true and if is true then i execute some code in this seocnd service... hope is better explanation
class example:
public class Settings {
private int currentAudioManager;
private Boolean isChanged;
public int getCurrentAudioManager() {
return currentAudioManager;
}
public void setCurrentAudioManager(int currentAudioManager) {
this.currentAudioManager = currentAudioManager;
}
........
Hope you understand what i want.

You can register broadcast receiver and send broadcasts parceable data between your services.
public class Service1 extends Service {
#Override
public void onCreate() {
super.onCreate();
registerReceiver(recevier1, new IntentFilter("YOUR_SERVICE_ACTION1"));
// if something happen in your service"
sendBroadcast(new Intent("YOUR_SERVICE_ACTION2")); // send to second service
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
public void onDestroy() {
unregisterReceiver(recevier1);
};
Service1Receiver recevier1 = new Service1Receiver();
private class Service1Receiver extends BroadcastReceiver{
#Override
public void onReceive(Context context, Intent intent) {
intent.getExtra("me.SERVICE");// handle your data
}
}
}

Related

Android Observable Pattern with 2 Observables

Inside my activity I have a broadcast receiver that I initialize as such:
private BroadcastReceiver mReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
updateViews();
}
};
updateViews() is a function inside the activity that is only used within the broadcast receiver. How can I create this receiver as a separate class that can play with the views (rotate, delete etc.) of my activity?
In addition, I have a compass within the activity. It works, however I would also like to make the compass a separate class that can send data to the activity. It will not change the views of the activity but only update certain double/float values.
#Override
public void onSensorChanged(SensorEvent event) { }
#Override
public void onAccuracyChanged(Sensor sensor, int accuracy) { }
How can I create this receiver as a separate class...?
This answer assumes that "separate class" means you want a BroadcastReceiver that is defined in its own source file and is not an inner class of an activity. Before offering a solution, I'll ask, what do you expect to gain by this? Do you have multiple activities that will use the receiver? If not, it's best to leave it as an inner class of the single activity that uses it. If you don't like using the anonymous inner class in the code you posted, you can declare is as an inner class:
private class MyBroadcastReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
// As an inner class of the activity, this receiver has
// access to all activity members.
updateViews();
}
}
If you really want it as a standalone receiver, the example code below is a starting point. Be sure to register/unregister the receiver in your activity's onResume/onPause callbacks. The example includes code for a less safe approach, using a plain activity reference, and a safer approach using a weak reference. Only one is needed.
public class MyBroadcastReceiver extends BroadcastReceiver {
// For less safe use
private MyClientActivity mActivity;
// For more safe use
private WeakReference<MyClientActivity> mActivityRef;
public MyBroadcastReceiver(MyClientActivity activity) {
mActivity = activity;
mActivityRef = new WeakReference<MyClientActivity>(activity);
}
#Override
public void onReceive(Context context, Intent intent) {
// Less safe
mActivity.findViewById(R.id.action_bar);
mActivity.someActivityMemberMethod();
// etc
// More safe. Guards against failure to unregister
// this receiver when activity is paused.
MyClientActivity act = mActivityRef.get();
if (act != null && !act.isDestroyed()) {
mActivity.findViewById(R.id.action_bar);
mActivity.someActivityMemberMethod();
// etc
} else {
// Error: Activity failed to unregister this receiver
}
}
}
I would also like to make the compass a separate class that can send
data to the activity
Same assumption and question as above: Will the compass be used by multiple activities? If not, it's probably best to make it an inner class of the single activity. If there are multiple client activities, consider using a started-service. It could notify activities of sensor events using a local broadcast or an event bus such as greenrobot.

Passing a notification from my object to a service

I'm working in an app for android. I have a Service to manage the background process of streamming. Then I have an object AudioPlayer that manages the MediaPlayer instance and it get called from the service. But the problem I have is with the listener onPrepared, because it's within my AudioPlayer but I need that when it gets trigger send a message from my object AudioPlayer to my Service. Is it that possible?
I can try to put the logic of my MediaPlayer within Service, but I want to keep things decouple.
Yes It is possible.For communication between service and fragment you can use
1.BroadCast Receiver or 2.Messenger
Using messengers refer this link Communication between an Application class and Service in Android
Create a public interface that allows you to communicate between your service and object.
public interface MyListener {
public void receiveNotification();
}
After that, you have to make your object implements that interface.
public class MediaObject implements MyListener {
public void init () {
InitService.getService.addListener(this);
}
#Override
public void receiveNotification () {
//what you want to do
}
//rest of your class
To make it work you should have in your service class sth like:
public class YourService extends Service {
MyListener listener;
public YourService static getService () {
return YourService.this;
}
public void addListener (MyListener listener) {
this.listener = listener;
}
public void methodYouWantToCommunicateWithObject () {
//your code
if (listener!= null) {
listener.receiveNotification();
}
}

How to hold an Object as long as a service live?

I have an Object that i use in all my activities which holds a lot of complex data in it, it would be quite an hassle to use Android framework of saving the object state and passing it around from activity to activity, so i thought it would be possible to make a Singleton that manages this object and makes it live as long as the application lives.
Tried to use regular Java Singleton scheme, with normal class and normal static instance, but the instance becomes null after a while (which is very confusing, why would an Object that is still referenced be turned to null and garbage collected?). so i decided to flow with Android designers and created a Service to manage this Object, the Service looks something like that :
public class DataService extends Service {
private Data data;
private static DataService instance;
#Override
public void onCreate() {
instance = this;
data= new Data(...);
instance.data.addProgressListener(listener);
(new Thread() {
#Override
public void run() {
data.doInitProgress();
listener = null;
};
}).start();
}
public static void listenToInitDataProcess(final ProgressBar progressBar,final Runnable onDone) {
listener = new ProgressListener() {
private int progress;
private int max;
#Override
public void onUpdateProgress(final long i) {
progressBar.setProgress(progress+=i);
}
#Override
public void onProgressEndComputed(final long n) {
progressBar.setMax(max=(int) n);
}
#Override
public void onDone() {
progressBar.setProgress(max);
onDone.run();
}
};
if (instance!=null) instance.data.addProgressListener(listener);
}
public static Data getData() {
return instance.data;
}
#Override
public IBinder onBind(Intent arg0) {
return null;
}
}
now the problem with that is that after a while that the app is on i get NPE caused by instance is null... notice that i was listenning to the data object creation and i was trying to get it only after it was once inited, so no way that instance was suppose to be null...
how to do this right then?
If you want an Object that lives as long as your application lives (i.e. as long as its process is not killed by OS) you can extend android.app.Application, put your 'global' data there and use that subclass as your app context (needs to be declared in manifest)
However many argue that singletons provide essentially the same result as custom context e.g.
Singletons vs. Application Context in Android?
but the instance becomes null after a while
First, understand Effective Java's singleton recommendations, and how something wouldn't become null:
// Singleton with public final field
public class Elvis {
public static final Elvis INSTANCE = new Elvis();
private Elvis() { ... }
public void leaveTheBuilding() { ... }
}
But a Service is different, since there is no public constructor there. So, first check if the Service is running (as referenced in this post: Check if Service is running from a Broadcast Receiver):
private boolean isMyServiceRunning(Context context) {
ActivityManager manager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
for (RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
if (DataService.class.getName().equals(service.service.getClassName())) {
return true;
}
}
return false;
}
Then define some methods in your Service to return your needed state variables.

Proper notification of AsyncTaskLoader about data changes from background thread

I want to implement AsyncTaskLoader for my custom data source:
public class DataSource {
public interface DataSourceObserver {
void onDataChanged();
}
...
}
DataSource will keep list of registered observers and will notify them about changes. CustomLoader will implement DataSourceObserver. The question is how to properly notify CustomLoader since Loader.onContentChanged() must be called from UI thread but in my case DataSource operations (and calls to DataSourceObserver.onDataChanged()) will be done from background threads.
Updated with idea from Selvin tip:
public class CustomLoader extends AsyncTaskLoader<...> implements DataSource.DataSourceObserver {
private final Handler observerHandler;
public CustomLoader(Context context) {
super(context);
observerHandler = new Handler()
}
#Override
public void onDataChanged() {
observerHandler.post(new Runnable() {
#Override
public void run() {
onContentChanged();
}
});
}
}
I've had a lot of success using Local Broadcasts in a case that's very similar to yours. The method involves an AsyncTaskLoader implementation that will register a BroadcastReceiver listening for a particular String that describes what's changed. This BroadcastReceiver keeps a reference to the Loader and calls onContentChanged. When the data needs a refresh, make the Local Broadcast with the aforementioned String and the BroadcastReceiver will hear it and trigger the load. Here's some example code, it may not work perfectly if you drop it in, I've generalized some class names, but hopefully you'll get the idea:
Broadcast Receiver to be used in your Loader Implmentation:
public class LoaderBroadcastReceiver extends BroadcastReceiver
{
private Loader loader;
public LoaderBroadcastReceiver(Loader loader)
{
this.loader = loader;
}
#Override
public void onReceive(Context context, Intent intent)
{
loader.onContentChanged();
}
}
Loader Implementation registers the Receiver in onStartLoading()
private LoaderBroadcastReceiver loaderBroadcastReceiver = null;
#Override
protected void onStartLoading()
{
//... some code here
if(loaderBroadcastReceiver == null)
{
loaderBroadcastReceiver = new LoaderBroadcastReceiver(this);
LocalBroadcastManager.getInstance(getContext()).registerReceiver(loaderBroadcastReceiver, new IntentFilter("NEWDATASTRING"));
}
//... some more code here
}
Finally, here's how onDataChanged in DataSource will make the Broadcast. It'll need a Context to help send the Broadcast. Since this can be called from an arbitrary Thread, I'd use your ApplicationContext, since an Context from an Activity could cause problems if the Activity is destroyed.
public class DataSource
{
public interface DataSourceObserver
{
void onDataChanged(Context applicationContext)
{
LocalBroadcastManager.getInstance(context).sendBroadcast(new Intent("NEWDATASTRING"));
}
}
...
}
You'll probably want to play with it a bit to see how it works for you. You can use different Strings to differentiate different data that needs loading. You'll also want to unregister the Receiver at some point, perhaps in onReset(). Let me know if any of this in unclear in the comments, I'll try my best to clarify.

Accessing resources within a service (Android)

I'm a fairly new developer to android, so I get the feeling there's some property of services that I am overlooking. Please let me know.
Everything seems to be working just fine as far as services go. I have an IntentService class that looks like this:
public class MyIntentService extends IntentService
{
myClass myObject;
int test;
public MyIntentService()
{
super("MyIntentService");
test = 12;
myObject = new myClass(this, R.raw.file);
}
#Override
public IBinder onBind(Intent intent)
{
return new LocalBinder<MyIntentService>(this);
}
#Override
protected void onHandleIntent(Intent intent) {
}
The constructor for myClass accepts a Context, and then an int for the raw resource. If I call the constructor in an Activity class it works just fine. The service itself also seems to be working because if I comment out the object stuff, I can retrieve the test int no problem.
So what am I missing here?
Thank you very much!

Categories

Resources