app widgetでテザリング
TRANSCRIPT
3G回線を使い、通常パケット料金内で
テザリング
AU Android2.2以上
● ときどきテザリングできると便利な人● そのためだけにテザリング契約したくない人● そのためだけに機種変更したくない人● 大量データを必要としない人
機種に依存するので、やれるかどうかまず確かめてみる
(PCに Android-SDK がインストールされているものとする)
● 実機をUSBでPCに接続し、WIFIテザリングのUIを呼び出すクラスが存在するか確かめてみる
terminal(UNIX系) や コマンドプロンプト(Windows系)で
$ adb -d shell (コマンドプロンプトでは、 C:\users\name>adb -d shell)
$ am start -a android.intent.action.MAIN -n com.android.settings/.wifi.WifiApSettings
で、テザリング設定のUIが表示される
$ am とやれば コマンド形式(help)が表示される
明示的Intentを投げてActivityを起動するには、
$ am start -a <アクション> -n <起動したいアプリケーションのパッケージ名>/.<Activity名>
要は
com.android.settings というパッケージの
wifi.WifiApSettings というActivity を
アクション MAIN で起動すればよい
Android アプリとしても簡単に作れるが簡単すぎるので
AppWidget として作ってみる
今日のミッション
テザリングを題材としてAppWidgetを作ってみる
AppWidgetを作るために用意する4つのファイル
■レイアウトファイル
■AppWidgetプロバイダーの登録ファイル
■AndroidManifest.xml
■Javaソースコードファイル
用意する4つのファイル
■レイアウトファイル
画面の表示はレイアウト用のXMLファイルとして用意します。
今回使用した名称は、layout_tether_widget.xml(任意)
AppWidgetでは、使用できるウィジェットが限定されています。
「AnalogClock」「Button」「Chronometer」「ImageButton」「ImageView」
「ProgressBar」「TextView」と、その他レイアウト関係のものしか使うことができません。
それ以外のもの、例えばテキストを入力するEditTextなどは使えません。
用意する4つのファイル
■レイアウトファイル
■AppWidgetプロバイダーの登録ファイル
これもXMLファイルです。
res フォルダの中の xml (任意)フォルダに tetherWidget.xml という名称(任意)で作成しました。
これは「AppWidgetプロバイダー」というものを記述するためのものです。
AppWidgetに関する各種の設定情報を記述します。
Androidは、ここに書かれた情報を元に、AppWidgetを作成します。
用意する4つのファイル
■レイアウトファイル
■AppWidgetプロバイダーの登録ファイル
■AndroidManifest.xml
これは、androidのプログラムに関する情報を記述しているファイルです。
ここに「プロバイダー」と「サービス」というものに関する設定を用意しておきます。
用意する4つのファイル
■レイアウトファイル
■AppWidgetプロバイダーの登録ファイル
■AndroidManifest.xml
■Javaソースコードファイル
これは、大きく分けて2つのソースコードからなります。
1つは「プロバイダー」クラス、もう1つは「サービス」クラスです。
この2つを組み合わせてプログラムは動きます。
プロバイダーは、プログラムやその中に用意されているデータ、
機能などを公開し、外部から利用できるようにします。
サービスは、バックグラウンドで実行されるプログラムです。
★AppWidgetのレイアウトを作る
ここでは「TetherWidget」という簡単なAppWidgetを作ってみます。
ボタンがひとつあり、クリックするとテザリングの設定ができる、というものです。
まずは、AppWidgetのレイアウト
プロジェクトの「res」内にある「layout」の中に、新たに「layout_tether_widget.xml」というファイルを作ります。
そして以下のリストのようにソースコードを記述します。
Buttonに表示するテキストは、面倒くさいので strings.xml を使わず直接設定しました。
Buttonがあるだけの超シンプルなものです。
● layout_tether_widget.xml<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#33000000"
android:orientation="vertical">
<Button
android:id="@+id/button"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="テザリング"
/>
</LinearLayout>
●
★AppWidgetプロバイダーの登録ファイルを用意する
これは、「res」フォルダ内に、新たに「xml」というフォルダを作り、この中に「tetherwidget.xml」という名称でXMLファイルを作ります。
ファイルの作成は、<ファイル><新規><その他(O)> を選択(クリック)し、<Android><Android XML File>メニューで作成しますが、ファイルの設定画面では、リソース・タイプとして「AppWidget Provider」を選びます。
これでAppWidgetプロバイダー作成のためのテンプレートが書き出されます。
<?xml version="1.0" encoding="utf-8"?>
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android" >
</appwidget-provider>
作成されたファイルを開き、ソースコードを記述します
● tetherwidget.xml
<?xml version="1.0" encoding="utf-8"?>
<appwidget-provider
xmlns:android="http://schemas.android.com/apk/res/android"
android:initialLayout="@layout/layout_tether_widget"
android:minHeight="72dip"
android:minWidth="146dip"
android:updatePeriodMillis="0">
</appwidget-provider>
<appwidget-provider>というタグを使って記述します。
この中に、AppWidget に関するさまざまな設定情報を属性として用意します。
● initialLayout ―― 使用するレイアウトを指定します。
● minHeight,minWidth ―― 最小高さ・最小幅を指定します。
● updatePeriodMillis ―― 更新の処理が実行される間隔を指定します。
updatePeriodMillis は、システムが定期的にAppWidgetプロバイダーの更新を行う間隔を指定するものです。
ここではゼロにすると更新処理は行われなくなります。
AppWidgetは常駐プログラムですから、頻繁に更新が呼び出されると、見る見るバッテリーを消費してしまいます。
ですので特別な理由がない限り、これはゼロにして「更新しない」ようにしておきます。
ウィジェットのサイズは自由に決めることはできません
画面を横4行、縦4列に分割して使用します。
1行1列のサイズは、74dip × 74dip
たとえば、横1行、縦2列(横に長い長方形)の場合では、横148、縦74 ですが、
実際に指定するときは、丸め誤差により問題が発生しないように、2dipを引いたものを最小サイズとして記載します。
● minHeight 74 - 2 = 72dip
● minWidth 148 - 2 = 146dip
★AndroidManifest.xml を修正する
これは、androidのプログラムに関する情報が記述されたもので、プロジェクトを作ると自動的に作成されます。
この中に、プログラムに関する情報が書かれており、androidのシステムはこれを見てプログラムの内容を理解します。
このファイルの内容は、整理するとだいたい以下のような形になっています。
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" …略…>
<application …略…>
<activity …略…>
……Activityの情報……
</activity>
</application>
<uses-sdk android:minSdkVersion="番号" />
</manifest>
<manifest>というタグ内に各種のプログラムの情報が置かれます。
この<manifest>というタグ内の <application>タグの中に、AppWidgetプロバイダーやサービスに関する情報を記述します。
<receiver>タグで、AppWidgetプロバイダーに関する設定を行います。
<service>タグで、サービスに関する設定を行います。
<receiver
android:name="TetherWidget"
android:label="TetherWidget" >
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>
<meta-data
android:name="android.appwidget.provider"
android:resource="@xml/tetherwidget" />
</receiver>
<intent-filter>タグ内に<action>というタグがありますが、これにより、APPWIDGET_UPDATEというアクションに対応するように指定しています。
(ただし、今回は、定期的な更新処理は使っていません)
<service
android:name="TetherService" >
<intent-filter>
<action android:name="BUTTON_CLICK_ACTION" />
</intent-filter>
</service>
<intent-filter>タグ内に<action>タグが用意されています。
これにより、BUTTON_CLICK_ACTION というアクションに対応するように指定しています。
BUTTON_CLICK_ACTION というアクションは、プログラマが任意に決めたものです。
これでようやく3つのXMLファイルができました
続いて、Javaソースコードの作成に進みます
まずは、AppWidgetプロバイダーのクラスです。
これは「AppWidgetProvider」というクラスとして用意されており、これを継承してクラスを定義します。
クラスの基本形を整理すると次のようになります。
public class クラス名 extends AppWidgetProvider {
@Override
public void onEnabled(Context context) {
……略……
}
@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager,
int[] appWidgetIds) {
……略……
}
@Override
public void onDisabled(Context context) {
……略……
}
@Override
public void onDeleted(Context context, int[] appWidgetIds) {
……略……
}
}
● AppWidgetProviderには、全部で4つのメソッドが用意されています。
これらは、必要に応じてオーバーライドして利用します。
それぞれのメソッドの役割をざっと整理しておきます。
onEnabled ――利用可能になったときに呼び出される。
onUpdate ――システムによりAppWidgetの更新の要求があったときに呼び出されます。
onDisabled ――利用不可になったときに呼び出される。
onDelete ――破棄される際に呼び出される。
これらは、すべて用意する必要はありません。
通常は、onUpdateが1つあれば十分です。
ここで必要な処理を用意しておく必要がありますから onUpdate は必要ですが、
それ以外のメソッドはなくとも問題はありません。
★TetherWidget.javaの作成
public class TetherWidget extends AppWidgetProvider {
@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
// サービスの起動
Intent intent = new Intent(context, TetherService.class);
context.startService(intent);
}
}
ここで用意する必要があるのは、onUpdateだけです
onUpdate で、AppWidget がホームスクリーンに貼り付けられる際の処理を用意しておきます。
今回は、「Intent(インテント)」と呼ばれるものを用意し、サービスを実行する処理を用意しています。
Intent は、サービスやプログラムを起動するのに使われるものです。
これは、以下のような形でインスタンスを作成します。
new Intent( [Context] , [サービスのクラス] );
こうして作成した Intent は、Context の「startService」を呼び出すことで実行されます。
ここでは、TetherService というサービスを実行しています。
ボタンをクリックしたときの処理を、このサービスに行わせることになります。
★サービス・クラスを作成する
サービスは、「Service」というクラスを継承して作成します。
この基本的な形を整理すると、だいたい以下に掲載しているようになります。
public class MyService extends Service { @Override public void onStart(Intent intent, int startId) { ……開始時の処理…… } @Override public IBinder onBind(Intent intent) { ……バインド時の処理…… }}
サービス・クラスには、2つの処理が最低限必要です。
1つは、サービス開始時の処理。
もう1つは、そのサービスに(どこかのプログラムが)バインドしたときの処理。
サービスはバックグラウンドで実行されます。
そして、プログラムから実行中のサービスにバインドをして結びつけることで、そのサービスを利用できるようになります。
このため、2つの処理が必ず必要になるのです。
といっても、これらで必ず何かをしないといけない、というわけではありません。
今回は、AppWidgetでボタンをクリックしたときの処理を、サービスにやらせるので、初期化処理だけあればそれで十分。
バインド時の処理などは不要です。
が、それでもメソッドだけは用意しておく必要があります。
★TetherServiceサービスを作成するpublic class TetherService extends Service {
private final String BUTTON_CLICK_ACTION =
"BUTTON_CLICK_ACTION";
@Override
public void onStart(Intent intent, int startId) {
super.onStart(intent, startId);
}
@Override
public IBinder onBind(Intent intent) {
return null;
}
}
サービス開始時の処理
★サービス開始時の処理// ボタンが押された時に発行されるインテントを準備する
Intent buttonIntent = new Intent();
buttonIntent.setAction(BUTTON_CLICK_ACTION);
PendingIntent pendingIntent = PendingIntent.getService(this, 0,buttonIntent, 0);
RemoteViews remoteViews = new RemoteViews(getPackageName(),
R.layout.layout_tether_widget);
remoteViews.setOnClickPendingIntent(R.id.button, pendingIntent);
// ボタンが押された時に発行されたインテントの場合の処理
if (BUTTON_CLICK_ACTION.equals(intent.getAction())) {
tethering(); // テザリング設定
}
// AppWidgetの画面更新
ComponentName thisWidget = new ComponentName(this, TetherWidget.class);
AppWidgetManager manager = AppWidgetManager.getInstance(this);
manager.updateAppWidget(thisWidget, remoteViews);
private void tethering() {
Intent intent = new Intent(Intent.ACTION_MAIN);
intent.setClassName("com.android.settings",
"com.android.settings.wifi.WifiApSettings");
try {
// Activity以外からActivityを呼び出すためのフラグを設定
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
} catch (Exception e) {
Log.e(TAG, "cannot start the activity\n" + e);
}
}
これでできあがりです。
プログラムをインストールしたら、ホームスクリーンをタップし続け(押しっぱなし)ます。
画面にリストが現れます。
ここから「Widgets」を選ぶと、現在インストールされているAppWidgetが一覧で表示されます。
この中に、作成した「TetherWidget」も表示されます。
これを選ぶと、TetherWidget(AppWidget)がホームスクリーンに貼り付けられます。
ボタンをクリックしてみましょう。
テザリングの設定画面になります。