Android alarmManager, BroadcastReceiver onReceive never called - java

I'm trying to set up a alarm to start a job on a certain time but my alarm is never trigger and I don't understand what i'm missing. I'm using android api 22.
Thank you.
public class MainActivity extends ProtectedActivity {
#Override
public void onResume() {
super.onResume();
if (terminalSettings.GetSettlementEnabled())
{
startAlarmManager();
}
}
private void startAlarmManager()
{
Intent i = new Intent(MainActivity.this,
AlarmBroadcastReceiver.class);
PendingIntent pi = PendingIntent.getBroadcast(MainActivity.this, 0,
i, 0);
AlarmManager am =( AlarmManager)getSystemService(ALARM_SERVICE);
am.set(AlarmManager.RTC, System.currentTimeMillis() + 1000, pi); //
Millisec * Second * Minute
}
}
class AlarmBroadcastReceiver
public class AlarmBroadcastReceiver extends BroadcastReceiver {
public AlarmBroadcastReceiver() {
super();
}
#Override
public void onReceive(Context context, Intent intent)
{
Toast.makeText(context, "Alarm !!!!!!!!!!",
Toast.LENGTH_LONG).show(); // For example
}
}
In the manifest I added those line
<receiver android:name=".AlarmBroadcastReceiver"></receiver>
<uses-permission android:name="android.permission.WAKE_LOCK"></uses-permission>

You need to call registerReceiver
public static final String Broadcast_PLAY_NEW_AUDIO = "Some key so you know which broadcast is which";
//Create Receiver
private BroadcastReceiver receiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
//Do stuff
}
};
//Register receiver
IntentFilter filter = new IntentFilter(HomeActivity.Broadcast_PLAY_NEW_AUDIO);
registerReceiver(receiver, filter);
//Send Broadcast
Intent broadcastIntent = new Intent(Broadcast_PLAY_NEW_AUDIO);
sendBroadcast(broadcastIntent);

Related

Why does the UI stop updating countdown after restarting the app while using intent service?

I am trying to show a countdown in a textview from a loop inside an Intent Service. I am using the result receiver class for the communication between Intent Service and Activity. It works fine when I start the service for the first time. The textview shows the countdown for each time the loop runs in the service.
But when I close and launch the app again the textview doesn't show the countdown and only shows the hard coded text, while on the other hand the service stills runs in the background.
Here is my code snippet for the MainActivity
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
public static final String RECEIVER_INTENT_EXTRA_NAME = "message_receiver_intent_extra";
private static final String TAG = "MainActivity";
private Intent intent;
MyIntentService myIntentService;
public TextView serviceCountdown;
private Button startButton, stopButton;
private Handler handler;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
getSupportActionBar().hide();
myIntentService = new MyIntentService();
startButton = findViewById(R.id.startServiceButton);
stopButton = findViewById(R.id.stopServiceButton);
startButton.setOnClickListener(this);
stopButton.setOnClickListener(this);
handler = new Handler();
serviceCountdown = findViewById(R.id.serviceCountdown);
MessageReceiver messageReceiver = new MessageReceiver(handler);
// send intent service
intent = new Intent(this, MyIntentService.class);
intent.putExtra(RECEIVER_INTENT_EXTRA_NAME, messageReceiver);
}
#Override
public void onClick(View v) {
if (startButton.equals(v)) {
ContextCompat.startForegroundService(getApplicationContext(), intent);
}
if (stopButton.equals(v)){
stopService(intent);
}
}
public class MessageReceiver extends ResultReceiver {
public MessageReceiver(Handler handler) {
super(handler);
}
#Override
protected void onReceiveResult(int resultCode, Bundle resultData) {
super.onReceiveResult(resultCode, resultData);
if (resultCode == 1 && resultData != null){
final String countdown = resultData.getString("countdown");
handler.post(new Runnable() {
#Override
public void run() {
serviceCountdown.setText(countdown);
}
});
}
}
}
}
And here is my code for the Intent Service Class
public class MyIntentService extends IntentService {
private static final String CHANNEL_ID = "my_channel_id";
private static final String TAG = "MyIntentService";
public MyIntentService() {
super("MyIntentService");
setIntentRedelivery(true);
}
#Override
public void onCreate() {
super.onCreate();
Intent notificationIntent = new Intent(this, MainActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent,0);
Notification notification = new NotificationCompat.Builder(this, CHANNEL_ID)
.setContentTitle("My Service Title")
.setContentText("This is sample notification text")
.setSmallIcon(R.drawable.ic_battery)
.setContentIntent(pendingIntent)
.build();
startForeground(1, notification);
}
#Override
protected void onHandleIntent(#Nullable Intent intent) {
ResultReceiver resultReceiver = intent.getParcelableExtra(MainActivity.RECEIVER_INTENT_EXTRA_NAME);
Log.d(TAG, "onHandleIntent: called");
synchronized (this) {
for (int i = 10; i >= 0; i--) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
Log.d(TAG, "Service is looping : " + i);
Bundle bundle = new Bundle();
bundle.putString("countdown", String.valueOf(i));
resultReceiver.send(1, bundle);
}
}
}
#Override
public void onDestroy() {
Log.d(TAG, "onDestroy: called");
super.onDestroy();
}
}
In the real project, my intention is not to using the loop to show a countdown. It is just for testing and debugging purpose.
Use Local Broadcast Receiver from your service to activity. Now you getting the ResultReceiver from the MainActivity Intent. When the activity destroyed intents are also destroyed.
Use this Broadcast Receiver code in your service class.
LocalBroadcastManager localBroadcastManager =
LocalBroadcastManager.getInstance(this);
Intent sendIntent = new Intent(INTENT_ACTION_KEY);
sendIntent.putExtra(DATA_KEY, data);
localBroadcastManager.sendBroadcast(sendIntent);
Get this local broadcast receiver in your activity.
BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
if (intent != null) {
//Perform your logic.
}
}
};
Make sure you register this broadcast when activity starts and unregister it when stop.
#Override
public void onStart() {
super.onStart();
LocalBroadcastManager.getInstance(this).registerReceiver((broadcastReceiver),
new IntentFilter(INTENT_ACTION_KEY));
}
#Override
public void onStop() {
LocalBroadcastManager.getInstance(this).unregisterReceiver(broadcastReceiver);
super.onStop();
}

Register Alarm Receiver

I try to register a broadcast receiver in my mainActivity (because I must have non static receiver in order to call a function of my mainActivity)
For the moment the receiver do not receive.... What should I do ?
mainActivity.java
public class mainActivity
{
private BroadcastReceiver alarm;
...
Intent startIntent = new Intent("WhatEverYouWant");
PendingIntent startPIntent = PendingIntent.getBroadcast(this, 0, startIntent, 0);
AlarmManager alarm = (AlarmManager) this.getSystemService(Context.ALARM_SERVICE);
alarm.set(AlarmManager.RTC_WAKEUP,System.currentTimeMillis() + 10000, startPIntent);
IntentFilter filter = new IntentFilter();
filter.addCategory(Intent.CATEGORY_DEFAULT);
this.alarm = new AlarmReceiver();
registerReceiver(this.alarm, filter);
}
public class AlarmReceiver extends BroadcastReceiver
{
public AlarmReceiver ()
{
}
public void onReceive(Context context, Intent intent)
{
doRestartApp();
}
}
The Intent must be have the same name as the IntentFilter...
Now it works !
public class mainActivity
{
private BroadcastReceiver alarm;
...
Intent startIntent = new Intent("MESSAGE_PROCESSED");
PendingIntent startPIntent = PendingIntent.getBroadcast(this, 0, startIntent, 0);
AlarmManager alarm = (AlarmManager) this.getSystemService(Context.ALARM_SERVICE);
alarm.set(AlarmManager.RTC_WAKEUP,System.currentTimeMillis() + 10000, startPIntent);
IntentFilter filter = new IntentFilter("MESSAGE_PROCESSED");
filter.addCategory(Intent.CATEGORY_DEFAULT);
this.alarm = new AlarmReceiver();
registerReceiver(this.alarm, filter);
}
public class AlarmReceiver extends BroadcastReceiver
{
public AlarmReceiver ()
{
}
public void onReceive(Context context, Intent intent)
{
doRestartApp();
}
}

cancelAlarm method not actually canceling my AlarmManager

I have used this cancelAlarm method from another reputable answer on stack, and it isn't getting the job done, and I am out of ideas of why this isn't working.
I have an activity where one button will start an alarm that will go off every given interval. I then have another button that will cancel that alarm. Here are the buttons first:
start.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
setupAlarm(10);
}
});
stop.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
try{
cancelAlarm(ALARM_ID);
} catch(Exception e){
Toast.makeText(getApplicationContext(), "ERROR", Toast.LENGTH_SHORT).show();
}
}
});
And here are my setupAlarm and cancelAlarm methods:
private void setupAlarm(int seconds) {
AlarmManager am = (AlarmManager)getSystemService(ALARM_SERVICE);
Intent i = new Intent(getBaseContext(), AlarmReceiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(
MainActivity.this, ALARM_ID, i, PendingIntent.FLAG_UPDATE_CURRENT);
Calendar t = Calendar.getInstance();
t.setTimeInMillis(System.currentTimeMillis());
int interval = seconds*1000;
am.setRepeating(AlarmManager.RTC_WAKEUP, t.getTimeInMillis(), interval, pendingIntent);
MainActivity.this.finish();
}
private void cancelAlarm(int alarmId){
Intent i = new Intent(getBaseContext(), AlarmManager.class);
PendingIntent sender = PendingIntent.getBroadcast(MainActivity.this, alarmId, i, 0);
AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
alarmManager.cancel(sender);
sender.cancel();
}
I remembered to make another alarm manager with the same ID, and call alarmManager.cancel(sender); on the PendingIntent but it doesn't seem to do anything, because my service will start back up anyway.
AlarmReciever class:
public class AlarmReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent)
{
Context oAppContext = context.getApplicationContext();
if (oAppContext == null) {
oAppContext = context;
}
Intent serviceIntent = new Intent(oAppContext, MyService.class);
oAppContext.startService(serviceIntent);
}
}
MyService class:
public class MyService extends Service implements SensorEventListener{
private PowerManager.WakeLock wakeLock;
Sensor mSensor;
SensorManager mSensorManager;
String toastString = "";
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate(){
mSensorManager = (SensorManager)getSystemService(SENSOR_SERVICE);
mSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
mSensorManager.registerListener(this, mSensor, SensorManager.SENSOR_DELAY_NORMAL);
PowerManager mgr = (PowerManager) getApplicationContext().getSystemService(Context.POWER_SERVICE);
wakeLock = mgr.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "MyWakeLock");
wakeLock.acquire();
Toast.makeText(this, "onCreate Successful", Toast.LENGTH_SHORT).show();
}
#Override
public int onStartCommand(Intent intent, int flags, int startid) {
Toast.makeText(this, "onStart Successful", Toast.LENGTH_SHORT).show();
return Service.START_STICKY;
}
#Override
public void onSensorChanged(SensorEvent event) {
//record some data from the accelerometer
quit();
}
#Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
private void quit(){
mSensorManager.unregisterListener(MyService.this);
wakeLock.release();
this.stopSelf();
}
}
And I keep on getting the toasts from my MyService class telling me that my onCreate and onStart were successfully instantiated, even after calling my cancelAlarm method.
Use same PendingIntent that you used while creating Alarm. Use AlarmReceiver.class instead of AlarmManager.class in your Intent:
Intent i = new Intent(getBaseContext(), AlarmReceiver.class);
Update cancelAlarm() method as below:
private void cancelAlarm(int alarmId){
Intent i = new Intent(getBaseContext(), AlarmReceiver.class);
PendingIntent sender = PendingIntent.getBroadcast(MainActivity.this, alarmId, i, PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
alarmManager.cancel(sender);
sender.cancel();
}
Hope this will help~

Android - Daily notification

I have this app which launches the function notifiy()in the NotificationService when ever device is started or when app is opened
my question is how I can make this notifiy() function be made on specific times daily for example at (12:00 AM, 3:00 AM) I searched for a while and all I saw is working with AlarmManager but I don't understand how to use it in my code
MainActivity
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
startService(new Intent(this,NotificationService.class));
BootReceiver
public class BootReceiver extends BroadcastReceiver{
#Override
public void onReceive(Context context, Intent intent) {
context.startService(new Intent(context,NotificationService.class));
}
}
NotificationService
public class NotificationService extends Service {
private MediaPlayer mediaPlayer;
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
super.onCreate();
notifiy();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
try {
}catch (Exception e){
e.printStackTrace();
}
return super.onStartCommand(intent, flags, startId);
}
#Override
public void onDestroy() {
try {
}catch (Exception e){
e.printStackTrace();
}
Intent intent=new Intent("com.company.app");
intent.putExtra("yourvalue","torestore");
sendBroadcast(intent);
}
public void notifiy(){
IntentFilter intentFilter=new IntentFilter();
intentFilter.addAction("RSSPullService");
Intent mIntent=new Intent(Intent.ACTION_VIEW, Uri.parse(""));
PendingIntent pendingIntent=PendingIntent.getActivity(getBaseContext(),0,mIntent,Intent.FLAG_ACTIVITY_NEW_TASK);
Context context=getApplicationContext();
Notification.Builder builder;
builder=new Notification.Builder(context)
.setContentTitle(title)
.setContentText("")
.setContentIntent(pendingIntent)
.setDefaults(Notification.DEFAULT_SOUND)
.setAutoCancel(true)
.setSmallIcon(R.drawable.images);
Notification notification=builder.build();
NotificationManager notificationManager=(NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(1,notification);
mediaPlayer = MediaPlayer.create(this, R.raw.msound);
mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mp) {
mediaPlayer.start();
}
});
}
}
1. If you want to set alarm after launching app then you can add below codes in your MainActivity's onCreate() method:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Schedule Date & time
Calendar target = Calendar.getInstance();
target.set(2017, 5, 3, 12, 0, 0);
// Intent
Intent mIntent = new Intent(getApplicationContext(), AlarmReceiver.class);
mIntent.putExtra("MSG_ID", "SOME MESSAGE");
// Pending broadcast intent
PendingIntent mPI = PendingIntent.getBroadcast(getApplicationContext(), 0, mIntent, PendingIntent.FLAG_UPDATE_CURRENT);
// Alarm manager
AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
// Set alarm
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, target.getTimeInMillis(), AlarmManager.INTERVAL_DAY, mPI);
}
2. If you want to set alarm after boot completion, then you can add that code in BootReceiver's onReceive() method:
public class BootReceiver extends BroadcastReceiver{
#Override
public void onReceive(Context context, Intent intent) {
// Schedule Date & time
Calendar target = Calendar.getInstance();
target.set(2017, 5, 3, 12, 0, 0);
// Intent
Intent mIntent = new Intent(getApplicationContext(), AlarmReceiver.class);
mIntent.putExtra("MSG_ID", "SOME MESSAGE");
// Pending broadcast intent
PendingIntent mPI = PendingIntent.getBroadcast(getApplicationContext(), 0, mIntent, PendingIntent.FLAG_UPDATE_CURRENT);
// Alarm manager
AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
// Set alarm
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, target.getTimeInMillis(), AlarmManager.INTERVAL_DAY, mPI);
}
}
Here is AlarmReceiver class:
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
public class AlarmReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent)
{
context.startService(new Intent(context, NotificationService.class));
Log.d("AlarmReceiver", "Called ");
}
}
Declare AlarmReceiver class in AndroidManifest.xml:
<receiver
android:name="YOUR_PACKAGE.AlarmReceiver">
</receiver>

Android Broadcast receiver with multiple actions

How should I implement a broadcast receiver & filter so that it can response to multiple intents.
private BroadcastReceiver myReceiver;
IntentFilter myFilter = new IntentFilter();
onCreate():
myFilter.addAction("first");
myFilter.addAction("second");
myReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
// do different actions according to the intent
}
};
registerReceiver(myReceiver, myFilter);
from my fragment:
Intent i = new Intent("first"); sendBroadcast(i);
Intent i = new Intent("second"); sendBroadcast(i);
Thanks
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if(action != null) {
if(action.equals("action1") {
// CODE
} else if (action.equals("action2") {
// CODE
}
}
}

Categories

Resources