Unlockイベント
BroadcastRecieverが必要?http://stackoverflow.com/questions/3462843/android-what-happens-when-device-is-unlocked
http://d.hatena.ne.jp/eryngii_mori/20100520/1274357535
原宿Android勉強会#15@THETERMINAL
URL:http://atnd.org/events/26535Androidアプリ勉強したいので参加、常駐してアイコンが動的に変わるのを作りたかった
・Widget
→ブロードキャストレシーバを使う。
・わかりやすい(日本語)
http://www.techfirm.co.jp/lab/android/widget.html
・わかりやすい(英語)
http://www.vogella.de/articles/AndroidWidgets/article.html
→日本語の解説
1.3. Register Widget(ウィジットの登録)
AppWidgetをAndroidManifest.xml
・AndroidManifest.xml(あとの3でも全ソースが記載されている)
<receiver android:icon="@drawable/icon" android:label="Example Widget" android:name="MyWidgetProvider" > <intent-filter > <action android:name="android.appwidget.action.APPWIDGET_UPDATE" /> </intent-filter> <meta-data android:name="android.appwidget.provider" android:resource="@xml/widget_info" /> </receiver>
※この時点で「widget_info」ではエラーが出るが、"3"で作るので気にしない。
・widget_info.xml(※3でまた書かれてます)
※resフォルダ内に「xml」フォルダを作成してその中へ配置
右クリックメニューより、「新規」→「Android XML file」を選択。
リソースの種類:AppWidget Provider
<?xml version="1.0" encoding="utf-8"?> <appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android" android:initialLayout="@layout/widget_layout" android:minHeight="72dp" android:minWidth="146dp" android:updatePeriodMillis="180000" </appwidget-provider>
※layout/widget_layoutは後で作るので、「layout/widget_layout」がないぞっていうエラーは無視する。
3. Example with fixed update interval(固定のアップデートインターバルの例)
「/res/drawable-mdpi」に「myshape.xml」を作成する
・myshape.xml
<?xml version="1.0" encoding="UTF-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle"> <stroke android:width="2dp" android:color="#FFFFFFFF" /> <gradient android:angle="225" android:endColor="#DD2ECCFA" android:startColor="#DD000000" /> <corners android:bottomLeftRadius="7dp" android:bottomRightRadius="7dp" android:topLeftRadius="7dp" android:topRightRadius="7dp" /> </shape>
「res/layout」に「widget_layout.xml」を作成する。
・widget_layout.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/layout" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_margin="8dip" android:background="@drawable/myshape" > <TextView android:id="@+id/update" style="@android:style/TextAppearance.Medium" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_gravity="center" android:gravity="center_horizontal|center_vertical" android:layout_margin="4dip" android:text="Static Text"> </TextView> </LinearLayout>
・MyWidgetProvider.java
※「package com.shinriyo.widget;」はご自分の環境にあわせて適宜変更します。
package com.shinriyo.widget; import java.util.Random; import android.app.PendingIntent; import android.appwidget.AppWidgetManager; import android.appwidget.AppWidgetProvider; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.util.Log; import android.widget.RemoteViews; public class MyWidgetProvider extends AppWidgetProvider { // 使われない?? private static final String ACTION_CLICK = "ACTION_CLICK"; @Override public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) { // すべてのID取得 ComponentName thisWidget = new ComponentName(context, MyWidgetProvider.class); int[] allWidgetIds = appWidgetManager.getAppWidgetIds(thisWidget); for (int widgetId : allWidgetIds) { // 乱数の生成 int number = (new Random().nextInt(100)); RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.widget_layout); Log.w("WidgetExample", String.valueOf(number)); // テキストをセットする remoteViews.setTextViewText(R.id.update, String.valueOf(number)); // onClickListenerの登録 Intent intent = new Intent(context, MyWidgetProvider.class); intent.setAction(AppWidgetManager.ACTION_APPWIDGET_UPDATE); intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, appWidgetIds); PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT); remoteViews.setOnClickPendingIntent(R.id.update, pendingIntent); appWidgetManager.updateAppWidget(widgetId, remoteViews); } } }
・AndroidManifest.xml もいじる
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="de.vogella.android.widget.example" android:versionCode="1" android:versionName="1.0" > <application android:icon="@drawable/icon" android:label="@string/app_name" > <receiver android:name="MyWidgetProvider" > <intent-filter > <action android:name="android.appwidget.action.APPWIDGET_UPDATE" /> </intent-filter> <meta-data android:name="android.appwidget.provider" android:resource="@xml/widget_info" /> </receiver> </application> <uses-sdk android:minSdkVersion="8" /> </manifest>
『3までで取り敢えず起動はできます』
動作内容:
ホームを押しっぱなしで、起動→ウィジット→Example Widget
ホームにでた青いグラデーションの四角を叩くと0〜99の数字が表示される。
4から、先ほどの「MyWidgetProvider.java」の内部処理を「UpdateWidgetService.java」に分割します。
4. Update via a service and onClickListener(サービスとオンクリックのリスナーによるアップデート)
・UpdateWidgetService.java 作成
※「package com.shinriyo.widget;」はご自分の環境にあわせて適宜変更します。
package com.shinriyo.widget; import java.util.Random; import android.app.PendingIntent; import android.app.Service; import android.appwidget.AppWidgetManager; import android.content.ComponentName; import android.content.Intent; import android.os.IBinder; import android.util.Log; import android.widget.RemoteViews; public class UpdateWidgetService extends Service { private static final String LOG = "com.shinriyo.widget example"; @Override public void onStart(Intent intent, int startId) { Log.i(LOG, "Called"); AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(this.getApplicationContext()); int[] allWidgetIds = intent.getIntArrayExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS); ComponentName thisWidget = new ComponentName(getApplicationContext(), MyWidgetProvider.class); int[] allWidgetIds2 = appWidgetManager.getAppWidgetIds(thisWidget); Log.w(LOG, "From Intent" + String.valueOf(allWidgetIds.length)); Log.w(LOG, "Direct" + String.valueOf(allWidgetIds2.length)); for (int widgetId : allWidgetIds) { // 乱数の生成 int number = (new Random().nextInt(100)); RemoteViews remoteViews = new RemoteViews(this .getApplicationContext().getPackageName(), R.layout.widget_layout); Log.w("WidgetExample", String.valueOf(number)); // テキストをセットする remoteViews.setTextViewText(R.id.update, "Random: " + String.valueOf(number)); // onClickListenerの登録 Intent clickIntent = new Intent(this.getApplicationContext(), MyWidgetProvider.class); clickIntent.setAction(AppWidgetManager.ACTION_APPWIDGET_UPDATE); clickIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, allWidgetIds); PendingIntent pendingIntent = PendingIntent.getBroadcast(getApplicationContext(), 0, clickIntent, PendingIntent.FLAG_UPDATE_CURRENT); remoteViews.setOnClickPendingIntent(R.id.update, pendingIntent); appWidgetManager.updateAppWidget(widgetId, remoteViews); } stopSelf(); super.onStart(intent, startId); } @Override public IBinder onBind(Intent intent) { return null; } }
・「AndroidManifest.xml」に次に作るJavaを登録しておく
<service android:name=".UpdateWidgetService"></service>
・先程の「MyWidgetProvider」を修正する
※消したところと追加したところを記載しました
package com.shinriyo.widget; //import java.util.Random; //import android.app.PendingIntent; import android.appwidget.AppWidgetManager; import android.appwidget.AppWidgetProvider; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.util.Log; //import android.widget.RemoteViews; public class MyWidgetProvider extends AppWidgetProvider { // 使われない?? // private static final String ACTION_CLICK = "ACTION_CLICK"; private static final String LOG = "com.shinriyo.widget example"; @Override public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) { Log.w(LOG, "onUpdate method called"); // 追加 // すべてのID取得 ComponentName thisWidget = new ComponentName(context, MyWidgetProvider.class); int[] allWidgetIds = appWidgetManager.getAppWidgetIds(thisWidget); // 追加 // サービスによりインテントの開始 Intent intent = new Intent(context.getApplicationContext(), UpdateWidgetService.class); intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, allWidgetIds); // サービスによるウィジットのアップデート context.startService(intent); /* for (int widgetId : allWidgetIds) { // 乱数の生成 int number = (new Random().nextInt(100)); RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.widget_layout); Log.w("WidgetExample", String.valueOf(number)); // テキストをセットする remoteViews.setTextViewText(R.id.update, String.valueOf(number)); // onClickListenerの登録 Intent intent = new Intent(context, MyWidgetProvider.class); intent.setAction(AppWidgetManager.ACTION_APPWIDGET_UPDATE); intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, appWidgetIds); PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT); remoteViews.setOnClickPendingIntent(R.id.update, pendingIntent); appWidgetManager.updateAppWidget(widgetId, remoteViews); } */ } }
→動作:
複数のウィジットが作成でき、1つのウィジットにタッチするとすべてのウィジットにランダムな数が反映される。
・細かい説明があるサイト(英語)
http://blog.doityourselfandroid.com/2011/05/24/developing-android-home-screenwidgets/
SQLAlchemyのわかりやすいところ
→チュートリアル風になってる・その1
http://d.hatena.ne.jp/TaoPyPI/20090131/1233414685
・その2
http://d.hatena.ne.jp/TaoPyPI/20090212/1234457633
quicktigame2d
Titanium用の2Dモジュールhttp://code.google.com/p/quicktigame2d/