- 自由研究に戻る
- 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.this, 0, 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(this, this); // 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>
参考サイト
沢山ありますがありがとうございました。