AlarmManager(حل شد)
با توجه به فصل 20 آموزش ها من میخوام یک اکتیویتی رو توی زمان خاصی از روز باز کنم (هر روز) توی گوگل زیاد سرچ کردم ولی یا خیلی پیچیده بودن یا عملکرد خوبی نداشتن ، کسی با IntentFilter و BroadCastReceiver و البته AlarmManager ها کار کرده؟








توی این برنامه چندین مرحله باید انجام بشه و برخلاف ظاهر و اسم ساده ای که داره بسیار کارهای پیچیده و وقت گیری باید انجام بشه.(2 روز برای من که مبتدی هستم طول کشید)
ابتدا باید در Manifest تنظیمات زیر رو اعمال کنیم:
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.VIBRATE"/>
<service android:name=".MyAlarmService"
android:enabled="true" />
<receiver android:name=".MyReceiver"
android:enabled="true">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
کد های بالا Permision های WAKE_LOCK و VIBRATE رو به ما میده و یک سرویس تعریف میکنه که فعالیت داشته باشه (حتی در هنگامی که برنامه باز نیست ) و Receiver و Intent Filter هم همان فضول و مسئله ای که اون فضول بهش توجه داره اند

در مرحله بعدی در اکتیویتی MainActivity باید زمان رو بگیریم و یک Calendar ست کنیم که بتوانیم با استفاده از اون سرویس خود را زمان بندی کنیم.
private PendingIntent pendingIntent;
private Calendar calendar;
public int setHours = 18;
public int setMinutes = 26;
public int setSeconds = 0;
final EditText hours = (EditText) findViewById(R.id.hours);
final EditText minutes = (EditText) findViewById(R.id.minutes);
final EditText seconds = (EditText) findViewById(R.id.seconds);
Button btnSet = (Button) findViewById(R.id.btnSet);
btnSet.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
Toast.makeText(getApplicationContext(), "TIME CHANGED", Toast.LENGTH_LONG).show();
Log.i("TAG", "TIME CHANGED");
setHours = Integer.parseInt(hours.getText().toString());
setMinutes = Integer.parseInt(minutes.getText().toString());
setSeconds = Integer.parseInt(seconds.getText().toString());
calendar = Calendar.getInstance();
Calendar c = Calendar.getInstance();
calendar.set(Calendar.MONTH, c.get(Calendar.MONTH));
calendar.set(Calendar.YEAR, c.get(Calendar.YEAR));
calendar.set(Calendar.DAY_OF_MONTH, c.get(Calendar.DAY_OF_MONTH));
calendar.set(Calendar.HOUR_OF_DAY, setHours);
calendar.set(Calendar.MINUTE, setMinutes);
calendar.set(Calendar.SECOND, setSeconds);
calendar.set(Calendar.AM_PM, Calendar.PM);
Intent myIntent = new Intent(MainActivity.this, MyReceiver.class);
pendingIntent = PendingIntent.getBroadcast(MainActivity.this, 0, myIntent, 0);
AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
alarmManager.set(AlarmManager.RTC, calendar.getTimeInMillis(), pendingIntent);
}
});
در بالا من 3 تا EditText برای گرفتن زمان در نظر گرفتم و البته یک دکمه که عملیات رو در نظر میگیره ، و Date رو از خود دستگاه تاریخ روز جاری رو میگیرم.بعد از ست کردن Calendar کلاس MyReceiver رو صدا میزنم که در اون کلاس کد زیر نوشته شده

public class MyReceiver extends BroadcastReceiver
{
@Override
public void onReceive(Context context, Intent intent)
{
Vibrator vibrator = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE);
vibrator.vibrate(1000);
Intent service1 = new Intent(context, MyAlarmService.class);
context.startService(service1);
}
}
که البته من Vibrator رو برای تست اینجا انجام دادم ، و بدون اون کاملا صحیح کار میکنه ...
پس از این کلاس ، کلاس MyAlarmService رو مینویسیم ، در این کلاس تمامی عملیاتی که با اجرا شدن سرویس ما توسط IntentFilter انجام میشه رو مینویسیم ، من توی برنامم نوتیفیکیشن دادم ، صدای Default Notification رو اضافه کردم ، و البته Notification bar رو لینک دادم به فرم جدید
public class MyAlarmService extends Service
{
private NotificationManager mManager;
@Override
public IBinder onBind(Intent arg0)
{
return null;
}
@Override
public void onCreate()
{
super.onCreate();
}
@SuppressWarnings("static-access")
@Override
public void onStart(Intent intent, int startId)
{
super.onStart(intent, startId);
mManager = (NotificationManager) this.getApplicationContext().getSystemService(this.getApplicationContext().NOTIFICATION_SERVICE);
Intent intent1 = new Intent(this.getApplicationContext(), NextActivity.class);
Notification notification = new Notification(R.drawable.ic_launcher, "message!", System.currentTimeMillis());
intent1.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent pendingNotificationIntent = PendingIntent.getActivity(this.getApplicationContext(), 0, intent1, PendingIntent.FLAG_UPDATE_CURRENT);
notification.flags |= Notification.FLAG_AUTO_CANCEL;
notification.setLatestEventInfo(this.getApplicationContext(), "AlarmManagerDemo", "This a test message!", pendingNotificationIntent);
Toast.makeText(this, "salaaaaaaaaaaaaaam", Toast.LENGTH_LONG).show();
MakeSomeSound();
mManager.notify(0, notification);
}
public void MakeSomeSound() {
try {
Uri notification = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
Ringtone r = RingtoneManager.getRingtone(getApplicationContext(), notification);
r.play();
}
catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void onDestroy()
{
// TODO Auto-generated method stub
super.onDestroy();
}
}

امیر جان زمانی که آلارم منیجر رو ست میکنیم، گوشی در زمان تعیین شده یک کلاس رو اجرا میکنه، وقتی گوشی شما خاموش و روشن میشه این آلارم ها حذف میشه، پس شما نیاز به عملگری داری که این آلارم هارو دوباره ست کنه. از BroadCastReceiver زمانی استفاده میکنیم که گوشی خاموش و روشن میشه، کارش اینه که دوباره آلارم منیجر رو ست کنه. حالا اگر بخواید چند آلارم ست کنید کافیه به PendingIntent یک ID اختصاص بدید، این آیدی ها رو همونطوری که حسین عزیز گفتن میتونید در یک آرایه از SharedPreferences ها ذخیره کنید، میتونید هم از دیتابیس استفاده کنید. زمانی که میخواید یک آلارم رو کنسل کنید، باید آیدی اون رو پیدا کنید و کنسلش کنید. حتما تست کنید که با خاموش و روشن شدن دستگاه دوباره فعال نشه.

ببین امیر جان، داری یک مساله خیلی راحت رو برای خودت سخت میکنی.
1-شما یک کلاس بساز که کارش ست کردن و حذف آلارم ها باشه.
2-یک کلاس Receiver بساز که زمانی که گوشی خاموش و روشن میشه کال بشه.
وظیفه کلاس اول(1) کاملا مشخصه، فقط آیدی هر آلارمی که ست میکنی رو در دیتابیس ذخیره کن.
وظیفه کلاس دوم(2) اینه که زمانی که گوشی دوباره روشن میشه، آلارم هایی که در دیتابیس هست رو دوباره ست کنه.
دلیل: آلارم هایی که ست میشن، با خاموش و روشن کردن گوشی از بین میرن، پس شما باید در هنگام راه اندازی مجدد گوشی دوباره آلارم ها رو ست کنی. در کلاس دوم شما باید یک حلقه داشته باشی، که به تعداد آلارم هایی که در دیتابیس ذخیره کردی آلارم ست کنه.

برنامه من تا set شدن آلارم درست کار میکنه اما داخل کلاس MyReceiver برای اجرا کردن سرویس نمیره!
Intent myIntent = new Intent(MainActivity.this, MyReceiver.class); pendingIntent = PendingIntent.getBroadcast(MainActivity.this, 0, myIntent, 0); AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE); alarmManager.set(AlarmManager.RTC, calendar.getTimeInMillis(), pendingIntent);
چه مشکلی میتونه داشته باشه؟؟

اینو امتحان کنید ببینید جواب میده ....
Intent myIntent = new Intent(context, MyService.class);
PendingIntent pendingIntent = PendingIntent.getService(context, 0, myIntent, 0);
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
alarmManager.set(AlarmManager.RTC, calendar.getTimeInMillis(), pendingIntent);
}

پرمیشن اینه:
<uses-permission android:name="com.android.alarm.permission.SET_ALARM" />
سرویستون رو هم توی منیفست تعریف کردید؟
پاسخگویی و مشاهده پاسخ های این سوال تنها برای اعضای ویژه سایت امکان پذیر است .
چنانچه تمایل دارید به همه بخش ها دسترسی داشته باشید میتوانید از این بخش لایسنس این آموزش را خریداری نمایید .