Call SharedPreferences on IntentService - android

I'm trying to set null a value on SharedPreferences on my IntentService but I'm getting NPE.
I Inject SharedPreferences from Dagger.
public class DenyService extends IntentService {
#Inject
NumberPreferences numberPreferences;
public DenyService(String name) {
super(name);
}
public DenyService() {
super("DenyService");
}
#Override
public void onCreate() {
super.onCreate();
((CustomApp) getApplication()).getComponent().inject(this);
}
#Override
protected void onHandleIntent(Intent intent) {
numberPreferences.setInt(Constants.CONTESTABLE_BOOKING_ID, null);
ResultReceiver rec = intent.getParcelableExtra("receiverTag");
rec.send(1, null);
}
}
Is something wring with my code, or am I missing something about onHandleIntent method?

Related

from Service, call Activity method (if it's in the foreground)

From an Android Service, I would like to call an Activity method, but only if the Activity is in the foreground.
I would like nothing to happen in case the Activity is not in the foreground.
Which is the simplest way to achieve that?
From a Service always better to broadcast events if the activity is listening to that broadcast will respond. If the activity is not listening then nothing will happen it will ignore.
This is the better solution than the one which you have asked.
I found a very simple solution, adapted from this previous answer:
On the Service:
Intent intent = new Intent(MainActivity.RECEIVER_INTENT);
intent.putExtra(MainActivity.RECEIVER_MESSAGE, myMessage);
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
On the Activity:
public static final String RECEIVER_INTENT = "RECEIVER_INTENT";
public static final String RECEIVER_MESSAGE = "RECEIVER_MESSAGE";
Create a listener on onCreate():
public void onCreate(Bundle savedInstanceState) {
...
mBroadcastReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
String message = intent.getStringExtra(RECEIVER_MESSAGE);
// call any method you want here
}
};
}
register it in onStart():
#Override
protected void onStart() {
super.onStart();
LocalBroadcastManager.getInstance(this).registerReceiver((mBroadcastReceiver),
new IntentFilter(RECEIVER_INTENT)
);
}
unregister it in onStop():
#Override
protected void onStop() {
LocalBroadcastManager.getInstance(this).unregisterReceiver(mBroadcastReceiver);
super.onStop();
}
You can do this using a Interface just to check if the activity is in background or in foreground.
I am sharing some code to have some idea.
public interface CheckAppInForeground {
boolean isAppInForGround();
}
In your Activity
public class MainActivity extends AppCompatActivity implements CheckAppInForeground {
Boolean isAppInForeGround;
#Override
protected void onResume() {
super.onResume();
isAppInForeGround = true;
}
#Override
protected void onStop() {
super.onStop();
isAppInForeGround = false;
}
#Override
public boolean isAppInForGround() {
return isAppInForeGround;
}
}
And your service class
public class MyService extends Service {
Activity activity;
public MyService(Activity activity) {
this.activity = activity;
}
#Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
throw new UnsupportedOperationException("Not yet implemented");
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
MainActivity mainActivity = (MainActivity) activity;
if (activity != null) {
boolean isActivityInForGround = mainActivity.isAppInForGround();
if (isActivityInForGround) {
// Do what you want to do when activity is in foreground
} else {
// Activity is in background
}
} else {
// Activity is destroyed
}
return super.onStartCommand(intent, flags, startId);
}
}
I think i am clear with the code. If you find something missing or unclear please let me know

Calling activity class method from Service class

I have seen many posts in SO regarding this but could not get the exact and most easy way to call an activity method from service class. Is broadcast receiver only the option? No easy way out ? I just need to call the following method in Activity class after the media player is prepared in Service class .
Activity class:
public void updateProgress() {
// set Progress bar values
songProgressBar.setProgress(0);
songProgressBar.setMax(100);
// Updating progress bar
updateProgressBar();
}
Service class:
#Override
public IBinder onBind(Intent intent) {
Log.d(this.getClass().getName(), "BIND");
return musicBind;
}
#Override
public boolean onUnbind(Intent intent) {
return false;
}
#Override
public void onPrepared(MediaPlayer mp) {
try {
mp.start();
} catch (IllegalStateException e) {
e.printStackTrace();
}
// updateProgress();// Need to call the Activity method here
}
Define an interface your Service will use to communicate events:
public interface ServiceCallbacks {
void doSomething();
}
Write your Service class. Your Activity will bind to this service, so follow the sample shown here. In addition, we will add a method to set the ServiceCallbacks.
public class MyService extends Service {
// Binder given to clients
private final IBinder binder = new LocalBinder();
// Registered callbacks
private ServiceCallbacks serviceCallbacks;
// Class used for the client Binder.
public class LocalBinder extends Binder {
MyService getService() {
// Return this instance of MyService so clients can call public methods
return MyService.this;
}
}
#Override
public IBinder onBind(Intent intent) {
return binder;
}
public void setCallbacks(ServiceCallbacks callbacks) {
serviceCallbacks = callbacks;
}
}
Write your Activity class following the same guide, but also make it implement your ServiceCallbacks interface. When you bind/unbind from the Service, you will register/unregister it by calling setCallbacks on the Service.
public class MyActivity extends Activity implements ServiceCallbacks {
private MyService myService;
private boolean bound = false;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(...);
}
#Override
protected void onStart() {
super.onStart();
// bind to Service
Intent intent = new Intent(this, MyService.class);
bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE);
}
#Override
protected void onStop() {
super.onStop();
// Unbind from service
if (bound) {
myService.setCallbacks(null); // unregister
unbindService(serviceConnection);
bound = false;
}
}
/** Callbacks for service binding, passed to bindService() */
private ServiceConnection serviceConnection = new ServiceConnection() {
#Override
public void onServiceConnected(ComponentName className, IBinder service) {
// cast the IBinder and get MyService instance
LocalBinder binder = (LocalBinder) service;
myService = binder.getService();
bound = true;
myService.setCallbacks(MyActivity.this); // register
}
#Override
public void onServiceDisconnected(ComponentName arg0) {
bound = false;
}
};
/* Defined by ServiceCallbacks interface */
#Override
public void doSomething() {
...
}
}
Now when your service wants to communicate back to the activity, just call one of the interface methods from earlier. Inside your service:
if (serviceCallbacks != null) {
serviceCallbacks.doSomething();
}
Use Broadcast receiver with service for updating your view from the service class.
For example:
In my activity class
public class ServiceDemoActivity extends Activity {
Intent intent;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
final TextView notification = (TextView) findViewById(R.id.notification);
if (CheckIfServiceIsRunning()) {
} else {
startService(new Intent(this, MyService.class));
}
}
private BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
updateDate(intent);
}
};
private void updateDate(Intent intent) {
String time = intent.getStringExtra("time");
Toast.makeText(getApplicationContext(), "Yea!!! Service called", Toast.LENGTH_SHORT).show();
TextView date = (TextView) findViewById(R.id.date);
date.setText(time);
}
#Override
public void onResume() {
super.onResume();
registerReceiver(broadcastReceiver, new IntentFilter(
MyService.BROADCAST_ACTION));
}
}
And in my service class I am calling my update ui after a few interval of time which updates my UI.
public class MyService extends Service {
public static final String
BROADCAST_ACTION = "com.mukesh.service";
private final Handler handler = new Handler();
#Override
public void onCreate() {
intent = new Intent(BROADCAST_ACTION);
}
#Override
public void onDestroy() {
stopService(intent);
}
#Override
public void onStart(Intent intent, int startid) {
int i = 0;
while (i <= 2) {
if (i > 1) {
i++;
this.onDestroy();
} else {
counter = i;
i++;
handler.removeCallbacks(sendUpdatesToUI);
handler.postDelayed(sendUpdatesToUI, 1 * 1000); // 1 sec
}
}
}
private Runnable sendUpdatesToUI = new Runnable() {
public void run() {
DisplayLoggingInfo();
handler.postDelayed(this, 7 * 1000); // 7 sec
}
};
private void DisplayLoggingInfo() {
intent.putExtra("time", new Date().toLocaleString());
intent.putExtra("counter", String.valueOf(counter));
sendBroadcast(intent);
stopService(intent);
}
}
For complete code check this link
I created a general class called Delegate (it's not a special name, you can name it John) and passed MainActivity class into it as a static field. Then I can access it from the service since its global now. I am not sure if it is cost-effective but it solved the problem for me simple.
My service:
package com.some.package;
import com.google.firebase.iid.FirebaseInstanceId;
import com.google.firebase.iid.FirebaseInstanceIdService;
public class FirebaseInstanceIDService extends FirebaseInstanceIdService {
#Override
public void onTokenRefresh() {
String token = FirebaseInstanceId.getInstance().getToken();
Delegate.theMainActivity.onDeviceTokenChange(token);
}
}
Delegate class:
package com.some.package;
public class Delegate {
static MainActivity theMainActivity;
}
What I did in MainActivity:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Delegate.theMainActivity = this;
//rest of the code...
}
public void onDeviceTokenChange(String token){
Log.e("updated token:", token);
}
You can't call your sevices method direcly from your activity or vise versa. There are 3 ways to communicate with a service; using broadcasters and receivers, using Messenger or binding to the service. For further information look at http://developer.android.com/guide/components/bound-services.html
You can call from your service
getContentResolver().notifyChange(uri, null);
and in your activity you set up a
getContentResolver().registerContentObserver(uri, false, new ContentObserver(getHandler())
{
public void onChange(boolean selfChange)
{
updateProgress()
}
};
the onChange method will ba called on the UI thread
You can call a method of activity from service by implementing your own listener like this
https://stackoverflow.com/a/18585247/5361964
You might consider running your activity method in runOnUiThread like this:
// method will be called from service
override fun callback(activity: Activity, result: String) {
runOnUiThread{
Toast.makeText(activity, result, Toast.LENGTH_LONG).show()
}
}
I would prefer to use some very easy and cleaner solution provided by
EventBus

How to access 'Activity' from a Service class via Intent?

I am new to Android programming - so I do not have very clear understanding of the 'Context' and the 'Intent'.
I want to know is there a way to access Activity from a Service class?
i.e. Let's say I have 2 classes - one extends from "Activity" and other extends from "Service" and I have created an intent in my Activity class to initiate the service.
Or, how to access the 'Service' class instance from my 'Activity' class - because in such workflow Service class is not directly instantiated by my Activity-code.
public class MainActivity extends Activity {
.
.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
startService(new Intent(this, CommunicationService.class));
.
.
}
public class CommunicationService extends Service implements ..... {
.
.
#Override
public int onStartCommand(final Intent intent, int flags, final int startId) {
super.onStartCommand(intent, flags, startId);
....
}
}
You can use bindService(Intent intent, ServiceConnection conn, int flags) instead of startService to initiate the service. And the conn will be a inner class just like:
private ServiceConnection conn = new ServiceConnection() {
#Override
public void onServiceConnected(ComponentName name, IBinder service) {
mMyService = ((CommunicationService.MyBinder) service).getService();
}
#Override
public void onServiceDisconnected(ComponentName name) {
}
};
mMyService is the instance of your CommunicationService.
In your CommunicationService, just override:
public IBinder onBind(Intent intent) {
return new MyBinder();
}
and the following class in your CommunicationService:
public class MyBinder extends Binder {
public CommunicationService getService() {
return CommunicationService.this;
}
}
So you can use mMyService to access any public methods and fields in your activity.
In addition, you can use callback interface to access activity in your service.
First write a interface like:
public interface OnChangeListener {
public void onChanged(int progress);
}
and in your service, please add a public method:
public void setOnChangeListener(OnChangeListener onChangeListener) {
this.mOnChangeListener = onChangeListener;
}
you can use the onChanged in your service anywhere, and the implement just in your activity:
public void onServiceConnected(ComponentName name, IBinder service) {
mMyService = ((CommunicationService.MyBinder) service).getService();
mMyService.setOnChangeListener(new OnChangeListener() {
#Override
public void onChanged(int progress) {
// anything you want to do, for example update the progressBar
// mProgressBar.setProgress(progress);
}
});
}
ps: bindService will be like this:
this.bindService(intent, conn, Context.BIND_AUTO_CREATE);
and do not forget
protected void onDestroy() {
this.unbindService(conn);
super.onDestroy();
}
Hope it helps.

How do I call a local method in my class by an intent in alarmManager?

For example:
Public class Calls extends Service {
public void onCreate()
{
//call myMethod here by alarmManager
}
myMethod()
{
}
}
I'm not sure if I missing something, but why you just do this?
public class Calls extends Service {
public void onCreate() {
myMethod();
}
myMethod() {
}
}

startService() from the service class itself

I try to start an android service from the service's class.
The reason to do this is to achieve some platform independence.
Doing this I get a NullPointerException at android.content.ContextWrapper.startService(ContextWrapper.java:326). The platform target is 2.1-update1, any suggestions?
See the code below (I left the imports out to save some space)
/* GUI: HelloAndroid.java */
package com.example.helloandroid;
public class HelloAndroid extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// that works!
startService(new Intent("com.example.helloandroid.UnusualService"));
// stop the service works of course, too
stopService(new Intent("com.example.helloandroid.UnusualService"));
// unusual start does not work:
UnusualService myService = new UnusualService();
myService.startService();
}
}
/* Service: UnusualService.java */
package com.example.helloandroid;
public class UnusualService extends Service {
#Override
public void onCreate() {
Toast.makeText(this, R.string.service_started, Toast.LENGTH_SHORT).show();
}
#Override
public void onDestroy() {
Toast.makeText(this, R.string.service_stopped, Toast.LENGTH_SHORT).show();
}
#Override
public IBinder onBind(Intent intent) {
return null; // make something here when the rest works
}
public void startService() {
// folowing line will cause the NullPointerException
startService(new Intent("com.example.helloandroid.UnusualService"));
}
public void stopService() {
stopSelf();
}
}
Of course - your newly created service does not have a reference to a context, so the context is null and therefore the system throws a NullPointerException.
Remember: Do not create a service on your own by using new - the system does this for you!
Your UnusualService extends Service. Service extends ContextWrapper which contains Context.
So when you call UnusualService.startService(new Intent("...")) it actually calls ContextWrapper.startService() which calls context.startService(). However at this point context is null and NullPointerException occurs.
public abstract class Service extends ContextWrapper implements ComponentCallbacks {
private static final String TAG = "Service";
public Service() {
super(null);
}
//...
}
public class ContextWrapper extends Context {
Context mBase;
public ContextWrapper(Context base) {
mBase = base;
}
#Override
public ComponentName startService(Intent service) {
return mBase.startService(service);
}
//...
}
public void startService() {
// folowing line will cause the NullPointerException
startService(new Intent("com.example.helloandroid.UnusualService"));
}
do this instead...
startService(new Intent(UnusualService.this, UnusualService.class));
Edit: Corrected as per CyprUS

Categories

Resources