Start Activity from BroadcastReceiver only once using locks --Android - android

Scenario :
When two alarms are set at the same time, then only of them should be shown.
My Problem:
I have a broadcastreceiver which forwards an intent to AlarmGoOffActivity when its time. However, I need to check if AlarmGoOffActivity is already running before forwarding an intent. From one of the answers I saw in SO. I tried this approach.Earlier, both alarms fired. Now, neither alarm fires now.
Code
MyBroadCastReceiver.java
if (AlarmGoOffActivity.running) {
BLog("AlarmActivity running");
} else {
BLog("AlarmActivity not running ");
//set this variable true so that new broadcasts are not entertained
AlarmGoOffActivity.running = true;
Intent intent1 = new Intent(context, AlarmGoOffActivity.class);
intent1.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent1.putExtra(DBHelper.COLUMN_ID, id);
String ext = extras.getString(DBHelper.TASK_TITLE);
if (ext != null) {
intent1.putExtra(DBHelper.TASK_TITLE, ext);
}
BLog("Starting alarm fire");
context.startActivity(intent1);
}
AlarmGoOffActivity.java
public class AlarmGoOffActivity extends ActionBarActivity {
public static boolean running = false;
.....
#Override
public void onDestroy() {
super.onDestroy();
//changing the lock to false here. So a new one can start from
//broadcastreceiver
running = false;
}
}
I was expecting the first one to fire. Now, neither one fires. Why is this not working? Is it because of the static variable (some concept I missed?) or is it because of the time gap of a 10 or less milliseconds between the broadcasts. Thanks for your help.

The receiver should handle the intent and then exit quickly. It should not try to determine if the Activity is visible or active or whatever.
Instead, you should have the Activity handle re-notifications. In particular, you will probably find onNewIntent useful for processing new intents sent from the receiver. In your activity you can set flags to determine how to handle re-notifications versus the state the Activity is currently in.

Related

WakefulBroadcastReceiver intent not starting only in some cases (strange)

I have a very strange bug happening in my app. I am building an Alarm APP and I am using SQLite to store alarm data and broadcast receivers to manage the alarm manager calls.
The code of onReceive strangely does not behave in the same way in some cases. I try to start an Activity when the receiver receives a broadcast, nearly 90% of cases everything goes well and I manage to start the Activity, but in some cases strangely enough the receiver executes the instruction "startActivity(i)" but nothing happens.
It is really hard to reproduce the BUG and during my debugging I have learned what I have mentioned, but more than this is really difficult for me to understand how a call to startActivity() in most cases works and in some cases does not work. I have searched through the Stack community but no one seamed to have this kind of problem, everybody just had problems in starting the activity because they had not set the flag or because they had not registered the receiver in the manifest. Below I am posting the code.
public class AlarmReceiver extends WakefulBroadcastReceiver {
// The app's AlarmManager, which provides access to the system alarm services.
private AlarmManager alarmMgr;
// The pending intent that is triggered when the alarm fires.
private PendingIntent alarmIntent;
#Override
public void onReceive(Context context, Intent intent) {
Utils.logToFile("Received Alarm ,I am in onReceive(), ALARM ID: "+intent.getExtras().getInt(Constants.ALARM_ID));
Intent intent = new Intent(context, StopAlarm.class);
Bundle b = new Bundle();
b.putInt(Constants.ALARM_ID, intent.getExtras().getInt(Constants.ALARM_ID));
if(intent.getExtras().containsKey(Constants.SNOOZE_ALARM)){
b.putString(Constants.SNOOZE_ALARM, intent.getExtras().getString(Constants.SNOOZE_ALARM));
}
i.putExtras(b);
//this flag is needed to start an Activity from a BroadcastReceiver
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intent);
//this method reads from the DB and sets the next alarm
//I tried commenting this method so that no DB action is
//performed and still the bug happened
setAlarm(context.getApplicationContext());
//this method just logs data into a file that I have created to keep track of events
//since not always the device is connected with LogCat
Utils.logToFile("Received Alarm, Intent(context, StopAlarm.class);");
}
Do I need to set any other flag and how is it possible that startActivity(intent) behaves incorrectly in some cases?
EDIT
<activity
android:label="#string/app_name"
android:name="package.activity.StopAlarm"
android:windowSoftInputMode="stateAlwaysHidden"
android:screenOrientation="sensorPortrait">
</activity>
<receiver android:name="package.receivers.AlarmReceiver" />
I have finally solved the issue by creating an IntentService and by starting the activity from the IntentService and setting two flags to the Intent. After doing this I placed the code which reads from DB in the activity that is started from the IntentService. I have tested nearly 60 times the behaviour and in all the tests the app behaved correctly. I am posting the code below.
public class MyAlarmReceiver extends WakefulBroadcastReceiver {
// The app's AlarmManager, which provides access to the system alarm services.
private static AlarmManager alarmMgr;
// The pending intent that is triggered when the alarm fires.
private static PendingIntent alarmIntent;
#Override
public void onReceive(Context context, Intent intent) {
Intent i = new Intent(context, AlarmIntentService.class);
Bundle b = new Bundle();
b.putInt(Constants.ALARM_ID, intent.getExtras().getInt(Constants.ALARM_ID));
if(intent.getExtras().containsKey(Constants.SNOOZE_ALARM)){
b.putString(Constants.SNOOZE_ALARM, intent.getExtras().getString(Constants.SNOOZE_ALARM));
}
i.putExtras(b);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startWakefulService(context, i);
}
This is the IntentService I needed to implement
public class AlarmIntentService extends IntentService {
public AlarmIntentService() {
super("AlarmIntentService");
}
#Override
protected void onHandleIntent(Intent intent) {
Intent i = new Intent(this, StopAlarm.class);
Bundle b = new Bundle();
b.putInt(Constants.ALARM_ID, intent.getExtras().getInt(Constants.ALARM_ID));
if(intent.getExtras().containsKey(Constants.SNOOZE_ALARM)){
b.putString(Constants.SNOOZE_ALARM, intent.getExtras().getString(Constants.SNOOZE_ALARM));
}
i.putExtras(b);
//THESE ARE THE FLAGS NEEDED TO START THE ACTIVITY AND TO PREVENT THE BUG
//(CLEAR_TASK is crucial for the bug and new task is needed to start activity from outside of an activity)
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(i);
MyAlarmReceiver.completeWakefulIntent(intent);
}
}
This is the activity started by the IntentService. Here I set the next alarm.
public class StopAlarm extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.stop_alarm);
//this method reads from the DB and sets the next alarm
MyAlarmReceiver.setAlarm(getApplicationContext());
...
I had a similar issue. From my experience the problem is,that startActivity(i) is asynchronous. So in this case the program will simultaneously call activities onCreate(),onStart(), etc. but also call QlokAlarmReceiver.completeWakefulIntent(intent) (without waiting for the activity to be closed), which will release the wakeLock. Because of that the device can go to sleep during executing the activities onCreate() or onStart().
Rubin, I know, that my answer is a contradiction of your solution, but my logs clearly indicated such order of events:
- startActivity called
- onCreate of the activity called
- completeWakefulIntent(intent); called in between logs from onStart of the activity
My workaround this is to start a wakelock with a timeout of eg 20 seconds just before calling startActivity and then start another wakeLock in the activities onCreate, which will be released in the onDestroy method.
I'm not sure if my solution goes along with best practises, but I haven't found a better solution so far.

How can I tell if my activity was started by a broadcast receiver?

I have an alarm clock application I am making. I have one activity where the user sets the time for the alarm. This registers a broadcast receiver class I have made to receive a broadcast at the time of the alarm, using AlarmManager. I then start a new activity in the receivers onReceive(). When this second activity starts, the alarm clock sound is played in onStart(). How can I tell if my activity has been started by a receiver or if the user is just multitasking with the application? I don't want my sound to play when the user silences the alarm, presses the home button, and then renters the app (while still on the sound playing activity).
Just send an extra via the intent you use in your onReceive() method:
Intent intent = new Intent(this, NextActivity.class);
intent.putExtras("playSound", true);
in your "sound playing" activity, you have to play the sound in onCreate():
boolean playSound = getIntent().getBooleanExtra("playSound", false);
This will return false if the intent-extra "playSound" does not exist or is set to false, true if it is set to true.
onCreate() is only called once (when the activity starts), while onStart() gets called everytime a user reenters your activity (i.e. through recent apps). You can see this in the lifecycle:
(diagram source)
Where Paused is called when something draws over you activity (e.g. low battery dialog), Stopped is called if you "exit" your app (e.g. through the home-button).
Start an activity or a service, etc., based on a received broadcast then you need a standalone broadcast receiver and you put that in your android manifest file. If you want your activity itself to respond to broadcasts then you create an instance of a broadcast receiver in your activity and register it there.
public class BRActivity extends Activity {
private BroadcastReceiver broadcastReceiver = new BroadcastReceiver(){
#Override
public void onReceive(Context context, Intent intent) {
..................
..................
}
};
public void onResume() {
super.onResume();
IntentFilter filter = new IntentFilter();
filter.addAction(BROADCAST_ACTION);
this.registerReceiver(this.broadcastReceiver , filter);
}
public void onPause() {
super.onPause();
this.unregisterReceiver(this.broadcastReceiver );
}
}
So, this way the receiver is instantiated when the class is created (could also do in onCreate). Then in the onResume/onPause I handle registering and unregistering the receiver. Then in the reciever's onReceive method I do whatever is necessary to make the activity react the way I want to when it receives the broadcast.
You can do as below:
For each alarm user sets, you put an boolean flag in sharedpreference to true. E.g. you have three alarms then in sharedpreference you will have 3 flags.
Now suppose a alarm broadcast is received for alarm1 and activity2 is started.
Now in activity2 first thing you check is whether the flag for alarm1 which you set in sharedpreference is true or false, if true play sound.
When user silences the alarm or press home button then you can mark this flag to false, so next time if user starts activity from background, flag in sharedpreference will be false and sound will not be played.
Same thing you can achieve using sqlite db, by setting flags in sqlite db table instead of sharedpreference.
For the intent used to launch the sound playing activity use the FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS flag. So if the user moves out of the activity, it cannot be resumed.
Intent intent = new Intent(context, SoundActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
or in manifest
<activity
android:name="SoundActivity"
android:excludeFromRecents="true" >
</activity>
There are couple of solutions:
(1) one approach is to use a Singleton Class which can be shared across activity.
In this approach set a boolean flag of Singleton class in BroadcastReceiver and then check that flag in the activity (which is fired from your BroadcastReceiver) where you play sound. Please reset the flag if it is set. This solution assumes that the Broadcast receiver is part of your Android App package.
(2)
Alternatively, you can also use Intet.putExtra ("Key", Value) method when you start an activity from BroadcastReceiver. You can check this key in the Activity you started from BroadcastReceiver to know who started this activity.
So this will take care of detecting where you come from.
If you are simply trying to set single (one-shot ) alarm then creating another activity for playing the sound is OK. If you set repeat alarm ( alarm plays at a multiple interval), I am not sure how your application will behave.
I prefer to play the sound in the Broadcast receiver itself (registered as remote receiver in manifest) for a specified duration for a given alarm ( like 30 sec of sound or you can ask user to configure it).
So this way you can use the same BroadcastReceiver for playing sound for single-shot & multi-repeat alarm.
I will use the same PendingIntent for setting both Single-shot and multi-repeat alarm.
You can simply set flag or any value in Intent that will determine what's your purpose in that class ..
For Ex: For playing sound set a Boolean value to TRUE in Intent and send same over that class using bundle ..
Else
Set that Boolean value to FALSE if starting alarm class from some other class.
This is the code to find if app is started via broadcast receiver.
public class AlarmReceiver extends BroadcastReceiver
{
#Override
public void onReceive(Context context, Intent intent)
{
String AlarmTriggerString = (String)intent.getSerializableExtra("AlarmTrigger");
Intent i = new Intent();
i.setClassName("com.prasath.viki.bot","com.prasath.viki.bot.MainActivity");
intent.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT|Intent.FLAG_ACTIVITY_NEW_TASK);
i.putExtra("FromBroacastReceiver",true);
i.putExtra("AlarmTrigger",AlarmTriggerString);
context.startActivity(i);
}
}
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
boolean FromReceiver = (boolean)getIntent().getSerializableExtra("FromBroacastReceiver");
String AlarmTriggerString = (String) getIntent().getSerializableExtra("AlarmTrigger");
if(AlarmTriggerString != null && FromReceiver != null && FromReceiver == true)
{
// do something
}
}

Dynamically registering and unregistering a broadcast receiver in an activity while allowing it to run outside the activity as well

I'm trying to register a broadcast receiver so that when the screen turns on, airplane mode turns on as well. It WORKS as long as I stay in the activity where I register it, but as soon as I leave the activity, it stops working. Android Manifest is static so I can't use that and besides, the Android Manifest method does not allow you to use SCREEN_ON because Android doesn't want you to run a bunch of things when the screen wakes up so it has to be done by using registerReceiver AFAIK.
My activity:-
public class WakeActivity extends Activity {
IntentFilter screenon = new IntentFilter("android.intent.action.SCREEN_ON");
//Skipped a bunch of code here to keep it relevant. Remember, the broadcast receiver
//does in fact work while I'm in the activity, so the problem isn't with
//the missing code here. Still, let me know if I'm missing something.
//The following method is called within onCreate()
protected void airplane(int i) {
Screen_On screenon_airplane = new Screen_On();
if (i == 0) {
screenon_airplane.airplanei = 0;
registerReceiver(screenon_airplane, screenon);
} else if (i == 1) {
screenon_airplane.airplanei = 1;
registerReceiver(screenon_airplane, screenon);
} else if (i == -1) {
unregisterReceiver(screenon_airplane);
}
}
}
My Broadcast Receiver:-
public class Screen_On extends BroadcastReceiver {
public int airplanei;
#Override
public void onReceive(final Context context, Intent intent) {
boolean isEnabled = Settings.System.getInt(
context.getContentResolver(), Settings.System.AIRPLANE_MODE_ON,
0) == 1;
if (airplanei == 0) {
if (isEnabled != false) {
Settings.System.putInt(context.getContentResolver(),
Settings.System.AIRPLANE_MODE_ON, 0);
Intent turnplaneoff = new Intent(
Intent.ACTION_AIRPLANE_MODE_CHANGED);
turnplaneoff.putExtra("state", 0);
context.sendBroadcast(turnplaneoff);
}
} else if (airplanei == 1) {
if (isEnabled == false) {
Settings.System.putInt(context.getContentResolver(),
Settings.System.AIRPLANE_MODE_ON, 1);
Intent turnplaneon = new Intent(
Intent.ACTION_AIRPLANE_MODE_CHANGED);
turnplaneon.putExtra("state", 1);
context.sendBroadcast(turnplaneon);
}
}
}
}
LogCat Error:-
05-17 23:44:24.886: E/ActivityThread(2435): Activity com.dragonheart.autodroid.ActionActivities.WakeActivity has leaked IntentReceiver com.dragonheart.autodroid.BroadCastRecievers.Screen_On#414271b0 that was originally registered here. Are you missing a call to unregisterReceiver()?
Could the error have something to do with not telling the Broadcast Receiver what to in onPause() or onDestroy()?...Although I thought once it's registered, it would work until unregistered, regardless of the activity...
I'm not sure that your broadcast receiver will work once the activity is stopped, since your receiver has been registered programmatically and not statically through manifest (since android do not let you do so).
I've looked at your code trying to understand what the code does, but that's not simple from just a couple of lines...
But anyway, why dont you create a service in which you register the listener to the screen state? In this way the service will not stop execution, even after the activity has stopped.
And every time the service notice the screen turn on/off you can send a message to your main activity (check documentation).
See this previous question, with example on how to use LocalBroadcastReceiver: LINK

How do I cancel all pending intents that are qued for intent Service

I have an intentservice that gets qued by the user and by my app automatically. I need to be able to kill all pending intents that are qued when the user logs out of my application, but I cannot seem to get that to work. I have tried stopService() and stopself(), but the intents continue to fire off the intentservice after the user has logged out. I would try to get the id of the intent but that is difficult as everytime the intentservice starts, the variable holding the intent id's is empty. Here is my intentservice code:
public class MainUploadIntentService extends IntentService {
private final String TAG = "MAINUPLOADINTSER";
private GMLHandsetApplication app = null;
private SimpleDateFormat sdf = null;
public boolean recStops = true;
public MainUploadIntentService() {
super("Main Upload Intent Service");
GMLHandsetApplication.writeToLogs(TAG,
"GMLMainUploadIntentService Constructor");
}
#Override
protected void onHandleIntent(Intent intent) {
GMLHandsetApplication.writeToLogs(TAG, "onHandleIntent Started");
if (app == null) {
app = (GMLHandsetApplication) getApplication();
}
uploadData(app);
GMLHandsetApplication.writeToLogs(TAG, "onHandleIntent Finished");
}
#Override
public void onDestroy() {
GMLHandsetApplication.writeToLogs(TAG, "onDestroy Started");
app = null;
stopSelf();
GMLHandsetApplication.writeToLogs(TAG, "onDestroy completed");
}
public void uploadData(GMLHandsetApplication appl) {
//All of my code that needs to be ran
}
Unfortunately, I don't think it's possible to accomplish that with the standard IntentService methods since it doesn't offer a way to interrupt it while it's already going.
There are a few options I can think of that you can try to see if they fit your need.
Copy the IntentService code to make your own modifications to it that would allow you to remove pending messages. Looks like someone had some success with that here: Android: intentservice, how abort or skip a task in the handleintent queue
Instead of copying all the IntentService code, you might also be able to Bind to it like a normal Service (since IntentService extends Service) so you can write your own function to remove pending messages. This one is also mentioned in that link.
Rewrite the IntentService as a regular Service instead. With this option, you'd have more control over adding and removing messages.
I had what sounds like a similar situation where I was using an IntentService, and I eventually just converted it to a Service instead. That let me run the tasks concurrently and also cancel them when I needed to clear them.
Here
When should I free the native (Android NDK) handles? is the HangAroundIntentService class that has the method cancelQueue().
The class also has the method
public static Intent markedAsCancelIntent(Intent intent)
that converts an intent into a cancel intent, and
public static boolean isCancelIntent(Intent intent).
The class is based on the open-sourced Google's code.
Just a thought but inside of your onhandleintent can you have an argument that checks to see if app is running if not then don't run the code? example. In the start of your app you could have a static var
boolean appRunning;
Next in your onhandle of the intent, when you set the appRunning to false, after an onPause or onDestroy of activity, you could wrap the onhandleintent code in a boolean:
protected void onHandleIntent(final Intent intent) {
if(MainActivity.appRunning){
...
}
}
Just a thought

Lock android app after a certain amount of idle time

My android application requires a password to be entered in the first activity. I want to be able to automatically send the application back to the password entry screen after the application has been idle for a fixed amount of time.
The application has multiple activities, but I would like the timeout to be global for all activities. So, it wouldn't be sufficient to create a timer thread in the onPause() method of an Activity.
I'm not sure what the best definition for the application being idle is, but no activities being active would be sufficient.
I know another answer is accepted already, but I came across this working on a similar problem and think I'm going to try an alternate much simpler approach that I figured I may as well document if anyone else wants to try to go down the same path.enter code here
The general idea is just to track the system clock time in a SharedPreference whenever any Activity pauses - sounds simple enough, but alas, there's a security hole if that's all you use, since that clock resets on reboot. To work around that:
Have an Application subclass or shared static singleton class with a global unlocked-since-boot state (initially false). This value should live as long as your Application's process.
Save the system time (realtime since boot) in every relevant Activity's onPause into a SharedPreference if the current app state is unlocked.
If the appwide unlocked-since-boot state is false (clean app start - either the app or the phone restarted), show the lock screen. Otherwise, check the SharedPreference's value at the lockable activity's onResume; if it's nonexistent or greater than the SharedPreference value + the timeout interval, also show the lock screen.
When the app is unlocked, set the appwide unlocked-since-boot state to true.
Besides the timeout, this approach will also automatically lock your app if your app is killed and restarts or if your phone restarts, but I don't think that's an especially bad problem for most apps. It's a little over-safe and may lock unecessarily on users who task switch a lot, but I think it's a worthwhile tradeoff for reduced code and complexity by a total removal of any background process / wakelock concerns (no services, alarms, or receivers necessary).
To work around process-killing locking the app regardless of time, instead of sharing an appwide singleton for unlocked-since-boot, you could use a SharedPreference and register a listener for the system boot broadcast intent to set that Preference to false. That re-adds some of the complexity of the initial solution with the benefit being a little more convenience in the case that the app's process is killed while backgrounded within the timeout interval, although for most apps it's probably overkill.
I dealt with this by using the AlarmManager to schedule and cancel timeout action.
Then in the onPause() event of all of my activites, I schedule the alarm. In the onResume() event of all of my activities, I check to see if the alarm goes off. If the alarm went off, I shutdown my app. If the alarm hasn't gone off yet I cancel it.
I created Timeout.java to manage my alarms. When the alarm goes off a intent is fired:
public class Timeout {
private static final int REQUEST_ID = 0;
private static final long DEFAULT_TIMEOUT = 5 * 60 * 1000; // 5 minutes
private static PendingIntent buildIntent(Context ctx) {
Intent intent = new Intent(Intents.TIMEOUT);
PendingIntent sender = PendingIntent.getBroadcast(ctx, REQUEST_ID, intent, PendingIntent.FLAG_CANCEL_CURRENT);
return sender;
}
public static void start(Context ctx) {
ctx.startService(new Intent(ctx, TimeoutService.class));
long triggerTime = System.currentTimeMillis() + DEFAULT_TIMEOUT;
AlarmManager am = (AlarmManager) ctx.getSystemService(Context.ALARM_SERVICE);
am.set(AlarmManager.RTC, triggerTime, buildIntent(ctx));
}
public static void cancel(Context ctx) {
AlarmManager am = (AlarmManager) ctx.getSystemService(Context.ALARM_SERVICE);
am.cancel(buildIntent(ctx));
ctx.startService(new Intent(ctx, TimeoutService.class));
}
}
Then, I created a service to capture the intent generated by the alarm. It sets some global state in my instance of the application class to indicate that the app should lock:
public class TimeoutService extends Service {
private BroadcastReceiver mIntentReceiver;
#Override
public void onCreate() {
super.onCreate();
mIntentReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if ( action.equals(Intents.TIMEOUT) ) {
timeout(context);
}
}
};
IntentFilter filter = new IntentFilter();
filter.addAction(Intents.TIMEOUT);
registerReceiver(mIntentReceiver, filter);
}
private void timeout(Context context) {
App.setShutdown();
NotificationManager nm = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
nm.cancelAll();
}
#Override
public void onDestroy() {
super.onDestroy();
unregisterReceiver(mIntentReceiver);
}
public class TimeoutBinder extends Binder {
public TimeoutService getService() {
return TimeoutService.this;
}
}
private final IBinder mBinder = new TimeoutBinder();
#Override
public IBinder onBind(Intent intent) {
return mBinder;
}
}
Finally, I created a subclass of Activity that all of my app's activities subclass from to manage locking and unlocking:
public class LockingActivity extends Activity {
#Override
protected void onPause() {
super.onPause();
Timeout.start(this);
}
#Override
protected void onResume() {
super.onResume();
Timeout.cancel(this);
checkShutdown();
}
private void checkShutdown() {
if ( App.isShutdown() ) {
finish();
}
}
}
Using onPause and onResume to start and stop the timeout gives me the following semantics. As long as one of my application's activities is active, the timeout clock is not running. Since I used an Alarm type of AlarmManager.RTC, whenever the phone goes to sleep the timeout clock runs. If the timeout happens while the phone is asleep, then my service will pick up the timeout as soon as the phone wakes up. Additionally, the clock runs when any other activity is open.
For a more detailed version of these, you can see how I actually implemented them in my application https://github.com/bpellin/keepassdroid
Check out how OpenIntents Safe implements this functionality.
This has been a really helpful post for me. To back the concept given by #Yoni Samlan . I have implemented it this way
public void pause() {
// Record timeout time in case timeout service is killed
long time = System.currentTimeMillis();
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
SharedPreferences.Editor edit = preferences.edit();
edit.putLong("Timeout_key", time);// start recording the current time as soon as app is asleep
edit.apply();
}
public void resume() {
// Check whether the timeout has expired
long cur_time = System.currentTimeMillis();
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
long timeout_start = preferences.getLong("Timeout_key", -1);
// The timeout never started
if (timeout_start == -1) {
return;
}
long timeout;
try {
//timeout = Long.parseLong(sTimeout);
timeout=idle_delay;
} catch (NumberFormatException e) {
timeout = 60000;
}
// We are set to never timeout
if (timeout == -1) {
return;
}
if (idle){
long diff = cur_time - timeout_start;
if (diff >= timeout) {
//Toast.makeText(act, "We have timed out", Toast.LENGTH_LONG).show();
showLockDialog();
}
}
}
Call pause method from onPause and resume method from onResume.

Categories

Resources