I want to implement a background task in my android application. For Android 5.0 and lower, my code suffices with a simple BroadcastReceiver, where I can easily set an repeating alarm with
setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), 1000 * seconds, pendingIntent);
On Android 6.0, however, I found out to replace my BroadcastReceiver with WakefulBroadcastReceiver and
setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), pendingIntent);
It is still not working at all and I don't know what my mistake is..
Here my code:
public class AlarmManagerBroadcastReceiver extends WakefulBroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
mContext = context;
PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "YOUR TAG");
//Acquire the lock
wl.acquire();
callback = new GPSActivityCallback() {...}
if(isConnectedToInternet()) {
gpsService = new GPSService(callback, context);
gpsService.refreshLocation();
Bundle extras = intent.getExtras();
StringBuilder msgStr = new StringBuilder();
if (extras != null && extras.getBoolean(REPEAT, Boolean.FALSE)) {
//Make sure this intent has been sent by the one-time timer button.
}
Format formatter = new SimpleDateFormat("hh:mm:ss a");
msgStr.append(formatter.format(new Date()));
}
else {
Toast.makeText(context, "Internetverbindung wurde unterbrochen", Toast.LENGTH_SHORT).show();
Log.d("INTERNET_TAG","Internetverbindung war kurrzeitig getrennt");
}
wl.release();
public void SetAlarm(Context context) {
AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(context, AlarmManagerBroadcastReceiver.class);
intent.putExtra(REPEAT, Boolean.FALSE);
PendingIntent pi = PendingIntent.getBroadcast(context, 0, intent, 0);
if(Build.VERSION.SDK_INT < 23){
if(Build.VERSION.SDK_INT >= 19){
am.setExact(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), pi);
}
else{
am.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), pi);
}
}
else{
am.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), pi);
}
am.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), 1000 * 10, pi);
}
public boolean isConnectedToInternet(){...}
}
This is my Manifest:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.nymvno.hiob.prototyp_v30">
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.WAKE_LOCK"/>
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:supportsRtl="true"
android:theme="#style/Theme.AppCompat">
<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="com.nymvno.hiob.prototyp_v30.AlarmManagerBroadcastReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
<action android:name="alarm" />
</intent-filter>
</receiver>
</application>
</manifest>
Related
I have an app developed in java whose function is to capture the location when the app is active, background, destroyed and when the phone restarts
I already managed to capture the location when the app is active, background and destroyed but I am trying to do it when the phone reboots and create the task to capture but it says that the task was configured well but it does not execute it every 1 minute
My Manifest
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.example.rutas">
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.WAKE_LOCK"/>
<application
android:allowBackup="true"
android:dataExtractionRules="#xml/data_extraction_rules"
android:fullBackupContent="#xml/backup_rules"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="#style/Theme.Rutas"
tools:targetApi="31">
<activity
android:name=".MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service android:name=".MyForegroundServices"></service>
<receiver android:name=".MyBroadcastReceiver"
android:exported="false">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"></action>
</intent-filter>
</receiver>
</application>
</manifest>
My Receiver
public class MyBroadcastReceiver extends BroadcastReceiver {
GPSTracker gps;
Context alarmContext;
#Override
public void onReceive(Context context, Intent intent) {
Log.e("onReceive", " Init Receive" );
alarmContext = context;
gps = new GPSTracker(context);
double latitude = gps.getLatitude();
double longitude = gps.getLongitude();
Log.e("Location", "Lat: " + latitude + "\n Long: " + longitude);
if(intent.getAction() != null){
if(intent.getAction().equals(Intent.ACTION_BOOT_COMPLETED)){
Log.e("Boot Completed", "Boot Completed");
setAlarmOnBoot();
Intent serviceIntent = new Intent(context, MyForegroundServices.class);
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O){
context.startForegroundService(serviceIntent);
}else{
context.startService(serviceIntent);
}
}
}
}
public void setAlarmOnBoot(){
Log.e("Alarm Boot", "Initialize task");
try{
AlarmManager alarm = (AlarmManager) alarmContext.getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(alarmContext, MyBroadcastReceiver.class);
PendingIntent pIntent = PendingIntent.getBroadcast(alarmContext, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
alarm.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, System.currentTimeMillis(), 1000*60*1, pIntent);
Log.e("Success", "Alarm has been configured successfully");
} catch (Exception ex){
Log.e("Failed Try Receiver", ex.getMessage());
}
}
}
I am testing the app on a samsung A13 with android 12
I have some trouble ring an alarm on android-studio app. First, I have a method, called with a button ( onClick), then I create alarmManager in this, and try to call a class AlarmReceiver to ring the alarm. The problem is that the program running never go in my AlarmReceiver class, and I don't understand why. Let me show you the code:
public void sendMessage(View v) {
long time = currentTimeMillis();
Toast.makeText(this, "ALARM ON", Toast.LENGTH_SHORT).show();
alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(MainActivity.this, AlarmReceiver.class);
pendingIntent = PendingIntent.getBroadcast(this, 0, intent, 0);
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.set(Calendar.HOUR_OF_DAY, 14);
calendar.set(Calendar.MINUTE, 58);
Toast.makeText(MainActivity.this, "bjr", Toast.LENGTH_SHORT).show();
alarmManager.set(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(),pendingIntent);}
This is the method called when click on button, and now this is the AlarmReceiver:
public class AlarmReceiver extends WakefulBroadcastReceiver
{
#Override
public void onReceive(Context context, Intent intent)
{
Toast.makeText(context, "Alarm! Wake up! Wake up!", Toast.LENGTH_LONG).show();
Uri alarmUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_ALARM);
if (alarmUri == null)
{
alarmUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
}
Ringtone ringtone = RingtoneManager.getRingtone(context, alarmUri);
ringtone.play();
}
}
So, when I run the app, then click on button, the word " ALARM ON" and "bjr" is printed, but the text so in AlarmReceiver "Alarm! Wake up!" Is never printed, so the app never go in this class, I need to know why.
My android manifest :
`<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.beantunes.myapplication">
<uses-feature
android:name="android.hardware.sensor.accelerometer"
android:required="true"/>
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
<uses-permission android:name="android.permission.WAKE_LOCK" />
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity android:name=".vue.MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver android:name=".vue.AlarmReceiver"
android:enabled="false">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"></action>
</intent-filter>
</receiver>
<activity android:name=".vue.DisplayMessageActivity"></activity>
</application>
`
I have looked at several questions on this site and none seem to be able to answer my question so hopefully someone can help with this. Currently for some reason when I send a message through from the PHP Website, my app doesn't receive the message. I have tried placing Log.d's in the lines of code but it doesn't appear as well. Can someone help to see if something has gone wrong?
[UPDATE] This is the result when I send from the php website
{"multicast_id":5610818169388245295,"success":1,"failure":0,"canonical_ids":0,"results":[{"message_id":"0:1460536959734990%40ad5721f9fd7ecd"}]}
My manifest
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.amosang.pushtest" >
<!-- GCM Permissions - Start here -->
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<permission
android:name="com.example.amosang.pushtest.permission.C2D_MESSAGE"
android:protectionLevel="signature" />
<uses-permission android:name="com.example.amosang.pushtest.permission.C2D_MESSAGE" />
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity
android:name=".MainActivity"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".HomeActivity"
android:label="#string/title_activity_home" >
</activity>
</application>
<receiver
android:name=".GCMBroadcastReceiver"
android:enabled="true"
android:exported="true"
android:permission="com.google.android.c2dm.permission.SEND" >
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
<category android:name="com.example.amosang.pushtest" />
</intent-filter>
</receiver>
<service android:name=".GCMNotificationIntentService">
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
</service>
</manifest>
My Broadcast Receiver
public class GCMBroadcastReceiver extends WakefulBroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
ComponentName comp = new ComponentName(context.getPackageName(), GCMNotificationIntentService.class.getName());
startWakefulService(context, (intent.setComponent(comp)));
Log.d("TESTTEST", "TEST");
setResultCode(Activity.RESULT_OK);
}
}
My intent service
public class GCMNotificationIntentService extends IntentService{
//set ID for the notification, so it can be updated
public static final int notifyID = 9001;
NotificationCompat.Builder builder;
public GCMNotificationIntentService() {
super("GCM Intent Service");
}
#Override
protected void onHandleIntent(Intent intent) {
Bundle extras = intent.getExtras();
GoogleCloudMessaging gcm = GoogleCloudMessaging.getInstance(this);
String messageType = gcm.getMessageType(intent);
Log.d("RECEIVEDMESSAGE", messageType);
if (!extras.isEmpty()) {
if (GoogleCloudMessaging.MESSAGE_TYPE_SEND_ERROR
.equals(messageType)) {
sendNotification("Send error: " + extras.toString());
} else if (GoogleCloudMessaging.MESSAGE_TYPE_DELETED
.equals(messageType)) {
sendNotification("Deleted messages on server: "
+ extras.toString());
} else if (GoogleCloudMessaging.MESSAGE_TYPE_MESSAGE
.equals(messageType)) {
sendNotification("Message Received from Google GCM Server:nn"
+ extras.get(AppConstants.MSG_KEY));
}
}
GCMBroadcastReceiver.completeWakefulIntent(intent);
}
private void sendNotification(String msg){
Intent resultIntent = new Intent(this, HomeActivity.class);
Log.d("RECEIVEDPT2",msg);
resultIntent.putExtra("msg", msg);
PendingIntent resultPendingIntent = PendingIntent.getActivity(this,0,resultIntent,PendingIntent.FLAG_ONE_SHOT);
NotificationCompat.Builder mNotifyBuilder;
NotificationManager mNotificationManager;
mNotificationManager = (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);
mNotifyBuilder = new NotificationCompat.Builder(this).setContentTitle("Alert")
.setContentTitle("You've received a new message");
//Set pending intent
mNotifyBuilder.setContentIntent(resultPendingIntent);
//Set vibration
int defaults = 0;
defaults = defaults | Notification.DEFAULT_LIGHTS;
defaults = defaults | Notification.DEFAULT_VIBRATE;
defaults = defaults | Notification.DEFAULT_SOUND;
mNotifyBuilder.setDefaults(defaults);
// Set the content for Notification
mNotifyBuilder.setContentText("You have new notifications");
// Set autocancel
mNotifyBuilder.setAutoCancel(true);
// Post a notification
mNotificationManager.notify(notifyID, mNotifyBuilder.build());
}
}
Please help.
I seem to be having trouble getting my onReceive class receive any broadcasts I send out. Im not sure if its my code thats the problem or its a problem with the Android Manifest.
public class AlarmReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Log.i("BROADCAST_RECEIVED", intent.getDataString());
PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
PowerManager.WakeLock wakeLock = pm.newWakeLock(PowerManager.ACQUIRE_CAUSES_WAKEUP, "");
wakeLock.acquire();
wakeLock.release();
context.startActivity(intent);
}
}
public void setDayOfWeekAlarm(DayOfWeek day){
long alarmInMili = 0;
Intent intent = new Intent(context,AlarmScreenActivity.class);
alarmInMili = System.currentTimeMillis() + 1000*10;
Log.i("REGISTER ALARM", String.valueOf(alarmInMili));
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
PendingIntent pi = PendingIntent.getBroadcast(context, 0, intent, 0);
alarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,SystemClock.elapsedRealtime() +
10 * 1000,pi);
}
AndroidManifest
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.brianlindsey.alarm"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="18"
android:targetSdkVersion="18" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<receiver
android:name="com.brianlindsey.AlarmReceiver"
android:enabled="true" >
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" >
</action>
</intent-filter>
</receiver>
</application>
</manifest>
In addition to Gabe's answer, the Intent that you are using in setDayOfWeekAlarm() points to AlarmScreenActivity. That is not your BroadcastReceiver, nor is it any other component registered in your manifest.
BOOT_COMPLETED receivers cannot recieve a broadcast until an activity in the apk has been launched at least once. Its a weird rule google added to prevent people from downloading an app by mistake and having it run at boot.
My service don't start on system boot, only when the user press the refresh button. I've tried everythng searched in stack but nothing i've rewrited my code 4 times and nothing, i want my service run in a time interval and when the refresh button is pressed, i canĀ“t understand why is not running on boot, Have i missed something?
Manifest.xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.moody"
android:installLocation="internalOnly"
android:versionCode="0"
android:versionName="0.6.7.2 alpha" >
<permission
android:name="com.android.moody.permission.GET_SERVER_DATA"
android:protectionLevel="normal" />
<uses-sdk
android:maxSdkVersion="18"
android:minSdkVersion="14"
android:targetSdkVersion="17" />
<uses-permission android:name="com.android.moody.permission.GET_SERVER_DATA" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<application
android:allowBackup="true"
android:allowClearUserData="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity
android:name="activities.MainActivity"
android:label="#string/app_name" >
</activity>
<activity
android:name="activities.Menu_esq"
android:label="#string/title_activity_menu_esq" >
</activity>
<activity
android:name="activities.BaseActivity"
android:label="#string/title_activity_base" >
</activity>
<activity
android:name="activities.MainView"
android:label="#string/title_activity_main_view" >
</activity>
<activity
android:name="activities.LoginActivity"
android:label="#string/app_name"
android:noHistory="true"
android:windowSoftInputMode="adjustResize|stateVisible" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name="com.example.moody.LeftActivity"
android:label="#string/title_activity_left" >
</activity>
<activity
android:name="com.example.moody.RightActivity"
android:label="#string/title_activity_right" >
</activity>
<activity
android:name="activities.UserDetailsActivity"
android:label="#string/title_activity_user_details" >
</activity>
<activity
android:name="fragments.FragTopicsPreview"
android:label="#string/title_activity_copy_of_topics_preview" >
</activity>
<activity android:name="activities.LoadingActivity" >
</activity>
<service
android:name="service.ServiceBackground"
android:enabled="true"
android:icon="#drawable/ic_launcher"
android:label="#string/moody_service" >
</service>
<receiver android:name="service.Alarm" >
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
<receiver
android:name="service.StartServiceReceiver"
android:permission="com.android.moody.permission.GET_SERVER_DATA" >
<intent-filter>
<action android:name="moody_get_data" />
</intent-filter>
</receiver>
</application>
ServiceBackground
public class ServiceBackground extends Service {
Alarm alarm = new Alarm();
public ServiceBackground() {
// TODO Auto-generated constructor stub
}
private boolean isRunning = false;
Object getContent;
#Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
#Override
public void onCreate() {
super.onCreate();
// android.os.Debug.waitForDebugger();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
super.onStartCommand(intent, flags, startId);
// Starts the alarm
alarm.setAlarm(getApplicationContext());
// Announcement about starting
Log.d("service", "Service Started");
// Start a Background thread
isRunning = true;
Thread backgroundThread = new Thread(new BackgroundThread());
backgroundThread.start();
return START_NOT_STICKY;
}
#Override
public void onDestroy() {
super.onDestroy();
// Stop the Background thread
isRunning = false;
}
private class BackgroundThread implements Runnable {
public void run() {
try {
while (isRunning) {
Log.d("service", "Thread started");
new ManContents().getAll(getResources(),
getApplicationContext());
isRunning = false;
}
stopSelf();
} catch (Exception e) {
e.printStackTrace();
}
}
}
Alarm
public class Alarm extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
context.startService(new Intent(context, ServiceBackground.class));
}
public void setAlarm(Context context) {
String alarm = Context.ALARM_SERVICE;
AlarmManager am = (AlarmManager) context.getSystemService(alarm);
Intent intent = new Intent("moody_get_data");
PendingIntent pi = PendingIntent.getBroadcast(context, 0, intent, 0);
int type = AlarmManager.ELAPSED_REALTIME_WAKEUP;
// long interval = AlarmManager.INTERVAL_FIFTEEN_MINUTES;
long interval = 1000 * 60 * 2;
long triggerTime = SystemClock.elapsedRealtime() + interval;
am.setRepeating(type, triggerTime, interval, pi);
}
public void CancelAlarm(Context context) {
Intent intent = new Intent(context, Alarm.class);
PendingIntent sender = PendingIntent
.getBroadcast(context, 0, intent, 0);
AlarmManager alarmManager = (AlarmManager) context
.getSystemService(Context.ALARM_SERVICE);
alarmManager.cancel(sender);
}
}
StartServiceReceiver
public class StartServiceReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Log.d("service", "Starting service from serviceReceiver");
Intent service = new Intent(context, ServiceBackground.class);
context.startService(service);
}
}
NOTES:
i already tried starting the service directly without filters, but
for no reason don't start, so with filters was the only way that
worked.
I also tried without the StartServiceReceiver.java, with the intent inside the alarm but no luck, i can change the code again if somebody thinks that its the problem.
I've the while(isRunning) in the thread only for future purpose, but i think the problem it's not because this.
Compared with one of my implementations, there're small differences in the manifest:
used permissions (seems to be equal with yours
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
The Receiver
<receiver
android:name="com.<!your activity!>"
android:permission="android.permission.RECEIVE_BOOT_COMPLETED" >
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
Yoiu see that there's an additional entry about the permission.