Переустановка Alarm после перезагрузки устройства. У меня объявлен широковещательный приемник, который запускается при загрузке ОС на устройстве. Приемник вызывет созданный мной сервис.
public class BootReceiver extends BroadcastReceiver {
private static final String BOOT_COMPLETED =
"android.intent.action.BOOT_COMPLETED";
private static final String QUICKBOOT_POWERON =
"android.intent.action.QUICKBOOT_POWERON";
@Override
public void onReceive(Context context, Intent intent) {
//that doing on boot system
String action = intent.getAction();
if (action.equals(BOOT_COMPLETED) || action.equals(QUICKBOOT_POWERON)) {
Intent service = new Intent(context, BootService.class);
context.startService(service);
}
}
}
Приемник запускает сервис который переустанавливает все сохраненные Alarms, посредством вызова метода из класса активности приложения.
public class BootService extends IntentService {
private Handler mHandler;
Options options;
public BootService() {
super("BootService");
}
public void onCreate(){
super.onCreate();
options = new Options();
Log.i("DEBUGER_BootService", "BootService.onCreate");
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
mHandler = new Handler();
setAlarm();
return super.onStartCommand(intent, flags, startId);
}
private void setAlarm(){
mHandler.post(new Runnable() {
@Override
public void run() {
SQLiteOpenHelper optionsDBhelper;
SQLiteDatabase optionsDB;
try {
optionsDBhelper = new OptionsDBHelper(getApplicationContext());
optionsDB = optionsDBhelper.getReadableDatabase();
//метод класса активности
options.reoptionNotify(optionsDB);
optionsDBhelper.close();
optionsDB.close();
} catch (SQLException e) {
Toast toast = Toast.makeText(getApplicationContext(), R.string.error_bd, Toast.LENGTH_SHORT);
toast.setGravity(Gravity.CENTER, 0, 0);
toast.show();
}
}
});
}
@Override
protected void onHandleIntent(Intent intent) {
//setAlarm();
Intent service = new Intent(this, BootService.class);
stopService(service);
}
public void onDestroy(){
super.onDestroy();
options = null;
}
}
Пробывал вызывать и из onStartComand и из onHandleIntent и из самого приемника, который запускаеться вместе со всей системой. В Logcat выдаеться одна и таже ошибка.
10-18 12:24:44.273 4152-4152/? I/DEBUG: [OnPurpose Redunant in preset_info] pid: 4087, tid: -1361051648, name: UNKNOWN >>> UNKNOWN <<<
Как видно из кода сервиса я пытаюсь вызвать метод из нового, созданного потока. Но результат один и тот же что с потоком что без.
Код метода:
public void reoptionNotify(SQLiteDatabase db){
//update notify option of sound
Cursor cTrainings, cTime, cCommon;
cTime = db.query("TIME_EX", new String[]{"_id", "TIME"},
null, null, null,null, null);
if (cTime.moveToFirst()){
cTrainings = db.query("TRAININGS",
new String[]{"NAME", "COL_EX", "REST_TIME", "TIME_TO_DO"}, "TIME_TO_DO = ?",
new String[]{Integer.toString(cTime.getInt(0))},
null, null, null);
cCommon = db.query("COMMON", new String[]{"SOUND"},
null,null,null,null,null);
cCommon.moveToFirst();
do {
if (cTrainings.moveToFirst()) {
restartNotify(cTime.getString(1),
cTime.getInt(0),
buildTrainingsStr(cTrainings,cTime), cCommon.getInt(0));
}
}while (cTime.moveToNext());
cTrainings.close();
cCommon.close();
}else {
Toast toast = Toast.makeText(Options.this, R.string.error_notime, Toast.LENGTH_SHORT);
toast.setGravity(Gravity.CENTER, 0, 0);
toast.show();
}
cTime.close();
}
//create or update notify
public void restartNotify(String selectedTime, int rC, String optStr, int optSnd) {
char c;
StringBuilder strB;
Calendar calendar = Calendar.getInstance();
AlarmManager am = (AlarmManager) MainActivity.context.getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(MainActivity.context, TimeNotification.class);
//transfer string with saved opt to create notify in receiver
intent.putExtra("OPTSTR", optStr);
intent.putExtra("ID", rC);
intent.putExtra("OPTSOUND", optSnd);
PendingIntent pendingIntent = PendingIntent.getBroadcast(MainActivity.context, rC,
intent, PendingIntent.FLAG_UPDATE_CURRENT );
//set saved time from db in object Calendar
strB = new StringBuilder();
for (int i = 0; i < selectedTime.length(); i++) {
c = selectedTime.charAt(i);
if (c == ':'){
calendar.set(Calendar.HOUR_OF_DAY, Integer.valueOf(strB.toString()));
strB = new StringBuilder();
}else
strB.append(c);
}
calendar.set(Calendar.MINUTE, Integer.valueOf(strB.toString()));
calendar.set(Calendar.SECOND, 0);
//check for selected time be smaller then currently time if not
//transfer alarm on the next day
if (calendar.getTimeInMillis() < System.currentTimeMillis())
calendar.add(Calendar.DATE, 1);
//set one time alarm
am.set(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), pendingIntent);
}
//build and return string of saved time and trainings on it
public String buildTrainingsStr(Cursor cTrainings, Cursor cTime){
StringBuilder builderStr = new StringBuilder();
builderStr.append(cTime.getString(1));
builderStr.append("\n");
do {
//get name of training
String ss = cTrainings.getString(0);
builderStr.append(ss);
//check for training "Основи" to ignore rest parameters
if (ss.equals(MainActivity.context.getString(R.string.f_osnovy))) {
builderStr.append(".\n");
} else {
builderStr.append(", ");
builderStr.append(MainActivity.context.getString(R.string.txt_ex_col));
builderStr.append(cTrainings.getInt(1));
//get value of rest time
int s = cTrainings.getInt(2);
//check for existing value of rest time
if (s != 0) {
builderStr.append(", ");
builderStr.append(s);
builderStr.append(MainActivity.context.getString(R.string.txt_exe_rt));
builderStr.append(".\n");
} else builderStr.append(".\n");
}
} while (cTrainings.moveToNext());
return builderStr.toString();
}
Вместо создания "мёртвого" экземпляра класса активности лучше вынести методы в отдельный класс-помощник. А для доступа к контексту передать его туда через конструктор. Выводить Toast
из этого помощника не следует, лучше возвращать из метода булево значение и проверив его делать что нужно - например, в активности вывести Toast
, а в сервисе уведомление или вообще ничего (зачем маячить тостами при старте устройства - вряд ли юзеру это нужно).
public class AlarmHelper {
private Context mContext;
public AlarmHelper(Context context) {
this.mContext = context;
}
public boolean reoptionNotify(SQLiteDatabase db){
//update notify option of sound
Cursor cTrainings, cTime, cCommon;
boolean setted = false;
cTime = db.query("TIME_EX", new String[]{"_id", "TIME"},
null, null, null,null, null);
if (cTime.moveToFirst()){
cTrainings = db.query("TRAININGS",
new String[]{"NAME", "COL_EX", "REST_TIME", "TIME_TO_DO"}, "TIME_TO_DO = ?",
new String[]{Integer.toString(cTime.getInt(0))},
null, null, null);
cCommon = db.query("COMMON", new String[]{"SOUND"},
null,null,null,null,null);
cCommon.moveToFirst();
do {
if (cTrainings.moveToFirst()) {
restartNotify(cTime.getString(1),
cTime.getInt(0),
buildTrainingsStr(cTrainings,cTime), cCommon.getInt(0));
setted = true;
}
} while (cTime.moveToNext());
cTrainings.close();
cCommon.close();
}
cTime.close();
return setted;
}
//create or update notify
public void restartNotify(String selectedTime, int rC, String optStr, int optSnd) {
char c;
StringBuilder strB;
Calendar calendar = Calendar.getInstance();
AlarmManager am = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(mContext, TimeNotification.class);
//transfer string with saved opt to create notify in receiver
intent.putExtra("OPTSTR", optStr);
intent.putExtra("ID", rC);
intent.putExtra("OPTSOUND", optSnd);
PendingIntent pendingIntent = PendingIntent.getBroadcast(mContext, rC,
intent, PendingIntent.FLAG_UPDATE_CURRENT );
//set saved time from db in object Calendar
strB = new StringBuilder();
for (int i = 0; i < selectedTime.length(); i++) {
c = selectedTime.charAt(i);
if (c == ':'){
calendar.set(Calendar.HOUR_OF_DAY, Integer.valueOf(strB.toString()));
strB = new StringBuilder();
}else
strB.append(c);
}
calendar.set(Calendar.MINUTE, Integer.valueOf(strB.toString()));
calendar.set(Calendar.SECOND, 0);
//check for selected time be smaller then currently time if not
//transfer alarm on the next day
if (calendar.getTimeInMillis() < System.currentTimeMillis())
calendar.add(Calendar.DATE, 1);
//set one time alarm
am.set(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), pendingIntent);
}
//build and return string of saved time and trainings on it
public String buildTrainingsStr(Cursor cTrainings, Cursor cTime){
StringBuilder builderStr = new StringBuilder();
builderStr.append(cTime.getString(1));
builderStr.append("\n");
do {
//get name of training
String ss = cTrainings.getString(0);
builderStr.append(ss);
//check for training "Основи" to ignore rest parameters
if (ss.equals(mContext.getString(R.string.f_osnovy))) {
builderStr.append(".\n");
} else {
builderStr.append(", ");
builderStr.append(mContext.getString(R.string.txt_ex_col));
builderStr.append(cTrainings.getInt(1));
//get value of rest time
int s = cTrainings.getInt(2);
//check for existing value of rest time
if (s != 0) {
builderStr.append(", ");
builderStr.append(s);
builderStr.append(mContext.getString(R.string.txt_exe_rt));
builderStr.append(".\n");
} else builderStr.append(".\n");
}
} while (cTrainings.moveToNext());
return builderStr.toString();
}
}
Использование в активности или сервисе:
AlarmHelper ah = new AlarmHelper(this);
if (ah.reoptionNotify(optionsDB)) {
// alarms setted
} else {
// don't have alarms
}
Айфон мало держит заряд, разбираемся с проблемой вместе с AppLab
В android studio при запуске эмулятора вылетает такая ошибка -
код ниже работает все отлично-непонятно другое int miles мы не задавали значений (расстояния) а задали их int dist = 252; По идее же тут вместо miles должно...