How to refresh token after particular time? - java

I am working in an application in which I need to refresh my token after every 60 minutes. I have created a service which runs in the background. However, the problem I am facing is, when the phone goes to sleep mode, my service gets stopped and hence I am unable to refresh my token. I am getting this problem mostly in OREO & PIE.
public class InActivityTimer extends Service {
#Override
public void onCreate() {
super.onCreate();
mService = APIUtils_AI.getSOService();
mService2 = APIUtils_AI.getSOServiceAI();
utils = new Utils();
receiver = new BroadcastTokenCheck();
filter = new IntentFilter(COUNTDOWN_BR);
registerReceiver(receiver, filter);
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
cdt = new CountDownTimer(15000, 1000) {
#Override
public void onTick(long millisUntilFinished) {
Log.i(TAG, "Countdown seconds remaining: " + millisUntilFinished / 1000);
if(millisUntilFinished<8000&&millisUntilFinished>5000){
if(!isSecond){
Log.i("", "Running: ");
refreshToken();//Refresh Token API
cdt.cancel();
cdt.start();
}
}
}
#Override
public void onFinish() {
Intent intent = new Intent(COUNTDOWN_BR);
intent.putExtra("VALUE","startService");
sendBroadcast(intent);
//stopSelf();
Log.i("", "Timer finished");
}
}.start();
return START_STICKY;
}
#Override
public void onDestroy() {
unregisterReceiver(receiver);
Log.e("Service Status: ","Stopped");
cdt.cancel();
super.onDestroy();
}
#Override
public IBinder onBind(Intent arg0) {
return null;
}
}

My suggestion is to refresh the token when necessary. From my understanding, the token is required to authenticate an API call in a server application. When the API returns unauthorized or 401 error status, you might consider refreshing the token in that case.
Android 8.0 put some limitations to background services which are described briefly in their developer's documentation. If you really need to refresh your token after every 60 minutes, then you might consider using JobScheduler which is suggested in their documentation.
However, I want to recommend to refresh your token in the onResume function of your launcher activity if 60 min has elapsed after the last refresh. The situation may vary based on your server-side implementation though.
Hope that helps!

Here is my 2 cents.
I assume you are calling refreshToken() to fetch a new token from the server, so that when you make the next REST call, you can use this valid token.
Maybe instead of continuously running a service in background, refreshing tokens and consuming the resources, even though user might not be using your app actively, you can do the following:
Keep a local flag in SharedPreference, where you keep record of how long it has been since you made the last call to refresh token. Or you can save the timestamp till the current token is valid.
Before making the REST call, you can check if your current token is valid or not by checking your shared preference.
If its not valid, fetch a new token and then when you receive the response, use that new token to make the initial call. Also persist the token that you received and update the SharedPreference flag.
Note: in case you are using Retrofit for REST calls, you can use something like Interceptor where you can do the above check. Something like this answer: Answer on "Refreshing OAuth token using Retrofit without modifying all calls"

Related

Verification email activity not refreshing

I have an activity where I want the user to wait until email account is verified, but it is not taking the user to mainActivity once account is verified, how should I address this?
See my code below;
user.sendEmailVerification();
final Handler handler = new Handler();
final int delay = 10000; //milliseconds
handler.postDelayed(new Runnable() {
public void run() {
if (user.isEmailVerified()) {
startActivity(new Intent(VerificationEmailActivity.this, MainActivity.class));
Toast.makeText(VerificationEmailActivity.this, R.string.spend_wisely, Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(VerificationEmailActivity.this, "Check your email!", Toast.LENGTH_SHORT).show();
}
handler.postDelayed(this, delay);
}
}, delay);
}
Since the actual verification of the user happens outside of your Android app (in your browser), the app is not aware that it happens. This means that the app only detects the user's updated state once it auto-refreshes the token, which can take up to an hour.
To detect it earlier, you can reload the profile by calling reload(), or forcing the refresh of the ID token by calling getIdToken(true).
This has been covered quite a few times already, so also check out:
Firebase email verification behavior
On every call of isEmailVerified() returning the false condition, Even after email verified
Firebase: Observe email verification status in real time
Flutter: How to listen to the FirebaseUser is Email verified boolean?

Firebase Message - onNewToken at async

I am trying to get the device token once the person has logged into the app and send back the device token to our server. The login process is done in async.
According to this post , you can get the token in activities but is it possible to get in async?
I have tried to put the code in async but does not work. (I changed the MainActivity.this to (Activity)mycontext, where I have defined mycontext as a Context)
FirebaseInstanceId.getInstance().getInstanceId().addOnSuccessListener( (Activitiy) mycontext, new OnSuccessListener<InstanceIdResult>() {
#Override
public void onSuccess(InstanceIdResult instanceIdResult) {
String newToken = instanceIdResult.getToken();
Log.e("newToken",newToken);
}
});
Thank you very much
thanks to Shashanth , the solution is just to get the token in one activity and pass that token value to async

How can I keep my service alive after finishing its work, waiting for data from another class?

i have a class(location2.java) that finds location for me,I use this code in my class :
What is the simplest and most robust way to get the user's current location on Android?
and I have a service that override that abstract "locationResult";Now i want my service after running its codes,service doesn't finish and stay alive for receiving location from location2.java.
appreciating any help for this.
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Location2.LocationResult locate = new Location2.LocationResult() {
#Override
public void gotLocation(Location location1, Boolean Gps, Boolean Net) {
if (location1 != null) {
Log.e("Loc", String.valueOf(location1.getLatitude()));
}
try {
//this is a method that i want to be run after receiving location from location2.java
json_maker(location1, speed_computation(location1), Gps, Net);
} catch (JSONException e) {
e.printStackTrace();
}
}
};
Location2 location = new Location2();
location.getLocation(context, locate);
return Service.START_FLAG_REDELIVERY;
}
The most successful way is to use return START_STICKY.
"and if service wants to restart, multiple constants for example START_STICKY can be used.doesn't it?" - Yes, we can use.
START_STICKY
Constant to return from onStartCommand(Intent, int, int) if this service's process is killed while it is started (after returning from onStartCommand(Intent, int, int)), then leave it in the started state but don't retain this delivered intent. Developer guide: Android

System.exit(0) in Android Wear Watchface?

I've read that using System.exit(0) is frowned upon when it comes to Java and Android, but so far I can find no alternative for what I'm trying to accomplish. To be clear, this is for a Watchface, which is simply a service extending CanvasWatchFaceService. I cannot call finish() in this case. I've also tried stopService and startService with no success.
The issue I'm trying to solve: It's well known that changing timezones on your device will not be reflected on a watchface unless it is restarted. In my testing, I found that System.currentTimeMillis() quite literally does not respond to timezone changes in Android Wear. The watchface must be restarted in order for it to show the correct time after a timezone change.
So I built a system with the following code:
private final BroadcastReceiver timeChangeReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
final String action = intent.getAction();
if (!restarting) {
if (action.equals(Intent.ACTION_TIMEZONE_CHANGED)) {
if (upSeconds >= 15) {
System.exit(0);
} else {
restarting = true;
int delay = ((15 - upSeconds) * 1000);
new CountDownTimer(delay, delay) {
#Override
public void onTick(long millisUntilFinished) { }
#Override
public void onFinish() {
System.exit(0);
}
}.start();
}
}
}
}
};
The delay is in case a user triggers a time zone change more frequently than 15 seconds at a time. Android Wear seems to detect system exits that are too frequent and replace the watchface with the "Simple" watchface.
It seems to work great, Android Wear automatically boots the watchface back up on exit. But I would eventually like to put this app on the Google Play Store, so I thought I should make sure I'm not playing with fire here.
I can't believe I went through all that work when the proper solution was so simple. Thanks ianhanniballake for the link!
After looking at the Analog Watchface Sample, I found that all I needed to do was use mCalendar.setTimeZone(TimeZone.getDefault());. In many places I was directly comparing the time in milliseconds fetched with long now = System.currentTimeMillis();, so I simply did a now = mCalendar.getTimeInMillis() to take care of that.
Now the watchface changes time properly when the timezone is changed. I guess the other watchfaces I downloaded did not properly handle this!

getExtra crashing the app in Service

I search a lot and I tried several ways but I couldn't find anything that avoid my error.
I'm working on app for my learning, where is an String in my MainActivity and then I call it in my Service. I tried something like this:
This next one goes in my myService.class
//In my myService.class that extends Service
public class myService extends Service{
AlarmManager manager;
PendingIntent pintent;
String te;
#Override
public void onCreate()
{
manager = (AlarmManager)(this.getSystemService(Context.ALARM_SERVICE));
pintent = PendingIntent.getBroadcast( this, 0, new Intent("blahblah"), 0 );}
#Override
public int onStartCommand(Intent intent, int flags, int startid)
{
super.onStartCommand(intent, flags, startid);
te = intent.getStringExtra("tst"); //if I change this line to te = "something", everything goes fine
BroadcastReceiver receiver = new BroadcastReceiver() {
#Override
public void onReceive( Context context, Intent intent )
{
Toast.makeText(getApplicationContext(),te, Toast.LENGTH_SHORT).show();
}
};
this.registerReceiver(receiver, new IntentFilter("blahblah") );
// set alarm to fire 30 min and waits 2 min
manager.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime() + 1000*30*60, 1000*2*60, pintent);
return START_STICKY;}
public IBinder onBind(Intent p1)
{
// TODO: Implement this method
return null;
}
}
Here the code runs perfectly, but when I exit my App, it crashes. After 1 minute, my device shows again that my App crashes, confirming my app "successfully" ran into background. What is wrong with it?
I also learned I could use IntentService instead of Service, wich one is better for long tasks and what is the difference between them ?
EDIT***
I received the following error: java.lang.NullPointerExeption.
So I change this:
te = intent.getStringExtra("tst");
To this:
try
{
te = intent.getStringExtra("tst");
}
catch(NullPointerException e)
{}
When I changed it my app works with any error, but The problem is: I need to retrieve my String from my MainActivity, when I close my app my service runs without errors but my "te" String takes null valor, what can I do to "save" my String in my service, to be able to use it and keeping showing the "working" message after I close my App ? Should I use SharedPreferences ?
Hope I was clear.
IntentService is different from Service.
IntentService Self kills the service as it finishes the task. Whereas Service runs for ever unless you kill it.
For my coding experience, I would use IntentService only for small tasks that run for a couple of seconds and use Service for long running one and call StopSelf() as needed.
Kindly post the log to answer your problem

Categories

Resources