1. 自由研究に戻る
  2. Menu表示

等々力から多摩川を望む
2012.05.01 多摩川-中原区から二子橋方面を望む

android アプリを指定時刻に起動する、AlarmManager

Web天気予報をダウンロードし音声出力、音声読み上げ

AlarmManagerの確認です。
・指定時刻(AlermManager)にwebサイトにアクセスし、天気予報をダウンロード
・Serviceの中で、トースト表示(alertDialog表示はエラーで、うまくいかない)
・(バックグラウンドスレッドでダイアログは生成できないようです。)
・テキストの音声読み上げ
の確認をしてみます。
下記サイトを参考にしながら動作を確認していきます。
(1)AlarmManager、Y.A.M の 雑記帳
(2)AlarmManagerで指定した時間に処理させる
(3)AlarmManager | Android Developers
 Serviceの一種でしょうかIntentServiceというものがあります。処理手順が簡略化されているようです。下記参照
(4)IntentServiceを使って非同期処理を行う
(5)ソフトウェア技術ドキュメントを勝手に翻訳
(6)AlarmService を利用したサービス実行のスケジューリング
  AlarmServiceとはAlarmManagerを使ってServiceをスケジューリングすることのようです。内容はAlarnManagerとIntentServiceについて書かれています。
(7) ゼロから始めるAndroid開発【サービス編】
 
使い方は
■起動したいアプリをIntentで登録します。
‐Intent intent = new Intent(MainActivity.this, AlarmReceiver.class);
■PendingIntentでIntentを発行する。
-PendingIntent sender = PendingIntent.getActivity(AlarmManageActivity.this, 0, intent, 0);
・PendingIntentはIntentを即座に発行するのではなく、タイミング(時間、イベント)を指定して発行するIntentです。
・Intentを投げる先は3つあります(PendingIntent.getActivity, PendingIntent.getService, PendingIntent.getBroadcast)。webデータをダウンロードする場合はデータが大きくなり、時間がかかりそうなので、Broadcastは不向です。このような場合は、ServiceあるいはActivityが使えるようです。
■AlarmManagerを使うことで指定した時間に任意の処理(メソッド)をさせることができます。
-AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
-alarmManager.set(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), sender);
メソッドの例として
 ‐void cancel(PendingIntent operation)処理を削除
 ‐void set(int type, long triggerAtTime, PendingIntent operation)任意の時間で実行する処理を登録
 ‐void setRepeating(int type, long triggerAtTime, long interval, PendingIntent operation)一定間隔で実行する処理を登録

例(1)Activityの場合
  <application .... /application>の配下に
  actionの指定を行う
例(2)Serviceの場合
  Manifestへの記述は
  <application .... /application>の配下に
  <service android:enabled="true" android:name=".AlarmReceiver" /> を記述
 下記プログラム参照
例(3)Broadcastの場合
  AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
   // one shot 任意の時間で実行する処理を登録
   alarmManager.set(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), sender);
  PendingIntent sender = PendingIntent.getBroadcast(MainActivity.this, 0, intent, 0);
  
  Manifestへの記述は
  <application .... /application>の配下に
  <receiver android:name=".AlarmReceiver" android:process=":remote" /> を記述

■起動時刻の設定はUTC時刻で行う。
setメソッドの第2引数はUTC時刻を設定するようです(typeがRTC, RTC_WAKEUPの場合)。現在のUTC時刻はcalendarで取得できます、またローカルタイムで時刻の設定をしている場合はUTCに変換が必要になるのでしょう。TimeZoneクラスのgetOffsetメソッドを使うと、UTC時刻からのoffsetをmillisecondsで得られるようです。


実施例(1)PendingIntent.getActivityを使う場合
確認プログラムは下記2段階で進めてみます。
・起動する時刻を設定し、指定時刻にアプリを起動する。
・起動されるアプリに天気予報読み上げさせる。
(音声読み上げは「テキスト読み上げ、音声認識」 の設定を使います)
起動画面
Fig.1 起動画面 (ここでstartボタンを押し、AlarmManagerが起動)

音声読み上げテキスト
Fig.2 天気予報をダウンロードした起動画面
一定時間後(ここでは15秒後)、別Activityが起動
ダウンロードした天気予報がTTSで読み上げられます。

実施例(2)PendingIntent.getServiceを使う場合
起動画面

Fig.3 起動画面、buttonでスタート

天気予報表示←トースト表示
Fig.4 天気予報をトーストで表示し、音声読み上げ
webサイトから天気予報をダウンロードします。トーストで表示します。また音声読み上げます。
============================================================================
ソースプログラム 実施例(1)PendingIntent.getActivityを使う場合
============================================================================
省略します。
============================================================================
ソースプログラム 実施例(2)PendingIntent.getServiceを使う場合
============================================================================
********* AlarmManageServiceActivity.java ******************** package alarmManageSevice.app;
import java.util.Calendar;
import android.app.Activity;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;

public class AlarmManageServiceActivity extends Activity implements View.OnClickListener{
    private Button buttonStart;
    TextView mTextView;    
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        mTextView = (TextView)findViewById(R.id.button1); 
        // ボタンのClickListenerの登録
        buttonStart = (Button)findViewById(R.id.button1);        
        buttonStart.setOnClickListener(this);
    }
    public void onClick(View arg0) {
        if (buttonStart == arg0) {
              mTextView.setText("AlarmManager start");              
            alarmSet();
        }else {}          
    }
    private void alarmSet() {
         Intent intent = new Intent(AlarmManageServiceActivity.this, AlarmReceiver.class);  
         PendingIntent sender = PendingIntent.getService(AlarmManageServiceActivity.this0, intent, 0);
         Calendar calendar = Calendar.getInstance();  
         calendar.setTimeInMillis(System.currentTimeMillis());  
         calendar.add(Calendar.SECOND, 10);  
         AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);  
         // one shot  
         alarmManager.set(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), sender);
         Toast.makeText(AlarmManageServiceActivity.this"Start Alarm!", Toast.LENGTH_SHORT).show(); 
    }    
}
------------------------------------------------------------------------
*********************** AlarmReceiver.java ***************************
package alarmManageSevice.app;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Locale;
import java.util.StringTokenizer;
import org.xmlpull.v1.XmlPullParser;
import android.app.Service;
import android.content.Intent;
import android.os.Handler;
import android.os.IBinder;
import android.speech.tts.TextToSpeech;
import android.util.Log;
import android.util.Xml;
import android.widget.TextView;
import android.widget.Toast;
public class AlarmReceiver extends Service implements TextToSpeech.OnInitListener {
    Handler  mHandler   = new Handler();    //Handlerのインスタンス生成    
    String src ;
    private TextToSpeech    tts;
    TextView mTextView; 
    @Override
    public IBinder onBind(Intent arg0) {
        // TODO 自動生成されたメソッド・スタブ
        return null;
    }
    @Override
    public void onCreate() {
         super.onCreate();
        Toast.makeText(this"Alarm onCreate!", Toast.LENGTH_SHORT).show();  
    } 
    @Override
      public int onStartCommand(Intent intent, int flags, int startId) {
        Toast.makeText(this"Alarm onStart!", Toast.LENGTH_SHORT).show();  
         tts = new TextToSpeech(thisthis);         // This is a good place to set spokenText        
         httpWeather();            
        return START_STICKY;
      }    
    @Override
    public void onDestroy() {
        super.onDestroy();
        if (null != tts) {
            // TextToSpeechのリソースを解放する
            tts.shutdown();
        }     
    }
    public void onInit(int status) {
           if (TextToSpeech.SUCCESS == status) {
               Locale locale = Locale.ENGLISH;
               if (tts.isLanguageAvailable(locale) >= TextToSpeech.LANG_AVAILABLE) {
                   tts.setLanguage(locale);
               } else {
                   Log.d("""Error SetLocale");
               }    
           } else {
                   Log.d("""Error Init");
           } 
    }  
    private void speechText(String string) {        
           if (0 < string.length()) {
               if (tts.isSpeaking()) { 
                   // 読み上げ中なら止める
               tts.stop();
               }       // 読み上げ開始
               tts.speak(string, TextToSpeech.QUEUE_FLUSH, null);
         }
    } 
    private void httpWeather() {
        // スレッド起動  
        (new Thread(new Runnable() {  
         //   @Override 
      public void run() {  
                // 通常バックグランドをここに記述します
                int intEventType = -1;
                   String strParserName = "";               
                   StringTokenizer  objToken = null;
                  String strGettingTitle = "";
                String strGettingTelop = "";
                String strGettingDiscription = "";
                HttpURLConnection http = null;
                InputStream in = null;
                try{
                //取得XMLのURIを設定
                //uri += "?city=" + id + "&day=tomorrow";
                    URL uri = new URL("http://weather.livedoor.com/forecast/webservice/rest/v1?city=54&day=tomorrow");
                   //XML取得
                    http = (HttpURLConnection)uri.openConnection();
                    http.setRequestMethod("GET");
                    http.connect();
                    // データを取得
                    in = http.getInputStream();
                    //XMLから情報を抽出
                    XmlPullParser parser = Xml.newPullParser();
                    parser.setInput(in,"UTF-8");                    
                    while(intEventType != XmlPullParser.END_DOCUMENT){
                        switch (intEventType){
                           case XmlPullParser.START_TAG: 
                            strParserName = parser.getName() ;
                            if(strParserName.equals("title") && strGettingTitle.equals("")){
                                   strGettingTitle = parser.nextText()+"は、";
                               }
                               if(strParserName.equals("telop") && strGettingTelop.equals("")){
                                   strGettingTelop = parser.nextText()+"です、";
                               }
                               if(strParserName.equals("description") && strGettingDiscription.equals("")){
                                   strGettingDiscription = parser.nextText();
                                   String[] strAry=strGettingDiscription.split("。",2); 
                                   strGettingDiscription=strAry[0]; //descriptionは1文のみ表示                    
                               }
                        }        
                        if(!strParserName.equals("") && !strGettingTelop.equals("") && !strGettingDiscription.equals("")){ 
                            break;
                        } 
                        intEventType = parser.next();
                    }
                    //取得データを画面に表示 
                    src=strGettingTitle + "\n" + strGettingTelop + "\n" + strGettingDiscription;                    
                }catch(Exception e){                    
                    src=e.toString(); 
                }finally{
                }    
                mHandler.post(new Runnable(){
                    public void run() {
                        // TODO 自動生成されたメソッド・スタブ
                        Toast.makeText(getApplicationContext(),src, Toast.LENGTH_LONG).show(); 
                    }
                });                
            speechText(src);  
         }
       })).start();  
    }        
}
------------------------------------------------------------------------
*********************** AndroidManifest.xml ************************
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="alarmManageSevice.app"
    android:versionCode="1"
    android:versionName="1.0" >
    <uses-sdk android:minSdkVersion="15" />
    <uses-permission android:name="android.permission.INTERNET"></uses-permission>
    <application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name" >
        <activity
            android:name=".AlarmManageServiceActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <service 
              android:enabled="true"
             android:name=".AlarmReceiver"  />
    </application>
</manifest>
参考サイト
沢山ありますがありがとうございました。