しかし、断片的なイメージが強かったのでまとめてみたいと思います。
■今回作成するアプリの概要
AlarmManagerを用いて、指定した時間後にアラーム通知画面が表示され、アラーム音を鳴らす
■手順
SampleActivity(アラーム設定画面とします)
↓
(任意)MyAlarmManager(設定されたアラームを管理する独自クラス)
↓MyAlarmService(サービスを起動してブロードキャストメッセージを送ります)
↓
MyAlarmNotificationReceiver(メッセージを受信して通知画面を起動します)
↓
AlarmNotificationActivity(通知画面です)
■条件
1、スリープ画面であってもアラーム画面を表示する
■実装
まず、マニフェストファイルで設定しないといけない項目があります。
以下のXMLをAndroidManifest.xmlのapplicationタグ内の適切なところに配置します。
intent-filterで独自のメッセージ「"MyAlarmAction"」を受信するようにしてます。
------------------------------------------------------------------------------------------------
<receiver android:name="MyAlarmNotificationReceiver">
<intent-filter>
<action android:name="MyAlarmAction"/>
</intent-filter>
</receiver>
<service android:name="MyAlarmService"></service>
<activity android:name="AlarmNotificationActivity"></activity>
------------------------------------------------------------------------------------------------
以下の2行をmanifesstタグ直下に配置します。
これは、スリープ状態を解除するために必要な権限です。
------------------------------------------------------------------------------------------------
<uses-permission android:name="android.permission.WAKE_LOCK"/>
<uses-permission android:name="android.permission.DISABLE_KEYGUARD"/>
------------------------------------------------------------------------------------------------
【SampleActivity.java】
アラームをセットするために必要なのは以下の2行だけです。
実行する場所はどこでもいいと思います。ボタンを押したタイミングなど...
今回はテストのため簡略化しています。
便宜上引数を設けた方がいいと思います。
MyAlarmManager mam = new MyAlarmManager(this);
mam.addAlarm();
【MyAlarmManager.java】
import java.util.Calendar;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
public class MyAlarmManager {
Context c;
AlarmManager am;
private PendingIntent mAlarmSender;
public MyAlarmManager(Context c){
this.c = c;
am = (AlarmManager)c.getSystemService(Context.ALARM_SERVICE);
Log.v("MyAlarmManger","初期化完了");
}
public void addAlarm(/*今はなにもなしで*/){
mAlarmSender = PendingIntent.getService(c, -1, new Intent(c, MyAlarmService.class), PendingIntent.FLAG_UPDATE_CURRENT);
// アラーム時間設定
Calendar cal = Calendar.getInstance();
cal.setTimeInMillis(System.currentTimeMillis());
cal.add(Calendar.MINUTE, 1);
cal.set(Calendar.SECOND, 0);
cal.set(Calendar.MILLISECOND, 0);
Log.v("MyAlarmManagerログ",cal.getTimeInMillis()+"ms");
am.set(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), mAlarmSender);
Log.v("MyAlarmManagerログ","アラームセット完了");
}
}
【MyAlarmService.java】
Serviceを継承してます。
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.util.Log;
public class MyAlarmService extends Service {
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public void onCreate() {
Log.v("MyAlarmServiceログ","Create");
Thread thr = new Thread(null, mTask, "MyAlarmServiceThread");
thr.start();
Log.v("MyAlarmServiceログ","スレッド開始");
}
/**
* アラームサービス
*/
Runnable mTask = new Runnable() {
public void run() {
// ここでアラーム通知する前の処理など...
Intent alarmBroadcast = new Intent();
alarmBroadcast.setAction("MyAlarmAction");//独自のメッセージを送信します
sendBroadcast(alarmBroadcast);
Log.v("MyAlarmServiceログ","通知画面起動メッセージを送った");
MyAlarmService.this.stopSelf();//サービスを止める
Log.v("MyAlarmServiceログ","サービス停止");
}
};
}
【MyAlarmNotificationReceiver.java】
これは、サービスから送られて来たメッセージを受信する役割を担います。
今回はただ通知画面を起動するだけです。
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
public class MyAlarmNotificationReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Log.v("レシーバログ", "action: " + intent.getAction());
Intent notification = new Intent(context,
AlarmNotification.class);
//ここがないと画面を起動できません
notification.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(notification);
}
}
【AlarmNotificationActivity.java】
これが実際に表示されるアラーム通知画面です。
onStartでアラーム音を再生しています。
onDestroyでリソースを解放します。
import android.app.Activity;
import android.app.KeyguardManager;
import android.app.KeyguardManager.KeyguardLock;
import android.content.Context;
import android.media.MediaPlayer;
import android.os.Bundle;
import android.os.PowerManager;
import android.os.PowerManager.WakeLock;
import android.util.Log;
public class AlarmNotification extends Activity {
private WakeLock wakelock;
private KeyguardLock keylock;
MediaPlayer mp;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.alarm);
Log.v("通知ログ", "create");
// スリープ状態から復帰する
wakelock = ((PowerManager) getSystemService(Context.POWER_SERVICE))
.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK
| PowerManager.ACQUIRE_CAUSES_WAKEUP
| PowerManager.ON_AFTER_RELEASE, "disableLock");
wakelock.acquire();
// スクリーンロックを解除する
KeyguardManager keyguard = (KeyguardManager) getSystemService(Context.KEYGUARD_SERVICE);
keylock = keyguard.newKeyguardLock("disableLock");
keylock.disableKeyguard();
}
@Override
public void onStart() {
super.onStart();
if (mp == null)
mp = MediaPlayer.create(this, R.raw.alarm);
mp.start();
}
@Override
public void onDestroy() {
super.onDestroy();
stopAndRelaese();
}
private void stopAndRelaese() {
if (mp != null) {
mp.stop();
mp.release();
}
}
}
大まかにこんな感じでアラームが起動します。
必要に応じてコードは書き換えて下さい。
リソースファイルなどを用意していないと動きません。
コピペで動く保障はしません。
他にも手段はあります。
あくまでも一例としてみて頂ければと思います。
アドバイス、指摘などありましたらコメントをお願いいたします。
こんにちはこんな素晴らしい、ブログやっと発見しました。
返信削除最近始めたばかりで、いろいろやってるんですが、うまくいかなくて。
不規則な勤務形態の仕事で一気に一日分のアラームセットを運行ダイヤごとに
設定したいのです。
例えば○○番ダイヤは3回休み時間があって10時23分と14時44分と18時20分の発車10分前になったらアラームセットアラーム音メッセージに行先など出したりとか、
しかし時間の計算とか意外と難しかったです、まだまだ、未熟です。
見てみるとこれならうまく行きそうです。色々試してみます。
これからも時々寄らして頂きます。