I have read many more similar questions to this in stackoverflow but I couldn't solve my problem.
I want to trigger an android service at 3.45p.m of every day.For that I used an AlarmManager which starts the service as follows.
Application class
public class AppSettings extends Application {
#Override
public void onCreate() {
super.onCreate();
scheduleAlarm();
}
public void scheduleAlarm() {
Intent intent = new Intent(getApplicationContext(), UploadService.class);
final PendingIntent pIntent = PendingIntent.getService(this, 0,
intent, 0);
AlarmManager alarm = (AlarmManager) getSystemService(ALARM_SERVICE);
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.set(Calendar.HOUR_OF_DAY, 15);
calendar.set(Calendar.MINUTE, 45);
alarm.setInexactRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), AlarmManager.INTERVAL_FIFTEEN_MINUTES, pIntent);
}
}
Service class
public class UploadService extends Service {
#Override
public void onCreate() {
Log.d("MyAlarmService", "onCreate");
Toast.makeText(this, "MyAlarmService.onCreate()", Toast.LENGTH_LONG).show();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Toast.makeText(this, "onStartCommand Called", Toast.LENGTH_LONG).show();
Vibrator v = (Vibrator) getSystemService(VIBRATOR_SERVICE);
// Vibrate for 500 milliseconds
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
v.vibrate(VibrationEffect.createOneShot(500, VibrationEffect.DEFAULT_AMPLITUDE));
} else {
//deprecated in API 26
v.vibrate(500);
}
stopSelf();
return START_STICKY;
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
Toast.makeText(this, "MyAlarmService.onBind()", Toast.LENGTH_LONG).show();
return null;
}
#Override
public void onDestroy() {
super.onDestroy();
Log.d("MyAlarmService", "onDestroy");
}
#Override
public boolean onUnbind(Intent intent) {
Toast.makeText(this, "MyAlarmService.onUnbind()", Toast.LENGTH_LONG).show();
return super.onUnbind(intent);
}
}
Manifest file
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.softarena.photosapp">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<application
android:name=".app.AppSettings"
android:allowBackup="true"
android:icon="#drawable/logoo"
android:label="#string/app_name"
android:roundIcon="#drawable/logoo"
android:supportsRtl="true"
android:theme="#style/Theme.MyApplication">
<activity android:name=".views.SplashActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".views.PhotoDetailActivity" />
<activity android:name=".views.MainActivity" />
<activity android:name=".views.LoginActivity" />
<activity android:name=".views.SignUpActivity" />
<service
android:name="com.softarena.photosapp.services.UploadService"
android:enabled="true" />
</application>
</manifest>
when I run the app the my phone is onStartCommand is getting called but only when the app is open.if I close the app and wait until onStartCommand getting called it is not working.I am using a Nokia 8 device which runs android 9.I tried starting alarm manager with setAndAllowWhileIdle() and setExactAndAllowWhileIdle() also considering Doze mode but there is no way to repeat the alarm with these 2 methods and if app is closed onStartCommand not getting called.
Is this a device problem or is there anything wrong with my code?
Edit: Can I use a WorkManager or a JobScheduler to achieve my requirement?
Related
I am trying an alarm for every fifteen minute and problem is that I hear that alarm will work when app is not running, but in my case alarm works first time and even second time if app is on screen. else not.also I want to know when first alarm is set and time was in previous time,alarm will start in recent time, but if I set pending intent for 24 hours and at that time mobile was shut down and I turned my mobile after one or two hours, will pending intent that was for a day work after 25 or 26 hours or not.please help
here is my code.
public class MainActivity extends AppCompatActivity {
Calendar calendar=Calendar.getInstance();
Button btn;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btn=(Button)findViewById(R.id.bt);
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.set(Calendar.HOUR_OF_DAY,13);
calendar.set(Calendar.MINUTE,54);
calendar.set(Calendar.SECOND,1);
btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.set(Calendar.HOUR_OF_DAY,13);
calendar.set(Calendar.MINUTE,54);
calendar.set(Calendar.SECOND,1);
setAlarm(calendar.getTimeInMillis());
}
});
}
private void setAlarm(long time) {
calendar.setTimeInMillis(System.currentTimeMillis());
//getting the alarm manager
AlarmManager am = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
//creating a new intent specifying the broadcast receiver
Intent i = new Intent(this, MyAlarm.class);
//creating a pending intent using the intent
PendingIntent pi = PendingIntent.getBroadcast(this, 0, i, 0);
//setting the repeating alarm that will be fired every day
am.setRepeating(AlarmManager.RTC, time, AlarmManager.INTERVAL_FIFTEEN_MINUTES, pi);
Toast.makeText(this, "Alarm is set", Toast.LENGTH_SHORT).show();
}
}
and here is my service
public class MyAlarm extends BroadcastReceiver{
MediaPlayer mp;
#Override
public void onReceive(Context context,Intent intent){
mp=MediaPlayer.create(context,R.raw.song);
mp.start();
}
}
manifest is here
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.bilal.pkr">
<uses-permission android:name="android.permission.WAKE_LOCK"></uses-permission>
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"></uses-permission>
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.VIEW"/>
<action android:name="android.intent.action.MAIN" />
<action android:name="android.intent.action.BOOT_COPLETED"></action>
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver
android:name=".MyAlarm"
android:enabled="true"
android:exported="true" />
</application>
</manifest>
am.setRepeating(AlarmManager.RTC_WAKEUP, time, AlarmManager.INTERVAL_FIFTEEN_MINUTES, pi);
Use this.
This is my first post and I am new to Android App development so please bear with me.
I have written (and use every day) a pretty good reminders App because all the others were either too complicated or too simple. It is also on the play store, although not easy to find, but thats another story.
While I am happy with the whole App the alarms which show a notification or sound an alarm do not always happen. If the alarm is soon then it will but more than say 2 hours from now it often gets missed. Using "adb shell dumpsys alarm" it looks as if they are being discarded?
I have googled for days and have tried so many things, from this forum too, but no luck so I thought I would post some code to see if anybody can please tell me were I am going wrong as it should work as far as I can see.
So here goes.
I use alarm manager to queue the pending intent to call my broadcast receiver which starts a service which starts an activity which creates a notification and optionally sounds an alarm.
I was skipping the service bit but after googling it seems I should use a service. And as mentioned, this works fine for alarms happening soon but not after a few hours or a day or more. Could be due to Doze mode or my app being stopped by Android?
I would really appreciate some help please as I am pulling my hair out!!
Thanks in advance.
Here is my manifest. Where I think the problem is?
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.wingwares.reminders">
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="com.android.alarm.permission.SET_ALARM" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.VIBRATE" />
<supports-screens
android:anyDensity="true"
android:normalScreens="true" />
<application
android:icon="#drawable/reminder2"
android:label="#string/app_name"
android:theme="#style/AppTheme">
<receiver android:name=".WidgetProvider">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>
<meta-data
android:name="android.appwidget.provider"
android:resource="#xml/widget_info" />
</receiver>
<service
android:name=".WidgetService"
android:exported="false"
android:permission="android.permission.BIND_REMOTEVIEWS" />
<activity
android:name=".AppPreferences" />
<activity
android:name=".ListActivity"
android:label="#string/app_name"
android:screenOrientation="portrait"
android:windowSoftInputMode="stateAlwaysHidden">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".RemActivity"
android:label="#string/add_reminder"
android:screenOrientation="portrait"
android:windowSoftInputMode="adjustPan" />
<service
android:name=".AlarmService"
android:enabled="true"
android:exported="true" >
</service>
<receiver
android:name=".AlarmReceiver"
android:enabled="true"
android:exported="true" >
<intent-filter>
<action android:name="SET_ALERT" />
</intent-filter>
</receiver>
<activity
android:name=".AlarmDialog"
android:theme="#style/AlarmDialog" />
</application>
</manifest>
And my Alarm Manager from ListActivity
public void setAlert(Context context, boolean turnOn){
intent = new Intent(context, AlarmReceiver.class);
intent.putExtra("name", fullName());
intent.putExtra("notes", notes);
intent.putExtra("setalarm", setalarm);
intent.putExtra("millis", time.getMilliTime());
intent.putExtra("remId", remId);
pendingIntent = PendingIntent.getBroadcast(context, 8192 + remId, intent, PendingIntent.FLAG_UPDATE_CURRENT);
alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
alarmManager.cancel(pendingIntent);
if (turnOn) {
alertTime = time.getMilliTime() - (warning * 60000);
interval = getInterval();
//set repeating alarmManager just once
if (freq.equals(EVERY) && type.equals(FIXED) && date.equals(getOriginal()) && interval > 0) {
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, alertTime, interval, pendingIntent);
} else {
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, alertTime, pendingIntent);
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
alarmManager.setExact(AlarmManager.RTC_WAKEUP, alertTime, pendingIntent);
} else {
alarmManager.set(AlarmManager.RTC_WAKEUP, alertTime, pendingIntent);
}
}
} else {
setalarm = false;
}
}
My broadcast receiver
public class AlarmReceiver extends WakefulBroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Intent newIntent = new Intent(context, AlarmService.class);
//pass the extras on and show the dialog
newIntent.putExtras(intent);
startWakefulService(context, newIntent);
}
}
My Service
public class AlarmService extends IntentService {
public AlarmService (){
super("AlarmService");
}
#Override
protected void onHandleIntent(Intent intent) {
Intent newIntent = new Intent(this, AlarmDialog.class);
newIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);
//pass the extras on and show the dialog
newIntent.putExtras(intent);
startActivity(newIntent);
AlarmReceiver.completeWakefulIntent(newIntent);
}
}
My Activity (the notification part)
public class AlarmDialog extends Activity
implements DialogInterface.OnCancelListener, DialogInterface.OnClickListener {
Bundle extras;
int remId;
String name, notes;
Boolean setalarm;
long alarmTime;
MediaPlayer player;
PendingIntent pendingIntent;
SharedPreferences mPrefs;
NotificationManager manager;
Notification notification;
static final int SNOOZE_BUTTON = -2;
static final int DISMISS_BUTTON = -1;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//create notification and alert box if alarmManager selected
mPrefs = PreferenceManager.getDefaultSharedPreferences(getBaseContext());
extras = getIntent().getExtras();
alarmTime = extras.getLong("millis");
remId = extras.getInt("remId");
name = extras.getString("name");
notes = extras.getString("notes");
setalarm = extras.getBoolean("setalarm");
//notification first
notification = new RemNotification(this, name).get();
if (notification != null) {
manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
manager.cancel(remId);
manager.notify(remId, notification);
}
}
I am currently trying to call a BroadCastReceiver with an AlarmManager to ouput a notification on a certain time! On Android SDK Level 19+ my method works, but on Android 17 my approach leads into nothing!
There are no errors outputted, nor are there any logs in the monitor of Android Studio. The BroadcastReceiver is simply not called by the AlarmManager.
MainActivity.java
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button mButton = (Button) findViewById(R.id.btn);
mButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
setNotification();
}
});
}
public void setNotification() {
Intent resultIntent = new Intent(this, NotificationPublisher.class);
resultIntent.setData(Uri.parse("notification://1995-" + System.currentTimeMillis()));
AlarmManager alarmManager = (AlarmManager)getSystemService(ALARM_SERVICE);
PendingIntent resultPendingIntent =
PendingIntent.getBroadcast(
this,
1995,
resultIntent,
PendingIntent.FLAG_UPDATE_CURRENT
);
alarmManager.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + 30 * 1000, resultPendingIntent);
Log.d("Test", "Alarm started");
}
}
NotificationPublisher.java
public class NotificationPublisher extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, "What", Toast.LENGTH_SHORT).show();
}
}
AndroidManifext.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="nbaye.apptesting">
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver android:name=".NotificationPublisher"
android:process=":remote"
android:enabled="true" />
</application>
</manifest>
Min SDK: 17
Target: 23
EDIT:
I have looked into the AlarmManager with "adb shell dumpsys alarm":
The alarm is created by the app, but the "when" variable of the alarm is counting down from +30 seconds to an infinite negative number!
I have to schedule invoking of an already install test project on the device after 10 sec once the button is click. For that I have created an AlarmReceiver and my TaskService which actually is invoking the test project.
After running the app, nothing happens after the button is clicked. I don't know what is wrong but service doesn't performs the job even after 10 sec.
Below is my code which I am trying. The Activity class:
// Create an anonymous implementation of OnClickListener
private OnClickListener HTListener = new OnClickListener() {
public void onClick(View v) {
btnStartSchedule(v);
}
};
public void btnStartSchedule(View v) {
try {
AlarmManager alarms = (AlarmManager) this.getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(getApplicationContext(), AlarmReceiver.class);
intent.putExtra(AlarmReceiver.ACTION_ALARM, AlarmReceiver.ACTION_ALARM);
final PendingIntent pIntent = PendingIntent.getBroadcast(this, 1234567, intent, PendingIntent.FLAG_UPDATE_CURRENT);
alarms.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), 10000, pIntent);
Toast.makeText(ScrapeActivity.this, "Alarm Started", Toast.LENGTH_LONG).show();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
The AlarmReceiver class :
public class AlarmReceiver extends BroadcastReceiver {
public static String ACTION_ALARM = "com.alarmmanager.alarm";
#Override
public void onReceive(Context context, Intent intent) {
Log.i("Alarm Receiver", "Entered");
Toast.makeText(context, "Entered", Toast.LENGTH_SHORT).show();
Bundle bundle = intent.getExtras();
String action = bundle.getString(ACTION_ALARM);
if (action.equals(ACTION_ALARM)) {
Log.i("Alarm Receiver", "If loop");
Intent inService = new Intent(context, LaunchService.class);
context.startService(inService);
} else {
Log.i("Alarm Receiver", "Else loop");
Toast.makeText(context, "Else loop", Toast.LENGTH_SHORT).show();
}
}
}
And finally the LaunchService class:
public class LaunchService extends IntentService {
public LaunchService(String name) {
super(name);
// TODO Auto-generated constructor stub
}
#Override
protected void onHandleIntent(Intent intent) {
Intent LaunchIntent = getPackageManager().getLaunchIntentForPackage("com.my.testproject");
startActivity(LaunchIntent);
}
}
I have also mention the receiver and service inside the manifest file :
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.my.pb.activity"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="19" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_INTERNAL_STORAGE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/PB_APP"
android:theme="#style/AppTheme" >
<activity
android:name="com.my.pb.activity.ScrapeActivity"
android:label="#string/PB_APP" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver
android:name=".AlarmReceiver"
android:process=":remote" >
</receiver>
<service android:name=".LaunchService" >
</service>
</application>
I don't understand whats the issue coz there's no exception in the Logcat. As I click the button, i just see the toast message saying Alarm Started. Please help.
You have a typo at the Manifest, you declared AlaramReceiver instead of .AlarmReceiver there.
Currently i am working on a Broadcast Receiver application, in which i am making an Alarm which should display a message after we enter the seconds. I used RTC_WAKEUP, which means it should display the message when the device is on and it is supposed to turn on the device and then display the message when the device is off. MY PROBLEM IS THAT IT RTC_WAKEUP DOESN'T ON MY DEVICE but it is working properly when device is on. i am pasting the code of my application. In my application there are two classes.
MainActivity
public class MainActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void startAlert(View view) {
EditText text = (EditText) findViewById(R.id.time);
int i = Integer.parseInt(text.getText().toString());
Intent intent = new Intent(this, MyBroadcastReceiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(this.getApplicationContext(), 23432424, intent, 0);
AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
alarmManager.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis()
+ (i * 1000), pendingIntent);
Toast.makeText(this, "Alarm set in " + i + " seconds",
Toast.LENGTH_LONG).show();
}
}
and other is
MyBroadcastReceiver
public class MyBroadcastReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, "Jaago Mohan Pyarreee!!!!.",
Toast.LENGTH_LONG).show();
}
}
Manifest
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.broadcastreceiver"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="15" />
<uses-permission android:name="android.permission.VIBRATE"/>
<uses-permission android:name="android.permission.WAKE_LOCK" />
<application
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity
android:name=".MainActivity"
android:label="#string/title_activity_main" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver android:name=".MyBroadcastReceiver" >
</receiver>
</application>
</manifest>
RTC_WAKEUP will not switch on the screen, all it does is wakes up thee cpu so that your job is done. For the Screen to be turned on you need a FULL wakelock to be acquired.
PowerManager pm = (PowerManager)mContext.getSystemService(Context.POWER_SERVICE);
PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK
| PowerManager.ON_AFTER_RELEASE,
"wakeup");
wl.acquire();
// ... do work...
//show toask
wl.release();
Do yo have the permission in your Manifest?
<uses-permission android:name="android.permission.WAKE_LOCK" />
Fix your manifest. Instead of
<receiver android:name="MyBroadcastReceiver" >
you need:
<receiver android:name=".MyBroadcastReceiver" >
Checked the google DeskClock app:
com.android.deskclock.alarms.AlarmStateManager (it's a BroadcastReceiver)
In its onReceive function used goAsync():
#Override
public void onReceive(final Context context, final Intent intent) {
final PendingResult result = goAsync();
final PowerManager.WakeLock wl = AlarmAlertWakeLock.createPartialWakeLock(context);
wl.acquire();
AsyncHandler.post(new Runnable() {
#Override
public void run() {
handleIntent(context, intent);
result.finish();
wl.release();
}
});
}
You should take a shot with that.