Android Alarm Service Not Responding - java

I took some code from some questions here in SO as well as some other website and I came up with a reasonable solution.
What I am trying to do: I need to shutdown the app after 2 minutes of inactivity. So The idea is to start up the alarm service when our app goes in into 'onPause' and cancel the service when our app goes into 'onResume'.
What I currently Have: Here is the relevant code that is currently running. My issue is that the TimeoutService java file is never being 'onCreated'. Does simply calling AlarmManager.set NOT start up the pending intent?
The Timeout.java File
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.widget.Toast;
public class Timeout
{
private static final int REQUEST_ID = 0;
private static final long DEFAULT_TIMEOUT = 2 * 60 * 1000; // 2 minutes
public static final String INTENT_TIMEOUT = "timeoutintent";
public static void start(Context ctx)
{
//long triggerTime = System.currentTimeMillis() + DEFAULT_TIMEOUT;
long triggerTime = System.currentTimeMillis() + (5000);
AlarmManager am = (AlarmManager) ctx.getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(ctx, TimeoutService.class);
PendingIntent pi = PendingIntent.getBroadcast(ctx, REQUEST_ID, intent, 0);
am.set(AlarmManager.RTC, triggerTime, pi);
}
public static void cancel(Context ctx)
{
AlarmManager am = (AlarmManager) ctx.getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(ctx, TimeoutService.class);
PendingIntent pi = PendingIntent.getBroadcast(ctx, REQUEST_ID, intent, 0);
am.cancel(pi);
}
}
LockingActivity File. This is used as a superclass to all of my Activities.
import android.app.Activity;
import android.widget.Toast;
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 ( AppVM.isShutDown() )
{
Toast.makeText(this, "Shuting Down", 1).show();
finish();
}
}
}
I could send over the TimeoutService file as well, but it's just a typical service file. The problem is the TimeoutService class is never being instanced, so I can't imagine the problem would lie in that class.

I think you are complicating things with an alarm. Use a Handler and postdelayed() to set a Runnable in two minutes, all in your main activity. Any user interaction cancels the post and sets a new one for the next two minutes. The runnable needs only yourActivity.finish();
Follow this answer here: Count for 45 seconds, pause for 20 then repeat with different title for an example of a timer and how to remove the callbacks.

Hi Try using PendingIntent.FLAG_CANCEL_CURRENT flag for your Pending Intent.
PendingIntent pi = PendingIntent.getBroadcast(ctx, REQUEST_ID, intent,PendingIntent.FLAG_CANCEL_CURRENT);
Make Alarm manager as RTC_WAKEUP to wake up device if it is going off some where and check.
With this you need to register a broadcast receiver and fire intent with some action when alarm goes off. Set action to same intent you are using for pending intent.
Start your service in your receiver.
Your this broadcast receiver should be able to listen to action fired by this Intent when Alarm goes OFF.
Intent intent = new Intent(SCH_ALARM_ACTION);
intent.setClass(getBaseContext(), SchAlarmReciever.class);
registerReceiver(new SchAlarmReciever(), new IntentFilter(SCH_ALARM_ACTION));
PendingIntent pi = PendingIntent.getBroadcast(getBaseContext(),
0,
intent,
PendingIntent.FLAG_CANCEL_CURRENT);

Related

How to fire a Service every 2 minutes

I'm doing a bluetooth scan event every 2 minutes to check if a specific device is nearby and can be detected through bluetooth. It's a service as I want it to run in the background.
I would like to know why setRepeat fluctuates after some time, the longest interval was 10 minutes. I'm setting it to fire every 2 minutes.
var intent = Intent(context, Alarm::class.java);
var am = context.getSystemService(AppCompatActivity.ALARM_SERVICE) as AlarmManager
intent.action = "from.alarm.clock";
var pi = PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT)
am.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime() , 1000 * 60 * 2, getBroadcast(this, 0, intent, 0))
UPDATE
Still haven't found the best answer for this problem.
You have to create an Alarm receiver that triggers exactly 2 minutes by recursive call. Android does not allow frequent precise wakeup calls as it might drain battery faster. This is a workaround to get your calls triggered in exact intervals.
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import java.util.concurrent.TimeUnit;
public class NotificationAlarmReceiver extends BroadcastReceiver {
public static final int REQUEST_CODE = 1234;
public static final long PING_FREQ = TimeUnit.MINUTES.toMillis(2);
#Override
public void onReceive(Context context, Intent intent) {
context.startService(new Intent(context, NotificationService.class));
initNotification(context);
}
private void initNotification(Context context) {
Intent intent = new Intent(context, NotificationAlarmReceiver.class);
final PendingIntent pIndent = PendingIntent.getBroadcast(context, NotificationAlarmReceiver.REQUEST_CODE, intent, PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager alarm = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
alarm.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + PING_FREQ, pIndent);
}
}
Refer this site and you will get a good idea on how to use Boradcast to get periodic calls to a service. Reference codepath.com

Android setAlarmClock triggering immediately

I created a simple application to try out setAlarmClock(). There is only a single button in the MainActivity, and it calls setAlarm when clicked.
The code is below.
MainActivity
public class MainActivity extends AppCompatActivity {
private static final String TAG = "alarmclock.MainActivity";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void setAlarm(View view) {
Context context = getApplicationContext();
Intent intent = new Intent(context, AlarmReceiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, intent, 0);
long nextTrigger = SystemClock.elapsedRealtime()+10*1000;
Log.i(TAG, SystemClock.elapsedRealtime() + ": scheduling next alarm at " + nextTrigger);
AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
AlarmManager.AlarmClockInfo ac = new AlarmManager.AlarmClockInfo(nextTrigger, null);
alarmManager.setAlarmClock(ac, pendingIntent);
}
}
AlarmReceiver
public class AlarmReceiver extends BroadcastReceiver {
private static final String TAG = "alarmclock.AlarmReceiver";
#Override
public void onReceive(Context context, Intent intent) {
Log.i(TAG, SystemClock.elapsedRealtime() + " in AlarmReceiver onReceive()");
}
}
I am basically triggering the alarm for 10seconds later, but for some reason it's triggering immediately.
2020-09-21 22:09:56.664 17910-17910/com.example.alarmclock I/alarmclock.MainActivity: 3362358: scheduling next alarm at 3372358
2020-09-21 22:09:56.687 17910-17910/com.example.alarmclock I/alarmclock.AlarmReceiver: 3362382 in AlarmReceiver onReceive()
If I use setExactAndAllowWhileIdle the same code seems to work fine. But I am specifically wanting to try out setAlarmClock.
The AlarmClockInfo requires a wall time:
time at which the underlying alarm is triggered in wall time milliseconds since the epoch
but you are using elapsedRealtime() time so use System.currentTimeMillis to fix the issue.
It worked after I changed from SystemClock.elapsedRealtime() to System.currentTimeMillis().
long nextTrigger = System.currentTimeMillis()+10*1000
After reading the documentation in greater detail, I realise that the first parameter of the AlarmClockInfo constructor takes
long: time at which the underlying alarm is triggered in wall time
milliseconds since the epoch
which is what System.currentTimeMillis() gives.
On the other hand, SystemClock.elapsedRealtime() returns the
time since the system was booted...
which will always be a much smaller number than wall time since epoch. As a result, the alarm gets scheduled immediately because
If the stated trigger time is in the past, the alarm will be triggered immediately.

Alarm Manager not starting after 60 seconds

I'm trying to set my alarm manager working, just simple schedule, firing toast every minute, but it's not working, what's wrong with the code?
Main Activity :
public void klik(View view) {
startalarm();
}
public void startalarm(){
AlarmManager manager = (AlarmManager)getSystemService(Context.ALARM_SERVICE);
Intent intent;
PendingIntent pendingIntent;
intent = new Intent(this, AlarmToastReciever.class);
pendingIntent = PendingIntent.getBroadcast(this,0,intent,0);
manager.setRepeating(AlarmManager.RTC_WAKEUP, SystemClock.elapsedRealtime()+3000,+60000,pendingIntent);
}
}
AlarmToastReciever class :
public class AlarmToastReciever extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent){
Toast.makeText(context,"GOWNO", Toast.LENGTH_SHORT).show();
}
}
As stated in documentation
As of Android 4.4 (API Level 19), all repeating alarms are inexact. Note that while setInexactRepeating() is an improvement over setRepeating(), it can still overwhelm a server if every instance of an app hits the server around the same time. Therefore, for network requests, add some randomness to your alarms, as discussed above.
You can use "setInexactRepeating()" or set an exact one time alarm then set next alarm in On Receive method
Also make sure you added your receiver to the manifest file, between application tag, like
<receiver android:name=".AlarmToastReciever"
android:enabled="true">
<intent-filter>
</intent-filter>
</receiver>
Use this code to initialize alarm manager.
public void setupAlarm() {
final Calendar calNow = Calendar.getInstance();
final Calendar calSet = (Calendar) calNow.clone();
calSet.set(Calendar.HOUR_OF_DAY, calNow.get(Calendar.HOUR_OF_DAY));
calSet.set(Calendar.MINUTE, calNow.get(Calendar.MINUTE) + 1);
calSet.set(Calendar.SECOND, calNow.get(Calendar.SECOND));
final Intent intent = new Intent(this, UploadStarterReceiver.class);
final PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 1,
intent, 0);
final AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
alarmManager.setInexactRepeating(AlarmManager.RTC_WAKEUP, calSet.getTimeInMillis(),
60 * 1000, pendingIntent);
}

Suspicious cast to AlarmManager for a ALARM_SERVICE

Does anyone have faced somthing like this?
Here is the scenario: I want to build a separate class, from where I can stop and start an alarm, via static methods. From the Activity classes, I want to call the methods from this class that I'm planning to build, but the point is that, even tough I'm planning to pass the Activity context to the static methods, when I pass "context" to my AlarmManager object, Android Studio is passing me the following information which is printed on the screen above and I have to admit, that I just can't the point of the message.
What am I missing? I have been looking on Google, but It seems that this situation here is not something so common.
IMPORTAT: Regarding the image above, I tried to use just the context (code below), without using getApplicationContext(), but it didn't worked as well...
Here is the code:
package com.mydomain.myapp;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.os.SystemClock;
public class AlarmManager {
private static AlarmManager alarm;
private static PendingIntent pIntent;
//start alarm
public static void setAlarm(Context context, int alarmId, long alarmTime) {
Intent startAlarmIntent;
long beginAt = SystemClock.elapsedRealtime() + 60 * 1000;
long interval = 300000; // 5 minutes
alarm = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
startAlarmIntent = new Intent(context, AlarmBroadcastReceiver.class);
pIntent = PendingIntent.getBroadcast(context, alarmId, startAlarmIntent, PendingIntent.FLAG_UPDATE_CURRENT);
alarm.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, beginAt, interval, pIntent);
}
//stop alarm
public static void stopAlarm(Context context, int id) {
Intent stopAlarmIntent;
alarm = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
stopAlarmIntent = new Intent(context, AlarmBroadcastReceiver.class);
pIntent = PendingIntent.getBroadcast(context, id, stopAlarmIntent, 0);
alarm.cancel(pIntent);
pIntent.cancel();
}
}
Can anyone give a hand with this, please? Tks!
You created a class named AlarmManager. This is not the same as Android's AlarmManager, and you are trying to cast the value returned by getSystemService() to your AlarmManager, not android.app.AlarmManager.
The simplest solution is to change the name of your class to be something else.

Android set() and setExact() alarms firing at incorrect intervals

I'm developing an app that should perform a certain task every 60 seconds. Since there's some accuracy problems with alarms in Android 4.4+, where all alarms are inexact, I've opted for the chained model: A BroadcastReceiver fires the first alarm, and each alarm in turn sets the next alarm.
The problem is that, even though I'm setting the alarms at intervals of 60 seconds (60000 ms), the alarms trigger at 5 second intervals, and sometimes even less. I've tested the code on my Nexus 5 (Android 5.1.1) and on an Android 5.0.1 emulator, both giving the same result.
I should point out that both receivers are registered on the AndroidManifest and my application has the RECEIVE_BOOT_COMPLETED permission.
EDIT: setExact() causes exactly the same problem
StartupReceiver.java (BroadcastReceiver for BOOT_COMPLETED):
public class StartupReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Log.d(TAG, "Got the BOOT_COMPLETED signal");
// Get the first alarm to be invoked immediately
AlarmReceiver.setNextScanAlarm(context, 0);
}
}
AlarmReceiver.java
public class AlarmReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
// Start the service
Intent startServiceIntent = new Intent(context, BackgroundService.class);
startServiceIntent.putExtra("interval", 60000);
startServiceIntent.putExtra("action", "scan");
context.startService(startServiceIntent);
// Schedule the next alarm
setNextScanAlarm(context, 60000);
}
public static void setNextScanAlarm(Context context, int interval) {
Intent scanIntent = new Intent(context, AlarmReceiver.class);
scanIntent.putExtra("interval", interval);
scanIntent.putExtra("action", "scan");
PendingIntent pendingIntent = PendingIntent.getBroadcast(
context,
0,
scanIntent,
PendingIntent.FLAG_ONE_SHOT);
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
alarmManager.set(
AlarmManager.ELAPSED_REALTIME_WAKEUP,
interval,
pendingIntent);
}
}
What could be the problem?
I believe because this is an alarm clock when calling
alarmManager.set(
AlarmManager.ELAPSED_REALTIME_WAKEUP,
interval,
pendingIntent);
The variable you are calling interval is the amount of time you want to elapse UNTIL the next alarm , but when you think about this when does it know to start? More so, when does time actually equal zero? When you create it? No. When you call .set()? No. It is actually zero upon BOOT. So you are asking it to launch 60 seconds after boot, and your asking for this everytime, this time will have already elapsed.
This is where the confusion is, and where you should probably just use a call like new
Handler.postDelayed(Runnnable r, 60000) instead of an alarm Manager. It will be much more accurate and will not be subject to some problems with understanding the Android Operating System and its alarms/clocks/etc/etc.
But for your specific case I believe you could solve it by accessing System function calls/variables. So inside of your function setNextScanAlarm() I believe it would look like this:
public static void setNextScanAlarm(Context context, int interval) {
//create the intent the same way as before
Intent scanIntent = new Intent(context, AlarmReceiver.class);
scanIntent.putExtra("interval", interval);
scanIntent.putExtra("action", "scan");
PendingIntent pendingIntent = PendingIntent.getBroadcast(
context,
0,
scanIntent,
PendingIntent.FLAG_ONE_SHOT);
//create new variables to calculate the correct time for this to go off
long timeRightNow = System.elapsedRealTime() //use something else if you change AlarmManager type
long timeWhenIShouldGoOff = timeRightNow + interval;
//use the new timeWhenIShouldGoOff variable instead of interval
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
alarmManager.set(
AlarmManager.ELAPSED_REALTIME_WAKEUP,
timeWhenIShouldGoOff,
pendingIntent);
}
See my answer to a similar question.
I use postDelayed() instead of AlarmManager for the short time intervals (less than 1 minute), and AlarmManager for long.

Categories

Resources