I want to call alarm in background with multiple arrayList items, in recyclerview. Alarm manager check in arrayList(Database) that when Date & Time of item match with current Date & Time, the alarm will be call and also send notification. This all work will be done in background.
But in my application when I refresh activity then alarm is calling otherwise it do not call in background. kindly Help me.
Thanks!
This is My my Fragment Class where I call Alarm:
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, Bundle savedInstanceState) {
v = inflater.inflate(R.layout.all_fragment,container,false);
recyclerView = (RecyclerView) v.findViewById(R.id.recyclerviewAll);
databaseHelper = new DatabaseHelper(getActivity());
loadDatabase();
setAlarm();
return v;
}
public void loadDatabase() {
LinearLayoutManager layoutManager = new LinearLayoutManager(getContext());
databaseHelper.ShowAll(arrayList);
adapter = new AllFragmentAdapter(getActivity(), arrayList);
adapter.setOnTapListner(new onTapListener() {
#Override
public void OnTapView(int position) {
Position = position;
// Toast.makeText(getContext(), "" + position, Toast.LENGTH_SHORT).show();
}
});
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(layoutManager);
recyclerView.setItemAnimator(new DefaultItemAnimator());
recyclerView.setAdapter(adapter);
adapter.notifyDataSetChanged();
adapter.notifyItemChanged(Position);
layoutManager.supportsPredictiveItemAnimations();
}
public void setAlarm() {
Calendar calendar1 = Calendar.getInstance();
SimpleDateFormat format, format2;
format2 = new SimpleDateFormat("dd-MM-yyyy HH:mm");
String currentTime = format2.format(calendar1.getTime());
String dbTimetoCompare = "";
Date date1;
long time1 = 0;
if (arrayList.size() > 0) {
for (int i = 0; i < arrayList.size(); i++) {
if (arrayList.get(i).getSchedule().equals("Schedule")) {
String date = arrayList.get(i).getDate();
String time = arrayList.get(i).getTime();
Name = arrayList.get(i).getName();
Detail = arrayList.get(i).getDetail();
String datetime = date + " " + time;
format = new SimpleDateFormat("dd-MM-yyyy HH:mm");
try {
date1 = (Date) format.parse(datetime);
dbTimetoCompare = format.format(date1.getTime());
time1 = date1.getTime();
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
alarmManager = (AlarmManager)getActivity().getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(getContext(), MyAlarm.class);
intent.putExtra("CTime", currentTime);
intent.putExtra("DBTime", dbTimetoCompare);
pendingIntent = PendingIntent.getBroadcast(getActivity(), j, intent, 0);
if (currentTime.equals(dbTimetoCompare)){
for (j = 0; j < 10; ++j) {
alarmManager.set(AlarmManager.RTC_WAKEUP, time1, pendingIntent);
}
Uri alert = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_ALARM);
Ringtone r = RingtoneManager.getRingtone(getContext(), alert);
if (r == null) {
alert = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
r = RingtoneManager.getRingtone(getContext(), alert);
if (r == null) {
alert = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_RINGTONE);
r = RingtoneManager.getRingtone(getContext(), alert);
}
}
if (r != null)
r.play();
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(getContext());
mBuilder.setSmallIcon(R.drawable.ic_notifications_black_24dp);
mBuilder.setContentTitle("Notification Alert");
mBuilder.setContentText("Name: " + Name + " Detail: " + Detail);
NotificationManager manager = (NotificationManager) getContext().getSystemService(Context.NOTIFICATION_SERVICE);
manager.notify(j, mBuilder.build());
Toast.makeText(getContext(), "Alarm Called", Toast.LENGTH_SHORT).show();
}
if (alarmManager != null) {
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(),
1000 * 60 * 5, pendingIntent);
intentArray.add(pendingIntent);
}
} catch (ParseException e) {
Toast.makeText(getContext(), "" + e, Toast.LENGTH_SHORT).show();
}
}
}
}
}
This is my broadcast Class:
public class MyAlarm extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
}
}
Create a new service which triggers the broadcast receiver.
public class AlarmService extends Service {
AlarmManager alarmManager;
#Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
//throw new UnsupportedOperationException("Not yet implemented");
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
//return super.onStartCommand(intent, flags, startId);
alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
long intervalSpan = 2 * 60 * 1000; // set the interval span as your requirement
Calendar calendar = Calendar.getInstance();
Intent intentAlarm = new Intent(this, AlarmBroadCastReceiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, intentAlarm, 0);
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), intervalSpan, pendingIntent);
return START_STICKY;
}
#Override
public void onDestroy() {
super.onDestroy();
Intent intentAlarm = new Intent(this, AlarmBroadCastReceiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, intentAlarm, 0);
alarmManager.cancel(pendingIntent);
}
}
In menifest file with application tag declare the service and your broadcast receiver
<service
android:name="AlarmService"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</service>
<receiver android:name=".receiver.AlarmBroadCastReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
on any click listener you can start the service as
startService(Intent(this#AlarmActivity, AlarmService::class.java))
I hope you have implemented your broadcast receiver so I am not implementing the broadcast receiver here. Now either you can check the condition inside broadcast receiver to trigger the alarm. When the condition is true just call the method to show notification.
Related
I have a service which captures the location of a user and updates database using retrofit. I want to stop the service automatically at 8 pm everyday if its running and also update the database that the user has punched out at 8 pm.
I want the service to start the manually but want the service to stop automatically if it is not stopped manually.
Here is my service class
public class LiveLocationService extends Service {
private static final String TAG = LiveLocationService.class.getSimpleName();
Retrofit retrofitClient;
CompositeDisposable compositeDisposable = new CompositeDisposable();
MyService myService;
String empCode, year, month, date;
FusedLocationProviderClient client;
LocationCallback locationCallback;
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
retrofitClient = RetrofitClient.getInstance();
myService = retrofitClient.create(MyService.class);
empCode = intent.getStringExtra("empCode");
year = intent.getStringExtra("year");
month = intent.getStringExtra("month");
date = intent.getStringExtra("date");
return super.onStartCommand(intent, flags, startId);
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
#RequiresApi(api = Build.VERSION_CODES.O)
#Override
public void onCreate() {
super.onCreate();
if (isOnline()) {
buildNotification();
requestLocationUpdates();
} else {
Log.e("MSER", "Please connect to the internet.");
}
}
private void buildNotification() {
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
String NOTIFICATION_CHANNEL_ID = "com.deepankmehta.managementservices";
String channelName = "My Background Service";
NotificationChannel chan = null;
chan = new NotificationChannel(NOTIFICATION_CHANNEL_ID, channelName, NotificationManager.IMPORTANCE_HIGH);
chan.setLightColor(Color.BLUE);
chan.setLockscreenVisibility(Notification.VISIBILITY_PRIVATE);
NotificationManager manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
assert manager != null;
manager.createNotificationChannel(chan);
PendingIntent intent = PendingIntent.getActivity(this, 0, new Intent(this, MainActivity.class), PendingIntent.FLAG_UPDATE_CURRENT);
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this, NOTIFICATION_CHANNEL_ID);
Notification notification = notificationBuilder.setOngoing(true)
.setSmallIcon(R.drawable.mser)
.setContentTitle("xxxx")
.setContentText("xxxx is tracking your location.")
.setPriority(NotificationManager.IMPORTANCE_HIGH)
.setCategory(Notification.CATEGORY_SERVICE)
.setContentIntent(intent)
.build();
startForeground(2, notification);
} else {
PendingIntent broadcastIntent = PendingIntent.getActivity(
this, 0, new Intent(this, MainActivity.class), PendingIntent.FLAG_UPDATE_CURRENT);
// Create the persistent notification
NotificationCompat.Builder builder = new NotificationCompat.Builder(this)
.setContentTitle(getString(R.string.app_name))
.setContentText("xxxx is tracking your location.")
.setOngoing(true)
.setContentIntent(broadcastIntent)
.setSmallIcon(R.drawable.mser);
startForeground(1, builder.build());
}
}
private void requestLocationUpdates() {
if (isOnline()) {
LocationRequest request = new LocationRequest();
request.setInterval(10000);
request.setFastestInterval(5000);
request.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
client = LocationServices.getFusedLocationProviderClient(this);
int permission = ContextCompat.checkSelfPermission(this,
Manifest.permission.ACCESS_FINE_LOCATION);
if (permission == PackageManager.PERMISSION_GRANTED) {
locationCallback = new LocationCallback() {
#Override
public void onLocationResult(LocationResult locationResult) {
Location location = locationResult.getLastLocation();
if (location != null) {
Log.d(TAG, "location update " + location);
double lat = location.getLatitude();
double lon = location.getLongitude();
final String time = new SimpleDateFormat("HH:mm", Locale.getDefault()).format(new Date());
compositeDisposable.add(myService.userLocation(empCode, year, month, date, time, lat, lon)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Consumer< String >() {
#Override
public void accept(String s) throws Exception {
Log.e("data", s);
if (s.equals("\"done\"")) {
Log.e("status", "location punched");
}
}
}));
} else {
Log.d("MSER", "location update, no location found. ");
}
}
};
client.requestLocationUpdates(request, locationCallback, null);
} else {
Log.e("MSER", "Please enable location.");
}
} else {
Log.e("MSER", "Please connect to the internet.");
}
}
#Override
public void onDestroy() {
super.onDestroy();
client.removeLocationUpdates(locationCallback);
stopForeground(true);
stopSelf();
}
protected boolean isOnline() {
ConnectivityManager cm = (ConnectivityManager)getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo netInfo = cm.getActiveNetworkInfo();
if (netInfo != null && netInfo.isConnectedOrConnecting()) {
return true;
} else {
return false;
}
}
}
Here is home activity class start service and stop service methods. These methods are called when the user clicks on punch in and punch out buttons respectively.
private void startTrackerService() {
final String date = new SimpleDateFormat("yyyy-MM-dd", Locale.getDefault()).format(new Date());
final String year = date.substring(0, 4);
final String month = date.substring(5, 7);
final String dateToday = date.substring(8, 10);
Intent intent = new Intent(this, LiveLocationService.class);
intent.putExtra("empCode", empCode);
intent.putExtra("year", year);
intent.putExtra("month", month);
intent.putExtra("date", dateToday);
startService(intent);
}
private void stopTrackerService() {
stopService(new Intent(this, LiveLocationService.class));
}
You can use AlarmManager to schedule this kind of the task,
Register AlaramManger at specific time and check whether service is running, if it is running then stop service.
Here is the example of registering AlaramManager at specific time
AlarmManager alarmManager = (AlarmManager) getActivityContext()
.getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(getActivityContext(), AutoStopReceiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(getActivityContext(),
0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP,
stopServieTime, pendingIntent);
Here is the Receiver Class,
public class AutoStopReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
//TODO Stop service from here
}
Register receiver in AndroidMenifest.xml
<receiver android:name=".AutoStopReceiver" />
I have alarm manager . when user click on add button , user select time , date and fill title and other ... and after this . I save this into database and show this values into recycle view .
I get values and save them into database like this :
saveAlarm.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
final String mTitle = title.getText().toString();
final String mDate = date;
final String mTime = time;
final String mRepeat = getrepeat.getText().toString();
final String mReport = single_choice_selected_report_as;
if (isAnyStringNullOrEmpty(mTitle, mDate, mTime, mRepeat, mReport)) {
Snackbar snackbar = Snackbar.make(mainLayout, "", Snackbar.LENGTH_LONG);
Snackbar.SnackbarLayout layout = (Snackbar.SnackbarLayout) snackbar.getView();
TextView textView = (TextView) layout.findViewById(com.google.android.material.R.id.snackbar_text);
textView.setVisibility(View.INVISIBLE);
View snackView = LayoutInflater.from(SetAlarmActivity.this).inflate(R.layout.custom_toast, null, false);
TextView txtNoticToExit = (TextView) snackView.findViewById(R.id.txtCustomToast);
txtNoticToExit.setText(getResources().getString(R.string.fill_field));
txtNoticToExit.setTypeface(Apps.font);
layout.setPadding(0, 0, 0, 0);
layout.addView(snackView, 0);
snackbar.show();
} else {
if (editMode) {
Alarm alarm = new Alarm(id, mTitle, mDate, mTime, mRepeat, mReport, active);
mDatabase.updateAlarm(alarm);
} else {
Alarm alarm = new Alarm(mTitle, mDate, mTime, mRepeat, mReport, 0);
mDatabase.addAlarm(alarm);
}
Intent intent = new Intent(SetAlarmActivity.this, AlarmActivity.class);
startActivity(intent);
SetAlarmActivity.this.finish();
}
}
In row of my recycle view I have a button to active this item to alarm base on the time .
holder.toggleButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
int test = alarm.getActive();
state = !state;
if (test == 0) {
holder.toggleButton.setBackgroundResource(R.drawable.on);
holder.row.setBackgroundResource(R.drawable.purple_row);
holder.reminderCalenderRow.setTextColor(context.getResources().getColor(R.color.white));
holder.reminderTitleRow.setTextColor(context.getResources().getColor(R.color.white));
holder.showCalenderRow.setTextColor(context.getResources().getColor(R.color.white));
holder.showTimeRow.setTextColor(context.getResources().getColor(R.color.white));
holder.reminderCalenderRow.setTextColor(context.getResources().getColor(R.color.white));
holder.reminderTimeRow.setTextColor(context.getResources().getColor(R.color.white));
Drawable myDrawable = context.getResources().getDrawable(R.drawable.menu_icon);
holder.popUp_menu.setBackground(myDrawable);
alarm.setActive(1);
String strTime = alarm.getTime();
String[] timeRemoveSpace = strTime.split(" ");
String[] splitTime = timeRemoveSpace[0].split(":");
hour = getHour(strTime);
mintue = Integer.parseInt(splitTime[1]);
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.set(Calendar.HOUR_OF_DAY, hour);
calendar.set(Calendar.MINUTE, mintue);
calendar.set(Calendar.SECOND, 00);
Long date = calendar.getTimeInMillis();
StartAlarm(alarm.getId(), alarm, date);
} else {
holder.row.setBackgroundResource(R.drawable.white_row);
holder.reminderTitleRow.setTextColor(context.getResources().getColor(R.color.colorBlack));
holder.showCalenderRow.setTextColor(context.getResources().getColor(R.color.colorBlack));
holder.showTimeRow.setTextColor(context.getResources().getColor(R.color.colorBlack));
holder.reminderCalenderRow.setTextColor(context.getResources().getColor(R.color.colorBlack));
holder.reminderTimeRow.setTextColor(context.getResources().getColor(R.color.colorBlack));
Drawable myDrawable = context.getResources().getDrawable(R.drawable.menu_icon_black);
holder.popUp_menu.setBackground(myDrawable);
alarm.setActive(0);
}
mDatabase.updateActive(state, alarm.getId());
notifyDataSetChanged();
}
});
and send intent into broatcast :
public void StartAlarm(int id, Alarm alarm, Long time) {
Intent intent = new Intent(context, MyReceiver.class);
intent.setAction("com.nooshindroid.yastashir");
Bundle bundle = new Bundle();
bundle.putString(EXTRA_TITLE, alarm.getTitle());
bundle.putString(EXTRA_ALARM_DATE, alarm.getDate());
bundle.putString(EXTRA_REPORT, alarm.getReport());
bundle.putString(EXTRA_REPEAT, alarm.getRepeat());
intent.putExtras(bundle);
pendingIntent = PendingIntent.getBroadcast(context, id, intent, 0);
AlarmManager alarmManager = (AlarmManager) context.getSystemService(ALARM_SERVICE);
if ("بدون تکرار".equals(alarm.getRepeat())) {
Log.i("ShowMeTime", "111111");
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
alarmManager.setExact(AlarmManager.RTC_WAKEUP, time, pendingIntent);
Toast.makeText(context, "Alarm>kitkat", Toast.LENGTH_SHORT).show();
}
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
alarmManager.set(AlarmManager.RTC_WAKEUP, time, pendingIntent);
Toast.makeText(context, "Alarm<kitkat", Toast.LENGTH_SHORT).show();
}
} else {
Log.i("ShowMeTime", "222222");
switch (alarm.getRepeat()) {
case "هر ساعت":
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, time, AlarmManager.INTERVAL_HOUR, pendingIntent);
break;
case "هر روز":
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, time, AlarmManager.INTERVAL_DAY, pendingIntent);
break;
case "هر هفته":
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, time, AlarmManager.INTERVAL_DAY * 7, pendingIntent);
break;
case "هر ماه":
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, time, AlarmManager.INTERVAL_DAY * 30, pendingIntent);
break;
}
}
}
all thins is ok until I want to edit , Once I edit my values and all these repeat , broad cast show the old values .
this my Receiver :
public class MyReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
//and doing something
if (intent.getAction().equals("com.nooshindroid.yastashir")) {
String title = intent.getExtras().getString(EXTRA_TITLE);
Toast.makeText(context, "Its time!!!", Toast.LENGTH_SHORT).show();
Log.i("khhhhhhhhhhhhhhh", "Started >>>>>>>"+title);
}
}
}
Why this happen ? any help?
I've created a service which consult notes if they are in recicle bin, it have to run once a day but with handler I think it will drain too much battery, So I need you help How can I do a task once a day without drain battery or other thing that's not a handler ?
When the app is launched the NotesApplication is created and start the NotesService class, it should be executing all day but it will drain battery, so I need to execute once a day
NotesApplication
public class NotesApplication extends Application {
String TAG = "NotesApplication";
Intent intent;
#Override
public void onCreate() {
// TODO: Implement this method
super.onCreate();
Log.d(TAG, "Application created");
intent = new Intent(getApplicationContext(), NotesService.class);
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O){
Log.d(TAG, "Foreground service started");
getApplicationContext().startForegroundService(intent);
}else if(Build.VERSION.SDK_INT < Build.VERSION_CODES.O){
Log.d(TAG, "Service started");
getApplicationContext().startService(intent);
}
}
Notes Service
public class NotesService extends Service {
ArrayList<Notes> listNotas;
String TAG = "NotesService";
SQLiteHelperConnection conn;
#Override
public void onCreate()
{
// TODO: Implement this method
super.onCreate();
Log.d(TAG, "Notes service created");
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O){
final NotificationManager mNotific= (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);
CharSequence name = "Axco";
String description = "Service";
int importance = NotificationManager.IMPORTANCE_MIN;
final String ChannelID="Service Channel";
NotificationChannel mChannel = new NotificationChannel(ChannelID, name, importance);
mChannel.setDescription(description);
mChannel.setLightColor(ThemeClass.getColor());
mChannel.canShowBadge();
mChannel.setShowBadge(true);
mNotific.createNotificationChannel(mChannel);
final int code = 101;
String body= "Service Running";
Notification notification = new Notification.Builder(this, ChannelID)
.setContentTitle(getPackageName())
.setContentText(body)
.setBadgeIconType(R.drawable.ic_launcher)
.setNumber(1)
.setSmallIcon(R.drawable.ic_launcher)
.setAutoCancel(true)
.build();
startForeground(code, notification);
}
conn = new SQLiteHelperConnection(this, "db_notas.db", null, 1);
listNotas = new ArrayList<Notes>();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId)
{
// TODO: Implement this method
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O){
final NotificationManager mNotific= (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);
CharSequence name = "Axco";
String description = "Service";
int importance = NotificationManager.IMPORTANCE_MIN;
final String ChannelID="Service Channel";
NotificationChannel mChannel = new NotificationChannel(ChannelID, name, importance);
mChannel.setDescription(description);
mChannel.setLightColor(ThemeClass.getColor());
mChannel.canShowBadge();
mChannel.setShowBadge(true);
mNotific.createNotificationChannel(mChannel);
final int code = 101;
String body= "Service Running";
Notification notification = new Notification.Builder(this, ChannelID)
.setContentTitle(getPackageName())
.setContentText(body)
.setBadgeIconType(R.drawable.ic_launcher)
.setNumber(1)
.setSmallIcon(R.drawable.ic_launcher)
.setAutoCancel(true)
.build();
startForeground(code, notification);
}
final Handler handler = new Handler();
Runnable runnable = new Runnable(){
#Override
public void run()
{
// TODO: Implement this method
Log.d(TAG, "Service running");
listNotas.clear();
consult();
check();
handler.postDelayed(this, 15000);
}
};
handler.post(runnable);
return Service.START_STICKY;
}
private void consult(){
Log.d(TAG, "Consulting...");
SQLiteDatabase db = conn.getReadableDatabase();
Notes notas = null;
Cursor cursor = db.rawQuery("SELECT * FROM "+Utilities.TABLA_NOTA, null);
while (cursor.moveToNext()) {
notas = new Notes();
notas.setId(cursor.getString(0));
notas.setLastModified(cursor.getString(5));
notas.setLastModifiedDate(cursor.getString(7));
boolean a = Boolean.valueOf(cursor.getString(4));
if(a){
listNotas.add(notas);
}
}
}
private void check(){
//Do something
}
private void deleteNote(int position){
SQLiteDatabase db = conn.getWritableDatabase();
String[] parametros = {listNotas.get(position).getId()};
db.delete(Utilities.TABLA_NOTA, Utilities.ID+"=?", parametros);
listNotas.remove(position);
}
#Override
public IBinder onBind(Intent p1){
// TODO: Implement this method
return null;
}
Using Alarm Manager is efficient.
See implementation
AlarmManager am=(AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
Intent i= new Intent(context, AlarmManagerBroadcastReceiver.class);
//intent.putExtra(something you want to put);
PendingIntent pi = PendingIntent.getBroadcast(context, 0, i, 0);
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
// check if it is more than 11 am. if so set alarm for next day
if (Calendar.getInstance().get(Calendar.HOUR_OF_DAY)) {
calendar.add(Calendar.DAY_OF_YEAR, 1);
}
// everyday at 11 am
calendar.set(Calendar.HOUR_OF_DAY, 9);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND, 0);
am.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(),
AlarmManager.INTERVAL_DAY, pi);
// alarm set
Finally create a broadcast receiver to do the work you want.
This question already has an answer here:
android prevent immediate trigger of alarm service if alarm time has passed for the day
(1 answer)
Closed 4 years ago.
Im creating my first app in Android Studio. My Alarm Clock is working almost well, but when I will set Alarm to hour earlier than current or after midnight my alarm is firing instantly. For example, current time is 17:00, when I set alarm for 17:05 everything is fine, but when alarm is for 16:00 or 00:05 alarm is firing instantly. I will be thankful for all your advices. Here is my code:
Alarm.java
public class Alarm extends AppCompatActivity {
private TimePicker timePicker;
private Button vibrationButton;
private Button soundButton;
private Button noteButton;
private Button saveButton;
private Button cancelButton;
private CheckBox wifiCheckBox;
private CheckBox soundCheckBox;
private CheckBox bluetoothCheckBox;
private TextView textView;
private BluetoothAdapter mBluetoothAdapter;
private WifiManager wiFi;
private AudioManager audioManager;
private AlarmManager alarmManager;
private PendingIntent pendingIntent;
private NotificationManager notificationManager;
private Intent intent;
private int hour;
private int minute;
private String minuteString;
private String hourString;
private void turnOnWifi() {
if (wifiCheckBox.isChecked())
wiFi.setWifiEnabled(true);
}
private void turnOnBluetooth() {
if (bluetoothCheckBox.isChecked())
mBluetoothAdapter.enable();
}
private void turnOnSound() {
if (soundCheckBox.isChecked())
audioManager.setRingerMode(AudioManager.RINGER_MODE_NORMAL);
}
private void notification() {
Intent intentNotification = new Intent(this.getApplicationContext(),Alarm.class);
PendingIntent pendingIntentNotification = PendingIntent.getActivity(this, 0, intentNotification, 0);
Notification notification = new Notification.Builder(this)
.setContentTitle("Alarm")
.setContentText("Next alarm: " + hourString + ":" + minuteString)
.setContentIntent(pendingIntentNotification)
.setAutoCancel(false)
.setSmallIcon(R.mipmap.ic_launcher)
.build();
notificationManager.notify(0, notification);
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_alarm);
timePicker = findViewById(R.id.timePicker);
vibrationButton = findViewById(R.id.vibrationButton);
soundButton = findViewById(R.id.soundButton);
noteButton = findViewById(R.id.noteButton);
saveButton = findViewById(R.id.saveButton);
cancelButton = findViewById(R.id.cancelButton);
wifiCheckBox = findViewById(R.id.wifiCheckBox);
soundCheckBox = findViewById(R.id.soundCheckBox);
bluetoothCheckBox = findViewById(R.id.bluetoothCheckBox);
textView = findViewById(R.id.textView);
wiFi = (WifiManager) getApplicationContext().getSystemService(Context.WIFI_SERVICE);
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
intent = new Intent(this, AlarmReceiver.class);
timePicker.setIs24HourView(true);
saveButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Calendar calendar = Calendar.getInstance();
if (calendar.before(Calendar.getInstance()))
calendar.add(Calendar.DATE, 1);
if (Build.VERSION.SDK_INT >= 23) {
calendar.set(Calendar.HOUR_OF_DAY, timePicker.getHour());
calendar.set(Calendar.MINUTE, timePicker.getMinute());
calendar.set(Calendar.SECOND, 0);
hour = timePicker.getHour();
minute = timePicker.getMinute();
} else {
calendar.set(Calendar.HOUR_OF_DAY, timePicker.getCurrentHour());
calendar.set(Calendar.MINUTE, timePicker.getCurrentMinute());
calendar.set(Calendar.SECOND, 0);
hour = timePicker.getCurrentHour();
minute = timePicker.getCurrentMinute();
}
hourString = String.valueOf(hour);
minuteString = String.valueOf(minute);
if (hour == 0)
hourString = "0" + hourString;
if (minute < 10)
minuteString = "0" + minuteString;
textView.setText("Next alarm: " + hourString + ":" + minuteString);
intent.putExtra("extra", "on");
setAlarm(calendar.getTimeInMillis());
// notification();
}
});
cancelButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
textView.setText("Alarm off!");
alarmManager.cancel(pendingIntent);
intent.putExtra("extra", "off");
sendBroadcast(intent);
// notificationManager.cancel(0);
}
});
}
private void setAlarm(long timeInMillis) {
pendingIntent = PendingIntent.getBroadcast(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
alarmManager.set(AlarmManager.RTC_WAKEUP, timeInMillis, pendingIntent);
}
}
AlarmReceiver.java
public class AlarmReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Log.e("test","test123");
String getState = intent.getExtras().getString("extra");
Log.e("Key is: ", getState);
Intent intentService = new Intent(context, RingtoneService.class);
intentService.putExtra("extra", getState);
context.startService(intentService);
}
}
RingtoneService.java
public class RingtoneService extends Service {
private MediaPlayer mediaPlayer;
boolean isRunning;
int startId;
#Override
public void onDestroy() {
Toast.makeText(this, "on destroy", Toast.LENGTH_SHORT).show();
this.isRunning = false;
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
public int onStartCommand(Intent intent, int flags, int startId) {
String state = intent.getExtras().getString("extra");
assert state != null;
switch (state) {
case "on":
startId = 1;
break;
case "off":
startId = 0;
break;
default:
startId = 0;
break;
}
if (!this.isRunning && startId == 1){
mediaPlayer = MediaPlayer.create(this, Settings.System.DEFAULT_RINGTONE_URI);
mediaPlayer.start();
this.isRunning = true;
this.startId = 0;
}
else if (this.isRunning && startId == 0){
mediaPlayer.stop();
mediaPlayer.reset();
this.isRunning = false;
this.startId = 0;
}
else if (!this.isRunning && startId == 0){
this.isRunning = false;
this.startId = 0;
}
else if (this.isRunning && startId == 1){
this.isRunning = true;
this.startId = 1;
}
return START_NOT_STICKY;
}
}
Of course it does... It's meant to work so.
Android recognizes that the time is past, so it will fire the alarm, even if it's late.
You can make sure that the time set for the alarm is after the current time. Just calculate this difference:
int diff = Calendar.getInstance().getTimeInMilis() - targetCal.getTimeInMillis();
If diff is greater than 0, then add a day to your calendar (targetCal)
Now, your device's time will be earlier (instead of being later) than the next scheduled alarm time.
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.HOUR_OF_DAY, hourOfDay);
calendar.set(Calendar.MINUTE, minute);
if(calendar.before(Calendar.getInstance())) {
calendar.add(Calendar.DATE, 1);
}
alarmManager.set(AlarmManager.RTC_WAKEUP,
calendar.getTimeInMillis(), pendingDinnerIntent);
I tried to develop a sample Alarm Application. I was searched Google and SC, most of the examples confusing me. I have done with my code, but why it failed to pass the alarm value to the Alarm receiver.
Please help me. Thank you for your concern.
Here is my code.
public class ReminderFragment extends Fragment {
Button buttonstartSetDialog;
TextView txt_time;
Context ctx;
final static int RQS_1 = 1;
public ReminderFragment() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_reminder, container, false);
txt_time = (TextView) v.findViewById(R.id.txt_time);
buttonstartSetDialog = (Button) v.findViewById(R.id.startSetDialog);
buttonstartSetDialog.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// textAlarmPrompt.setText("");
showTimePicker();
}
});
return v;
}
private void showTimePicker() {
// DatePickerFragment date = new DatePickerFragment();
TimePickerFragment time = new TimePickerFragment();
Calendar calendar = Calendar.getInstance();
Calendar calSet = (Calendar) calendar.clone();
Bundle args = new Bundle();
args.putInt("hour", calendar.HOUR_OF_DAY);
args.putInt("month", calendar.get(Calendar.MONTH));
args.putInt("minute", calendar.get(Calendar.MINUTE));
time.setArguments(args);
time.setCallBack(ontime);
time.show(getFragmentManager(), "Time Picker");
}
OnTimeSetListener ontime = new OnTimeSetListener() {
public void onTimeSet(TimePicker view, int hourOfDay, int minute) {
// TODO Auto-generated method stub
txt_time.setText(String.valueOf(hourOfDay) + ":" + String.valueOf(minute));
Intent intent = new Intent(getActivity(), AlarmReceiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(getActivity(), RQS_1, intent, 0);
AlarmManager alarmManager = (AlarmManager) ctx.getSystemService(Context.ALARM_SERVICE);
alarmManager.set(AlarmManager.RTC_WAKEUP, txt_time.getTimeInMillis(), pendingIntent);
}
};
}
AlarmReceiver.java
public class AlarmReceiver extends BroadcastReceiver {
private MediaPlayer mMediaPlayer;
#Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, "Time is up!!!!.", Toast.LENGTH_LONG).show();
// Vibrate the mobile phone
Vibrator vibrator = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE);
vibrator.vibrate(2000);
}
}
TimePickerFragment.java
public class TimePickerFragment extends DialogFragment {
OnTimeSetListener onTimeSet;
public TimePickerFragment() {
}
public void setCallBack(OnTimeSetListener ontime) {
onTimeSet = ontime;
}
#SuppressLint("NewApi")
private int hour, minute;
public void setArguments(Bundle args) {
super.setArguments(args);
hour = args.getInt("hour");
minute = args.getInt("minute");
}
public Dialog onCreateDialog(Bundle savedInstanceState) {
return new TimePickerDialog(getActivity(), onTimeSet, hour, minute, false);
}
}
Pass the values by
intent .putExtra("test", "ValueReceived");
and then in onReceive() get the value by
intent.getStringExtra("test")
Try with
OnTimeSetListener ontime = new OnTimeSetListener()
{
public void onTimeSet(TimePicker view, int hourOfDay, int minute) {
// TODO Auto-generated method stub
txt_time.setText(String.valueOf(hourOfDay) + ":" + String.valueOf(minute));
Intent intent = new Intent(getActivity(), AlarmReceiver.class);
intent.putExtra("time_value",String.valueOf(hourOfDay) + " : " + String.valueOf(minute));
PendingIntent pendingIntent = PendingIntent.getBroadcast(getActivity(), RQS_1, intent, 0);
AlarmManager alarmManager = (AlarmManager)ctx.getSystemService(Context.ALARM_SERVICE);
alarmManager.set(AlarmManager.RTC_WAKEUP, txt_time.getTimeInMillis(), pendingIntent);
}
};
You need to convert the selected time in long value (milliseconds)
use the below code to do this.
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.HOUR, hourOfDay);
calendar.set(Calendar.MINUTE, minute);
calendar.set(Calendar.AM_PM, Calendar.PM); // set AM or PM
long timeInMillis = calendar.getTimeInMillis();
and then pass this value timeInMillis in
alarmManager.set(AlarmManager.RTC_WAKEUP, timeInMillis, pendingIntent);