Hatena::ブログ(Diary)

万年素人からGeekへの道 このページをアンテナに追加 RSSフィード Twitter

2014/8/19に移行した→ 万年素人からHackerへの道
 | 

2012-03-20 Tuesday このエントリーを含むブックマーク このエントリーのブックマークコメント

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/26535

Androidアプリ勉強したいので参加、常駐してアイコンが動的に変わるのを作りたかった

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<application>のタグ内へ登録します

・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を登録しておく

<application>と</application>の間に記載する

<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/

 |