Androidの最近のブログ記事

twitter4j_oauth.png

Android で Twitter4J を使用し、Twitter の OAuth 処理を行うクラスを作成しました。

特徴としては、動的に WebView を作成し、コールバックページのフックをソースコードで記述しているため、

リソースファイルや AndroidManifest.xml への独自スキーマのための定義が不要であり、

本クラス(1ファイル)を導入するだけで認証できるようになります

※もちろん AndroidManifest.xml への Activity の追加は必要です^^;

※Android 1.5 以降 + twitter4j-android-2.2.2 で確認済

 

使い方

  • 呼び出し方法

OAuth画面をさせるには、自アプリ用のコールバック文字列、認証用文字列をインテントに設定して呼び出すだけ。

Intent intent = new Intent(this, OAuthActivity.class);
intent.putExtra(OAuthActivity.CALLBACK, CALLBACK);
intent.putExtra(OAuthActivity.CONSUMER_KEY, CONSUMER_KEY);
intent.putExtra(OAuthActivity.CONSUMER_SECRET, CONSUMER_SECRET);
startActivityForResult(intent, REQUEST_OAUTH);

 

  • 結果の取得方法

認証結果は、呼び出し元のonActivityResult()でインテントにセットして返されますので、必要な情報を取得するだけ。

long userId = data.getLongExtra(OAuthActivity.USER_ID, 0);
String screenName = data.getStringExtra(OAuthActivity.SCREEN_NAME);
String token = data.getStringExtra(OAuthActivity.TOKEN);
String tokenSecret = data.getStringExtra(OAuthActivity.TOKEN_SECRET);                

 

OAuth 認証コード(一部)

さて、(何故か)ここでお題。。。

認証処理で必要な処理のうち、getOAuthRequestToken() と getOAuthAccessToken() メソッドは、

呼び出しに時間のかかる処理であり、メイン(UI)スレッドでは呼び出してはいけない処理です。

以下では、AsyncTask で実装しましたが、コードも長くなり、いささか気持ち悪いです。

他にも Thread + Handler などの実装方法が考えられますが、もっとスマートな書き方はないでしょうか?

もっといい書き方あるよ!という方は、Twitter で(ry...

※6/5追記:環境によってはshouldOverrideUrlLoading()でフックできない場合があるようです(謎)。
その場合、onPageStarted()で代替できますので、そちらをお使いください。。。

public class OAuthActivity extends Activity {

    // Activity開始時のインテントパラメータ
    public static final String CALLBACK = "callback";
    public static final String CONSUMER_KEY = "consumer_key";
    public static final String CONSUMER_SECRET = "consumer_secret";

    // Activity終了時のインテントパラメータ
    public static final String USER_ID = "user_id";
    public static final String SCREEN_NAME = "screen_name";
    public static final String TOKEN = "token";
    public static final String TOKEN_SECRET = "token_secret";

    private static final String OAUTH_VERIFIER = "oauth_verifier";
    
    private WebView mWebView;
    private String mCallback;
    private Twitter mTwitter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setResult(Activity.RESULT_CANCELED);

        // プログレス表示
        requestWindowFeature(Window.FEATURE_PROGRESS);
        requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);

        // Viewのセットアップ
        mWebView = new WebView(this);
        WebSettings webSettings = mWebView.getSettings();
        webSettings.setSavePassword(false);
        mWebView.setWebChromeClient(mWebChromeClient);
        mWebView.setWebViewClient(mWebViewClient);
        setContentView(mWebView);

        // TwitterのOAuth認証画面で毎回ユーザ名、アカウントを入力させるために必要
        CookieManager cookieManager = CookieManager.getInstance();
        cookieManager.setAcceptCookie(false);

        Intent intent = getIntent();
        mCallback = intent.getStringExtra(CALLBACK);
        String consumerKey = intent.getStringExtra(CONSUMER_KEY);
        String consumerSecret = intent.getStringExtra(CONSUMER_SECRET);
        if ((mCallback == null) || (consumerKey == null)
                || (consumerSecret == null)) {
            finish();
        }

        mTwitter = new TwitterFactory().getInstance();
        mTwitter.setOAuthConsumer(consumerKey, consumerSecret);

        PreTask preTask = new PreTask();
        preTask.execute();
    }

    // 前処理
    public class PreTask extends AsyncTask<Void, Void, String> {

        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            setProgressBarIndeterminateVisibility(true);
        }

        @Override
        protected String doInBackground(Void... params) {
            String authorizationUrl = null;
            try {
                // 非同期処理が必要なメソッドの呼び出し
                RequestToken requestToken = mTwitter.getOAuthRequestToken();
                if (requestToken != null) {
                    authorizationUrl = requestToken.getAuthorizationURL();
                }
            } catch (TwitterException e) {
                e.printStackTrace();
            }
            return authorizationUrl;
        }

        @Override
        protected void onPostExecute(String result) {
            super.onPostExecute(result);
            setProgressBarIndeterminateVisibility(false);
            if (result != null) {
                mWebView.loadUrl(result);
            } else {
                finish();
            }
        }

    }

    private WebChromeClient mWebChromeClient = new WebChromeClient() {

        @Override
        public void onProgressChanged(WebView view, int newProgress) {
            super.onProgressChanged(view, newProgress);
            setProgress(newProgress * 100);
        }

    };

    private WebViewClient mWebViewClient = new WebViewClient() {

        // 特定のページをフック
        @Override
        public boolean shouldOverrideUrlLoading(WebView view, String url) {
            boolean result = true;
            if ((url != null) && (url.startsWith(mCallback))) {
                Uri uri = Uri.parse(url);
                String oAuthVerifier = uri.getQueryParameter(OAUTH_VERIFIER);
                PostTask postTask = new PostTask();
                postTask.execute(oAuthVerifier);
            } else {
                result = super.shouldOverrideUrlLoading(view, url);
            }
            return result;
        }

    };

    // 後処理
    public class PostTask extends AsyncTask<String, Void, AccessToken> {

        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            setProgressBarIndeterminateVisibility(true);
        }

        @Override
        protected AccessToken doInBackground(String... params) {
            AccessToken accessToken = null;
            if (params != null) {
                try {
                    // 非同期処理が必要なメソッドの呼び出し
                    accessToken = mTwitter.getOAuthAccessToken(params[0]);
                } catch (TwitterException e) {
                    e.printStackTrace();
                }
            }
            return accessToken;
        }

        @Override
        protected void onPostExecute(AccessToken result) {
            super.onPostExecute(result);
            setProgressBarIndeterminateVisibility(false);
            if (result != null) {
                long userId = result.getUserId();
                String screenName = result.getScreenName();
                String token = result.getToken();
                String tokenSecret = result.getTokenSecret();
                Intent intent = new Intent();
                intent.putExtra(USER_ID, userId);
                intent.putExtra(SCREEN_NAME, screenName);
                intent.putExtra(TOKEN, token);
                intent.putExtra(TOKEN_SECRET, tokenSecret);
                setResult(Activity.RESULT_OK, intent);
            }
            finish();
        }

    }

}

eula.png

アプリでよく使用する End User License Agreement (EULA)

Google I/O 2011 のアプリ(iosched)のソースコードを見ていたら入っていたので、ソース場所を共有しておきます。

 

EulaHelper

 

実装は、Accept されたかどうかを SharedPreferences に保存し、ダイアログ表示するだけのもの。

adk.jpg

Google I/O 2011 で発表された「Open Accessory Development Kit (ADK)」を使ってみました。

 

試した環境

  • Ubuntu 10.10 (64bit)
  • Nexus S 2.3.4
  • Arduino 0022 + adk_release_0512.zip + CapacitiveSense003.zip

 

PC に Arudiono IDE と必要なライブラリをインストールする

1. Arduino Software を ココ からダウンロードし、任意の場所に展開する

2. CapSense library を ココ からダウンロードし、任意の場所に展開する

3. The ADK package を ココ からダウンロードし、任意の場所に展開する

4. (手順)2 で得られたディレクトリ直下に含まれる CapSense.h と CapSense.cpp を

 (手順)1 で得られた arduino/libraries ディレクトリ直下に、新たに CapSense ディレクトリを作成し、

 同ディレクトリ下にコピーする

5. (手順)3 で得られた firmware/arduino_libs/AndroidAccessory ディレクトリと

 firmware/arduino_libs/USB_Host_Shield ディレクトリを、

 (手順)1 で得られた arduino/libraries ディレクトリ直下に(ディレクトリごと)コピーする

<完成図>

arduino を展開したディレクトリの libraries 下の構成が以下のようになっていればOK。

arduino-0022-libraries.png 

 

ADK ボードのファームウェア書き換える

I/O で配布された状態でも動作するのですが、このままだとタッチセンサーが動作しないため、ファームウェアを書き換えます。

1) ADK ボードと PC を USB 接続する

2) PC 側で(コマンドラインから上記でインストールしたディレクトリ直下にある)arduino (IDE)を起動する

3) (arduino IDE)初回起動時、「Select folder for sketches...」のようにディレクトリ選択画面が表示されるので、

 任意のディレクトリを選択し、arduino IDE を起動する

4) Tools > Board > Arduino Mega 2560 を選択する

5) Tools > Serial Port > /dev/ttyUSB0 (名称は環境依存)を選択する

6) File > Open から、(先のインストール手順でダウンロードした)The ADK package に含まれる

 firmware/demokit/demokit.pde を選択し、sketch を開く

7) Sketch > Verify / Compile からコンパイルする(Done compiling. と表示されればOK)

8) File > Upload to I/O Board で ADK ボードに転送する(Done uploading. と表示されればOK)

demokit.png

 

Android 端末に ADK のサンプルアプリをインストールする

1. android コマンドから「Google APIs API Level 10 add-on library」をインストールする

2. Eclipse を起動し、New > Project > Android Project、Create project from existing source で

 (先のインストール手順でダウンロードした)The ADK package に含まれる app プロジェクトを選択、

 Buile Target を Google APIs (Platform 2.3.3) に変更し、Finish

3. プロジェクトをビルドし、PC と Android 端末を USB 接続して、アプリケーションを転送する

 

ADK ボードを Android アプリケーションから操作する!

Android 端末と ADK ボードを接続すると、DemoKit ダイアログが表示されるので OK をタップ。

ADK ボード側の Temp / Light / Buttons / Joystick のセンサー値がアプリ画面の In タブ、

アプリ画面の Out 画面で操作した結果が、ADK ボードに反映されます。

in.png

out.png

adk_board.jpg

 

備考

  • 事前に、Ubuntu への arduino のインストールを sudo apt-get install arduino から実行したため、
    上記手順だけだと、必要なライブラリのインストールが足りないと思います(汗)
    ※ちなみに apt-get からだと arduino 0018 がインストールされますが、
     コンパイルエラーとなるため 0022 の圧縮ファイルをダウンロード・展開し直しました
  • arudino IDE 起動時、
    「java.lang.UnsatisfiedLinkError: no rxtxSerial in java.library.path thrown while loading gnu.io.RXTXCommDriver」
    のようなエラーが出た場合、以下のサイトを参考にエラーを回避できました
    http://colinharrington.net/blog/2010/11/arduino-ubuntu-10-10-maverick-meerkat-no-rxtxserial/

 

あわせて読みたい

Google I/O 2011 で予定されているセッションのうち、Android 関連のものをピックアップし、表にしてみました。

 

概要

  • Android 関連のセッションは、全部で21セッションある
  • それらは、Room8(2F)、Room9(2F)、Room11(3F)で開催される
  • Room11 のみ LIVE STREAMING される
  • セッションレベルは、101(初級)、201(中級)、301 (上級)の3種類

sessions_color.png

 

2011/5/10 Android 関連セッション

io2011_0510_android.png

 

2011/5/11 Android 関連セッション

io2011_0511_android.png

 

Map

MAP3F.pngMAP2F.png

 

受講したいセッション(adakoda)

starred10.png starred11.png

  • 初日(10日)は、ずっと Room 11
  • 二日目(11日)は、Room 9 > 11 > 8 > 9 > 9
  • 一番興味深いのが、(キャプチャ切れましたが)最後のメモリ管理のセッション

 

※上記表はGoogle Docsで作成しており、以下のリンクからも参照できます

https://spreadsheets.google.com/ccc?key=0AkHlMPkv8YCOdFpZUDJ1V3ZlUk9TS1ZQVkxiTFc4ZkE&hl=ja&authkey=CNqDi7UF

[Android] twicca supporters

| トラックバック(0) |

twicca バージョン 0.9.0RC からアプリ内課金を利用した「twicca サポーター」が追加されました。

 

twicca サポーターとは?

twicca では今後の開発およびメンテナンスを続けるためのサポーターを募集しています。

サポーターの皆さんのお名前は『twiccaについて』の中に掲載させていただきます。

twicca サポーターになるにはサポーターチケットを購入してください。

 

早い話が、今まで「青山さん、俺だ!振込先を教えてくれー!」って言っていた人の思いが通じたということです。

 

購入するには、「メニュー」 > 「その他」 > 「twiccaサポーターズ」を選択後、

日数を選択し、「購入する」ボタンを、ポチるだけです。

※アプリ内課金は有料アプリと異なり、キャンセルできませんので、ご注意ください

※サポーターズチケットは、「7日間(1週間)105円」~選択できるようです(2011年5月5日現在)

 

twicca_supporters.png twicca_supporters2.png

twicca_supporters3.pngtwicca_supporters4.png

twicca_supporters5.png

 

購入後は、「メニュー」 > 「その他」 > 「twiccaについて」から、名前を確認できます。

twicca_supporters6.png

 

こういったアプリ内課金の使い方は、おそらく国内では初?と思われます。

素晴らしいアプリは評価される風土が根付いて欲しいですね。

2011年3月29日、東京電力の最大供給量と使用量を取得できる API が公開されました。

 

同 API については、先日(3月19日~21日)開催された Hack for Japan でも要望のあったものです。

Yahoo!デベロッパーネットワークさん、仕事が早いですね。さすが!

 

API 解説

 

本 API を使用することにより、東電の最大供給量と電力使用量を、XML または JSON 形式で取得できるようです。

ただし、期間限定の API であり、終了日は未定とのことです。

また、 API の使用にあたり、アプリケーションID が必要であり、かつ、

24 時間中 1 アプリケーション ID につき 50000 件のリクエストが上限とのことですので、注意が必要です。

(現実的には、キャッシュサーバー用意する必要あり?)

 

以下、早速 Android から呼び出してみました。

一応、API を簡単に使えるようなラッパークラスを作成し、2 行書けば取得できるようにしています。

※誌面の都合上、エラー処理や諸々省略しています

※完全なコードは、Google Code からチェックアウトできます

 

サンプルソースコード

public class SetsudenClient {
    private String mAppID;
    public SetsudenClient(String appID) {
        mAppID = appID;
    }
    public LatestPowerUsageResult getLatestPowerUsage() {
        LatestPowerUsageResult result = new LatestPowerUsageResult();
        // Build uri
        Uri.Builder uriBuilder = new Uri.Builder();
        uriBuilder.path("http://setsuden.yahooapis.jp/v1/Setsuden/latestPowerUsage");
        uriBuilder.appendQueryParameter("appid", mAppID);
        uriBuilder.appendQueryParameter("output", "json");
        String uri = Uri.decode(uriBuilder.build().toString());
        // Request HTTP GET
        HttpUriRequest httpGet = new HttpGet(uri);
        DefaultHttpClient defaultHttpClient = new DefaultHttpClient();
        try {
            HttpResponse httpResponse = defaultHttpClient.execute(httpGet);
            String stringEntity = EntityUtils.toString(httpResponse.getEntity());
            // Parse JSON result
            JSONObject jsonEntity = new JSONObject(stringEntity);
            if (jsonEntity != null) {
                JSONObject jsonElectricPowerUsage =
                    jsonEntity.optJSONObject("ElectricPowerUsage");
                if (jsonElectricPowerUsage != null) {
                    result.setArea(jsonElectricPowerUsage.optString("Area"));
                    JSONObject jsonUsage =
                        jsonElectricPowerUsage.optJSONObject("Usage");
                    if (jsonUsage != null) {
                        result.setUsageUnit(jsonUsage.optString("@unit"));
                        result.setUsageValue(jsonUsage.optInt("$"));
                    }
                    JSONObject jsonCapacity =
                        jsonElectricPowerUsage.optJSONObject("Capacity");
                    if (jsonCapacity != null) {
                        result.setCapacityUnit(jsonCapacity.optString("@unit"));
                        result.setCapacityValue(jsonCapacity.optInt("$"));
                    }
                    result.setDate(jsonElectricPowerUsage.optString("Date"));
                    result.setHour(jsonElectricPowerUsage.optString("Hour"));
                }
            }
        } catch (ClientProtocolException e) {
        } catch (IOException e) {
        } catch (JSONException e) {
        }
        return result;
    }
}

 

public class SetsudenYahooAPISampleActivity extends Activity {
    private static final String TAG = "SetsudenYahooAPISampleActivity";
    private static final String MY_APP_ID = "XXXXXXXXXX"; // 取得したappidで置き換えてください
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        // 非同期処理
        SetsudenClientTask setsudenClientTask = new SetsudenClientTask();
        setsudenClientTask.execute();
    }
    class SetsudenClientTask extends AsyncTask<Void, Void, LatestPowerUsageResult> {
        protected LatestPowerUsageResult doInBackground(Void... params) {
            // 電力使用状況APIのラッパークラスの呼び出し例
SetsudenClient setsudenClient = new SetsudenClient(MY_APP_ID); return setsudenClient.getLatestPowerUsage(); } protected void onPostExecute(LatestPowerUsageResult result) { // LogCat の出力結果
Log.v(TAG, "Area = " + result.getArea()); Log.v(TAG, "Usage = " + result.getUsageValue() + result.getUsageUnit()); Log.v(TAG, "Capacity = " + result.getCapacityValue() + result.getCapacityUnit()); Log.v(TAG, "Date = " + result.getDate()); Log.v(TAG, "Hour = " + result.getHour()); } } }

 

実行結果(DDMS のLogCat 画面)

ddms_output.png

google_code_android_screen_monitor.png

Android 端末(実機、またはエミュレーター)の画面をリアルタイムで PC 上に表示するツールである

Android Screen Monitor のソースコードを公開しました(Apache License 2.0)。

以下のサイトからチェックアウトできます。

 

android-screen-monitor - Project Hosting on Google Code

http://code.google.com/p/android-screen-monitor/

 

引き続き、製品のデモンストレーション、勉強会などのプレゼンテーション等でお使いいただければと思います^^

Androidify.png

Google から Androidify という Android Robot のアバターを作成できる Android アプリケーションがリリースされました。

 

概要

以下の動画のように、髪型や洋服などを選んでいくだけで、自分好みのアバターが作ることができます。

 

Androidify

以下の公式サイトからインストールすることができます。

※Android2.1以降で動作します
※日本語アプリ名は「Androidメーカー」
※Androidify is an application developed together by Google Creative Lab & Larva Labs.

 

早速作ってみました!

kuroharukakka.png

 。。。

ちなみに作成した画像については保存するだけでなく、他のアプリと共有できますので、Twitter に投稿してみても面白いかもしれません。

 

本日見た限りでは、Twitter のタイムラインに流れていた  「Twicca の作者さん(外部リンク)」 の以下の作品が秀逸でした(似すぎwww)。

R246.png

yahoo_map.png

2011年2月7日、「Yahoo!地図 SDK for Android」が公開されました。

 

Yahoo!地図 SDK for Android

 

概要

  • 「Yahoo!地図 SDK for Android」を使用することにより、「Yahoo!地図」と同じ地図データを利用できる
  • Android 2.1 以降で動作する
  • 有償で販売、またはアプリ内で課金してはいけない ※詳細は「Yahoo! JAPAN - サービス利用規約」(特に第5章)参照
  • アプリの配布時およびアプリ内において、「クレジット表示」が必要
  • 「Yahoo!デベロッパーネットワーク」の「アプリケーションID」が必要
  • 「Yahoo!地図 SDK for Android」には、Javaライブラリー(ymap.jar)と画像リソース(res)が格納されている
  • 「Yahoo!地図 SDK for Android ドキュメント」には、大変わかり易いHTMLが格納されている

 

サンプルソースコード 

package com.adakoda.android.yahoomapsample;

import jp.co.yahoo.android.maps.GeoPoint;
import jp.co.yahoo.android.maps.MapActivity;
import jp.co.yahoo.android.maps.MapController;
import jp.co.yahoo.android.maps.MapView;
import android.os.Bundle;

// 3. 「Yahoo!地図」を表示したいアクティビティを(jp.co.yahoo.android.maps.)MapActivity を継承して作成する
public class YahooMapSampleActivity extends MapActivity {
    private static final String APP_ID = "取得したアプリIDに書き変えてください!";
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // 5. MapView を(アプリケーションID渡しで)生成し、
        // getMapController() で取得した MapController で、表示位置などの設定をする
        MapView mapView = new MapView(this, APP_ID);
        MapController c = mapView.getMapController();
        c.setCenter(new GeoPoint(35632385, 139881695)); // 初期表示の地図を指定
        c.setZoom(3); // 初期表示の縮尺を指定
        mapView.setMapType(mapView.MapTypeSatellite); // 航空写真表示(オプショナル)
        // 6. MapActivity に MapView を設定し、表示させる
        setContentView(mapView);
    }
    // 4. MapActivity.isRouteDisplayed をオーバーライドする
    @Override
    protected boolean isRouteDisplayed() {
        return false;
    }
}

1. SDK 内の「ymap.jar」を、組み込みたいアプリのプロジェクトに追加し、ライブラリーのパスを通す

2. SDK 内の「res/drawable-hdpi」下のpngファイル(6つ)を、組み込みたいアプリのプロジェクトにコピーする

3. 「Yahoo!地図」を表示したいアクティビティを(jp.co.yahoo.android.maps.)MapActivity を継承して作成する

4. MapActivity.isRouteDisplayed をオーバーライドする

5. MapView を(アプリケーションID渡しで)生成し、getMapController() で取得した MapController で、表示位置などの設定をする

6. MapActivity に MapView を設定し、表示させる

7. AndroidManifest.xml に android.permission.INTERNET を追加する

 

実行結果

TDR.png

Web Services by Yahoo! JAPAN

 

あわせて読みたい

market.png

2011年2月2日(現地時間)、Android Market (Web 版) がリニューアルされました。

 

Android Market web store ・・・Android Market (Web版)

 

今回のリニューアルにより、

PC からアクセスした Android Market (Web 版)から

スマートフォンやタブレットなどの Android 端末に Push(OTA)インストールができるようになりました。

 

 

早速、「(=x=)ヒャッハー」 を PC からインストールしてみました。

 

1. 右上の検索ボックスから 「ひゃっはー」 と入力したところ、

ぐぐるさんが 「DID YOU MEAN? ヒャッハー」 というように、あいまい検索結果やフィルタ検索にも対応しています。

market_search.png

 

2. 可愛らしいモグタソアイコンをクリックしてみると、Android 端末版の Android Market のようにアプリケーション情報が表示されます。

内容を確認し、アイコンの横にある 「INSTALL」 ボタンをクリックします。

market_app1.png

 

3. インストール先の Android 端末を選択し、「INSTALL」 をクリックします。

market_install1.png

 

4. すると、自動的に Android 端末側で Android Market からのアプリケーションのダウンロードが開始され、インストールが行われます。

※下図は、まさにクラウドからスマートフォンに、もの凄いスピードで (=X=) が侵略しようとしている決定的瞬間

market_install2.png

 

5. 以上で、インストール完了です。

ちなみに、Android Market サイトの下部にある 「My Market Account」 から、

「ORDERS」 タブで インストール済みのアプリケーションの一覧を閲覧、

「SETTINGS」 タブで 接続先デバイスの一覧の設定をすることもできます。

market_my_orders.png

 

 

これまでは、Web から Android アプリケーションをプロモーションする時には、

Android 端末専用の market プロトコルを使用するか、androlib などのサイトを利用していましたが、

今後は、単純な Web のリンク(http プロトコル)で済むようになったため、

これまで以上に、アプリケーションのプロモーションがし易くなったと思います。

<<前のページへ 1234567891011

Android Advent Calendar 2011

2012年2月

      1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29