2012年4月14日土曜日

Androidでアラームを作るための手順の例

ネットで「Android アラーム 開発」などとググるといろんな方が記事を書いています。

しかし、断片的なイメージが強かったのでまとめてみたいと思います。

■今回作成するアプリの概要
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();
    }
    }
}


大まかにこんな感じでアラームが起動します。
必要に応じてコードは書き換えて下さい。
リソースファイルなどを用意していないと動きません。
コピペで動く保障はしません。

他にも手段はあります。
あくまでも一例としてみて頂ければと思います。

アドバイス、指摘などありましたらコメントをお願いいたします。

1 件のコメント:

  1. こんにちはこんな素晴らしい、ブログやっと発見しました。
    最近始めたばかりで、いろいろやってるんですが、うまくいかなくて。
    不規則な勤務形態の仕事で一気に一日分のアラームセットを運行ダイヤごとに
    設定したいのです。
    例えば○○番ダイヤは3回休み時間があって10時23分と14時44分と18時20分の発車10分前になったらアラームセットアラーム音メッセージに行先など出したりとか、
    しかし時間の計算とか意外と難しかったです、まだまだ、未熟です。
    見てみるとこれならうまく行きそうです。色々試してみます。
    これからも時々寄らして頂きます。

    返信削除