AlarmClock intent says "No apps can perform this action." - android

I am trying to set an alarm in the alarm clock with an intent. I am using an Android One Phone (which has the unmodified OS) and have the Clock app installed (which came pre-installed) which allows setting alarm. Setting an alarm has worked in the past when I had used an AlarmManager and PendingIntent when I had to set the alarm in the background. That shows that my Clock app can respond to AlarmClock intents. But now when I am trying to send an intent from the foreground of my app, it says:
No apps can perform this action.
This is not from the stack trace, but a popup which is shown to users to choose which Clock app to choose to set the alarm (or which app to use in general for an intent)
Here's the Activity's onCreate() code where I am calling it:
public class MainActivity extends AppCompatActivity {
...
#Override
protected void onCreate(Bundle savedInstanceState) {
...
Utils.setAlarm(this, Utils.getLDT(epochTime).plusHours(8));
}
}
Here's the Utils#setAlarm function that sends the intent:
public class Utils {
public static void setAlarm(Context context, LocalDateTime alarmTimeDT) {
Intent intent = new Intent(AlarmClock.ACTION_SET_ALARM);
intent.putExtra(AlarmClock.EXTRA_SKIP_UI, true);
intent.putExtra(AlarmClock.EXTRA_HOUR, alarmTimeDT.getHour());
intent.putExtra(AlarmClock.EXTRA_MINUTES, alarmTimeDT.getMinute());
intent.putExtra(AlarmClock.EXTRA_MESSAGE, "Good Morning");
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intent);
}
...
}
This is the additional code that was used in the past for the same device and same Clock app. This is for cancelling an already set alarm, but the code used to set the old alarm was similar except for the cancelling part:
//cancel old alarm
AlarmManager alarmMgr = (AlarmManager) this.getSystemService(Context.ALARM_SERVICE);
PendingIntent alarmIntent = PendingIntent.getActivity(
this, 0, i, PendingIntent.FLAG_UPDATE_CURRENT);
if (alarmIntent != null) {
alarmMgr.cancel(alarmIntent);
} else {
Log.i(TAG, "intent is null");
}
What am I doing wrong? Any help appreciated.
The below comments is just questioning and asking for more clarification on the question, which were done as asked for. So you may skip reading them

No apps can perform this action.
This happens when you don't have the required permission to set the alarm.
From AlarmClock reference:
Applications that wish to receive the ACTION_SET_ALARM and ACTION_SET_TIMER Intents should create an activity to handle the Intent that requires the permission com.android.alarm.permission.SET_ALARM.
Request the SET_ALARM permission:
<mainfest
...
<uses-permission android:name="com.android.alarm.permission.SET_ALARM"/>
</manifest>

Related

Xamarin service - run according to a time schedule

I am developing an app built on this example: https://github.com/xamarin/mobile-samples/tree/master/BackgroundLocationDemo
The example works and the location updates are coming in as expected. However, Android keeps showing an notification that the service is running and draining battery. Now, all my users have a defined working schedule (list of Start to End DateTime per day e.g 8am-1pm, 4pm-8pm), and I want that the service is only running between those working times. This means that I need to start/stop the service whenever the schedule says the user is working or not.
I've asked this question before but wondering if anyone figured out an efficient and solid way to achieve this type of service that is operating from a time schedule?
You can use AlarmManager to execute a task in specific time.
For example, I want my task running at the 10:51 am every day, I can use following code to execute it.
public static void startAlarmBroadcastReceiver(Context context)
{
Intent _intent = new Intent(context, typeof( AlarmBroadcastReceiver));
PendingIntent pendingIntent = PendingIntent.GetBroadcast(context, 0, _intent, 0);
AlarmManager alarmManager = (AlarmManager)context.GetSystemService(Context.AlarmService);
// Remove any previous pending intent.
alarmManager.Cancel(pendingIntent);
Calendar cal = Calendar.Instance;
cal.Set( CalendarField.HourOfDay, 10);
cal.Set(CalendarField.Minute, 51);
cal.Set(CalendarField.Second, 0);
alarmManager.SetRepeating(AlarmType.RtcWakeup, cal.TimeInMillis, AlarmManager.IntervalDay, pendingIntent);
}
Here is code about AlarmBroadcastReceiver.
[BroadcastReceiver(Enabled = true, Exported = false)]
public class AlarmBroadcastReceiver : BroadcastReceiver
{
public override void OnReceive(Context context, Intent intent)
{
Toast.MakeText(context, "Received intent!", ToastLength.Short).Show();
}
}
Do not forget to add following permissions.
<uses-permission android:name="com.android.alarm.permission.SET_ALARM" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
Here is running gif.

Why Alarm not fired when I remove app from recent apps?

I can see many apps that can handle more complex situations like Notifications and it's work verywell.
Requirement:
I'm just trying to set an alarm to fire at specific time
Problem:
It's work only if app exist in recent apps, if I removed it from recent apps no alarm fired!
Questions:
Why it's not working? - What should I do to make it working?
My Code Snipp:
What my alarm firing look like:
Intent intent = new Intent(this, MyBroadcastReceiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(
this.getApplicationContext(), PENDING_INTENT_ID, intent, PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
assert alarmManager != null;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, timeInMilliseconds, pendingIntent);
} else {
alarmManager.setExact(AlarmManager.RTC_WAKEUP, timeInMilliseconds, pendingIntent);
}
What MyBroadcastReceiver look like:
public class MyBroadcastReceiver extends BroadcastReceiver {
private static final String TAG = "MyBroadcastReceiver";
#Override
public void onReceive(Context context, Intent intent) {
Log.i(TAG, "BroadCast Fired!");
}
Enable for boot:
ComponentName componentName = new ComponentName(this, MyBroadcastReceiver.class);
PackageManager packageManager = getPackageManager();
packageManager.setComponentEnabledSetting(componentName,
componentEnabledState,
PackageManager.DONT_KILL_APP);
Manifest:
<receiver
android:name="MyBroadcastReceiver"
android:enabled="false">
<intent-filter>
<action
android:name="android.intent.action.BOOT_COMPLETED"/>
</intent-filter>
</receiver>
This happens because the manufacturer of your device (Oppo) added a custom setting to kill apps when they are removed from the list of recent apps.
This is NOT standard Android behavior. In normal Android, an app is not killed when removed from the list of recent apps (and that's why it worked correctly on the emulator).
The solution is to locate where this setting resides in your device and change it. In some devices, you may need to pin the app to the list of recent apps too, so it doesn't get removed. But this may change depending on the specific device model.
If you can't find the setting, I recommend to search in Oppo forums or check this page: https://dontkillmyapp.com/
But your code is correct. There's nothing more you can do from the app.

Android 8.0 Oreo AlarmManager with broadcast receiver and implicit broadcast ban

I have critical reminders that are set via the Alarm Manager (It should function the same way as an alarm clock application).
Previously I had the following in my Android Manifest:
<receiver android:name="com.example.app.AlarmReceiver" >
<intent-filter>
<action android:name="${packageName}.alarm.action.trigger"/>
</intent-filter>
</receiver>
The broadcast receiver:
public class AlarmReceiver extends BroadcastReceiver {
#Override public void onReceive(
final Context context,
final Intent intent) {
// WAKE LOCK
// BUILD NOTIFICATION etc...
}
}
How the alarm is set:
final PendingIntent operation = PendingIntent.getBroadcast(
mContext,
requestCode,
intent,
PendingIntent.FLAG_CANCEL_CURRENT);
if (PlatformUtils.hasMarshmallow()) {
alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, triggerAtMillis, operation);
} else {
alarmManager.setExact(AlarmManager.RTC_WAKEUP, triggerAtMillis, operation);
}
}
With Android 8.0 I can no longer use an implicit broadcast as defined in the Manifest. That's fine, the alternative given is to register it manually like so:
final BroadcastReceiver receiver = new AlarmReceiver();
final IntentFilter intentFilter = new IntentFilter(ALARM_RECEIVER_INTENT_TRIGGER);
context.registerReceiver(receiver, intentFilter);
This does not seem logical to me.
The alarm receiver will be tied to the lifetime of the context. This causes an issue when say the application is killed due to memory pressure or when the device is restarted. I need my alarms to fire every time as they are critical for the health of the user.
Even if I listen to "android.intent.action.BOOT_COMPLETED" and register my alarm receiver the app is killed shortly after and no alarm is fired. I also don't see my alarm via
adb shell dumpsys alarm
How do I create a custom broadcast receiver that receives an implicit broadcast to fire an alarm while targeting Android O (8.0)? Can someone enlighten me with a code example or link to documentation. How does Timely or any other alarm clock app function while targeting O?
Revise your code slightly to make the broadcast explicit rather than implicit and you'll be fine (assuming this is an Activity reference or some other Context):
Intent intent = new Intent(ALARM_RECEIVER_INTENT_TRIGGER);
intent.setClass(this, AlarmReceiver.class);
The restriction in Oreo is on implicit broadcast Intent registration, which is to say it you are sending it broadcasts will only action, category, or data specified. You make it an explicit broadcast by specifying the class which is to receive the broadcast.
If you guys are used to check if the alarm has already been registered don't forget to do the same on this verification:
public boolean isAlarmBroadcastRegistered(Context context, String action, Class clazz) {
Intent intent = new Intent(action);
intent.setClass(context, clazz);
return PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_NO_CREATE) != null;
}

android services life time continuation

In mainactivity
I have Broadcast Receiver, pending intent, and alarm manager. It triggers as per selected time (System.currentTimeMillis() + smstimeinmilliseconds).
Intent intent = new Intent(this, DBBroadcastReceiver.class);
intent.putExtra("message", message);
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, id, intent, 0);
AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
alarmManager.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + smstimeinmilliseconds, pendingIntent);
On selected time, this pending intent triggers broadcast receiver.
public class DBBroadcastReceiver extends BroadcastReceiver
#Override
public void onReceive(Context context, Intent intent)
{
message = intent.getStringExtra("message");
}
I can set message in activity and set time in alarm manager.
Every thing works flawless. I can activate and deactivate this. But if i set few alarm mangers in future time and reboot my mobile. all alarm manager destroy .....
Kindly tell me in steps and sequence what to do with activity , broadcast receiver and do i need service , if yes then how can i use it.
You need a BoradcastReceiver to be called on boot up.
Then you need in your manifest :
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<receiver
android:name=".broadcasts.YourBroadcastReceiverName">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
And this broadcast receiver needs to schedule again all the alarms.
Something like :
public class YourBroadcastReceiverName extends BroadcastReceiver {
private AlarmManagerFacade alarmManager;
#Override
public void onReceive(Context context, Intent intent) {
// Retreive data related to alarms
Cursor cursor = context.getContentResolver().query(Alarm.CONTENT_URI, null,
Alarm.COLUMN_ACTIVE + " = ? ",
new String[] { String.valueOf(1) }, "");
if (cursor.moveToFirst()) {
// Schedule all the active alarms.
alarmManager = new AlarmManagerFacade(context);
do {
// TODO : Schedule alarm according to data in cursor.
} while (cursor.moveToNext());
}
cursor.close();
}
}
(This code is coming from one of my app, some of the objects are not available in the Android SDK)
In order to be able to re schedule all the alarms, you need to have them stored somewhere.
You can write your own ContentProvider for example.
It works well with other android components thanks to the CursorAdapter widget.
It is not the easiest solution but it's the way to go if you want to follow android guidelines.
There may be other simpler alternative to store your alarms, like SharedPreferences.
It's easy to use.
But you will need to hack around to store multiple alarms in a friendly manner.
One last alternative is that you can create an object containing the information, serialize it and store it as a file on the SD Card.
It's ugly and not flexible.
But it not that hard to implement ...
If you want to have a closer look to each storage options, you can read about it in the docs here : http://developer.android.com/guide/topics/data/data-storage.html
I hope all this help you. :)

How do you start an Activity with AlarmManager in Android?

I've poured through a dozen tutorials and forum answers about this problem, but still haven't been able to get some working code together. I'll try to keep the question straightforward:
How do you use AlarmManager (in the Android API) to start an Activity at a given time? Any solution to this problem will do.
My latest attempt to achieve this is below.
(Imports omitted. I expect MyActivity to start 3 seconds after the program is opened, which it doesn't. There are no error messages to speak of.)
public class AndroidTest2Activity extends Activity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Context context = this;//.getApplicationContext();
AlarmManager manager = (AlarmManager) getSystemService(Context.ALARM_SERVICE); // CORRECT
Intent intent = new Intent(context, myReceiver.class); // CORRECT
PendingIntent pending = PendingIntent.getBroadcast( context, 0, intent, 0 ); // CORRECT
manager.set( AlarmManager.RTC, System.currentTimeMillis() + 3000, pending ); // CORRECT
setContentView(R.layout.main);
}
}
public class myReceiver extends BroadcastReceiver {
public void onReceive(Context context, Intent intent) {
Intent i=new Intent(context, myActivity.class);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(i);
}
}
public class myActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d("", "Elusive success");
setContentView(R.layout.main);
}
}
Any advice would be appreciated.
Please note: I've got myReceiver in the manifest already
In case someone else stumbles upon this - here's some working code (Tested on 2.3.3 emulator):
public final void setAlarm(int seconds) {
// create the pending intent
Intent intent = new Intent(MainActivity.this, AlarmReceiver.class);
// intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
pendingIntent = PendingIntent.getBroadcast(MainActivity.this, 0,
intent, 0);
// get the alarm manager, and scedule an alarm that calls the receiver
((AlarmManager) getSystemService(ALARM_SERVICE)).set(
AlarmManager.RTC, System.currentTimeMillis() + seconds
* 1000, pendingIntent);
Toast.makeText(MainActivity.this, "Timer set to " + seconds + " seconds.",
Toast.LENGTH_SHORT).show();
}
public static class AlarmReceiver extends BroadcastReceiver {
public void onReceive(Context context, Intent intent) {
Log.d("-", "Receiver3");
}
}
AndroidManifest.xml:
<receiver android:name="com.example.test.MainActivity$AlarmReceiver" >
</receiver>
Issues with BenLambell's code :
EITHER:
Move the receiver to it's own .java file or
make the inner class static - so it can be accessed from outside
Receiver is not declared correctly in the manifest:
if it's an inner class in MainActivity use:
<receiver android:name="package.name.MainActivity$AlarmReceiver" ></receiver>
if it's in a separate file:
<receiver android:name="package.name.AlarmReceiver" ></receiver>
If your intention is to display a dialog in the receiver's onReceive (like me): that's not allowed - only activities can start dialogs. This can be achieved with a dialog activity.
You can directly call an activity with the AlarmManager:
Intent intent = new Intent(MainActivity.this, TriggeredActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(MainActivity.this, 0, intent, PendingIntent.FLAG_ONE_SHOT);
((AlarmManager) getSystemService(ALARM_SERVICE)).set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + seconds * 1000, pendingIntent);
How do you use AlarmManager (in the Android API) to start an Activity at a given time?
Supply a PendingIntent to the set() call that identifies the activity to start up. Or, do what you're doing, which should work just fine.
This sample project is a bit elaborate, because it's 19 tutorials deep into one of my books, but if you look at classes like EditPreferences, OnBootReceiver, and OnAlarmReceiver, you will see the same basic recipe that you're using above. In this case, I could have just used a getActivity() PendingIntent, but the tutorial after this one gives the user a choice of launching an activity or displaying a Notification, so a BroadcastReceiver makes more sense.
Look for warnings in addition to errors in LogCat. Most likely, your receiver or activity is not in your manifest.
Note that popping up an activity out of the middle of nowhere is generally not a good idea. Quoting myself from the book in question:
Displaying the lunchtime alarm via a full-screen activity certainly works,
and if the user is looking at the screen, it will get their attention. However,
it is also rather disruptive if they happen to be using the phone right that
instant. For example, if they are typing a text message while driving, your
alarm activity popping up out of nowhere might distract them enough to
cause an accident. So, in the interest of public safety, we should give the user an option to
have a more subtle way to remind them to have lunch.
add this in your android mainifest file and it will hopefully work
<activity android:name=".MyReceiver" />
<receiver android:name=".MyReceiver"> </receiver>
In my experience you can achieve this without broadcast receiver, just use PendingIntent.getActivity() instead of getbroadcast()
private void setReminder(){
AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
Calendar startTime = Calendar.getInstance();
startTime.add(Calendar.MINUTE, 1);
Intent intent = new Intent(ReminderActivity.this, ReminderActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
PendingIntent pendingIntent = PendingIntent.getActivity(ReminderActivity.this, 1, intent, PendingIntent.FLAG_UPDATE_CURRENT);
alarmManager.set(AlarmManager.RTC, startTime.getTimeInMillis(), pendingIntent);
}
I've tested this code on android O but I'm not sure about other android versions please inform me if this doesn't work on any other android version.
Main Problem : if you close completely you're app and expect to start you're activity after 3 seconds, you wrong. because when you close you're app , you're app cant receive broadcast, for solve this problem use services instead of broadcasts.
Point: when you're service would ran ,you cant start your activity if your app wouldn't in foreground.
Solution: I think when your service started you can again set Alarmmanager to start your activity with PendingIntent for just now.
Remember :
When you create your intent for pass it to pendingIntent add the FLAG_ACTIVITY_NEW_TASK to it.
For this PendingIntent use PendingIntent.getActivity() method and for the first PendingIntent use PendingIntent.getService() method.
I hope this help you.
I had this problem too long ago to know which answer is correct, but thank you to everyone for their responses. I'm self-answering so the question isn't still open.
According to Java convention class name begin with Capital letter.So change your
"myReceiver" to "MyReceiver" and "myActivity" to "MyActivity".
Then add your receiver in the manifest file like the below.
<application
------------
<receiver android:name="MyReceiver"></receiver>
---------------------
</application>
you are not sending any broadcast for the receiver to receiver and further more it lokks like u want a splash screen or something like that for that purpose u can start a new thread wait for some sec then start ur activity in that and for that time period u can do what ever u want on the UI thread ...

Categories

Resources