Category Archives: Android

こんにちはこんばんわイッシーです。すっかりブログの更新をサボってしましました。( ✖ Δ ✖)。。。そろそろ書いておかないとアレがアレなので書いておきます。

今回のネタは今更にはなりますがAsyncTaskについてです。通信や巨大ファイルの操作などをする時にメインスレッドで行っている方はいませんよね?(いたらすぐにやめてくださいね)

時間がかかる処理は別スレッドで行いUIスレッドでは行わないのは鉄則です。androidではメインスレッドが5秒以上応答しないと“Application Not Responding”(通称:ANR)が表示されて強制終了のダイアログが表示されます。従って、通信をメインスレッドで行ってはいけません。

さて、以下のようなコードを考えましょう。

public class Main extends ListActivity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if(isConencted(this)){
            Task task = new Task();
            task.execute(URL);
        }
    }
   
    /**
     * isConencted
     * ネットワークの有無を確認する
     * @param context
     * @return boolean
     */

    protected boolean isConencted(Context context)
    {
        ConnectivityManager connectivityManger = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo networkInfo = connectivityManger.getActiveNetworkInfo();
        if(networkInfo == null){
            return false;
        }
        return (networkInfo.isConnected());
    }
   
    /**
     * Task
     * バックグラウンド処理用のクラス
     */

    protected class Task extends AsyncTask<String, String, String>
    {
        @Override
        protected String doInBackground(String... params)
        {
            HttpClient client = new DefaultHttpClient();
            HttpGet get = new HttpGet(params[0]);
            byte[] result = null;
            String str = "";
            try{
                HttpResponse response = client.execute(get);
                StatusLine statusLine = response.getStatusLine();
                if(statusLine.getStatusCode() == HttpURLConnection.HTTP_OK){
                    result = EntityUtils.toByteArray(response.getEntity());
                    str = new String(result, "UTF-8");
                }
            }
            catch (Exception e) {
            }
            return str;
        }
       
        /**
         * onPostExecute
         * @param String result 通信結果
         * 結果を受け取ったときに・・・メインスレッド
         */

        @Override
        protected void onPostExecute(String result)
        {
            try {
                JSONObject json = new JSONObject(result);
            }
            catch (JSONException e) {
                e.printStackTrace();
            }
        }
    }
}

■ポイント

ポイント1

isConenctedで圏外をチェックしてから通信(バックグラウンドタスクを実行)します。電波が無いところで通信しようとするのは無駄というものです。まあ、当然ですね。

ポイント2

別スレッドで実行されるのはdoInBackgroundだけであって、onPostExecuteはメインスレッドで実行されます。時間がかかる処理をonPostExecuteに書かないようにしましょう。

ポイント3

onPostExecuteが実行されたからといって、必ずしも通信が完了したとは考えないほうが良いと思います。地下鉄などではすぐに電波の状態が悪くなります。通信中に圏外になった場合、文字列が途中まで返ってくるのですがJSONでしたら当然パースできません。JSONExceptionできっちり処理してあげてください。

ポイント4

サンプルコードには書いてませんが同時に多数のAsyncTaskを実行するとメモリ不足で落ちる場合、synchronized(activity)して1本しか走らせないようにしましょう。

手短ですが本日はここまで。次回もandroidネタにしようかと思います。

みなさんこんにちはこんばんわ。すっかり夏になりまして暑さに弱い自分は溶けかかってます。バニラアイスが食べたいな٩(๑❛ᴗ❛๑)۶

さて、今回はandroidのアプリ内課金を試すのですがサンプルアプリがダウンロードできるので、それを実行してみたいと思います。

事務的な作業

テストだけでも以下の登録は必要になります。

  • Android Marketの開発者アカウント
  • Google checkoutの財務情報登録

あって困る物ではないので、まだの方はこの機会に登録してみてはどうでしょうか?

■サンプルアプリのダウンロード

以下のような手順でダウンロードします。

  1. AVD Managerを起動
  2. Avalilable packages
  3. Third party Add-ons
  4. Google Inc.
  5. Google Market Billing package, revision 1をチェック

上述の作業が終わるとサンプルアプリが[sdkdir]/extras/google/market_billingに保存されています。

■公開鍵の追記

プロフィールの編集でライセンスとアプリ内課金の公開鍵をコピーし、src/com/example/dungeons/Security.javaを編集します。以下の部分にコピーしたコードをペーストしてください。

String base64EncodedPublicKey = "your public key here";

■プロジェクトのインポート

変更したらeclipseにインポートします。プロジェクトで右クリックし新規プロジェクトを選択し、androidのプロジェクトを新たに作ります。

※但し、既存のソースから新規作成するようにしてください。

■パッケージ名の変更

公式マニュアルに以下のように記載されています。com.exampleというパッケージ名は使用できませんので、パッケージ名を変更します。

The current package name is com.example.dungeons. Android Market does not let you upload applications with package names that contain com.example, so you must change the package name to something else.

パッケージ・エクスプローラのウィンドウでパッケージを選択し、eclipseメニューのリファクタリングから名前変更をします。Manifestのパッケージ名が変わらないようなのでファイルを開いて修正してください。

手動でパッケージ名の変更をおこなう場合は以下の項目を変更します。

  • ディレクトリ名
  • マニフェストファイル
  • package
  • import

■デバッグ

以下の部分を

public static final boolean DEBUG = false;

以下のように変更します。

public static final boolean DEBUG = true;

■マーケットへの登録

通常のアプリと同様に署名してマーケットにアップする必要があります。但し、絶対に公開してはいけません。下書きのまま保存します。

■アイテムの登録

Google checkoutでmerchant登録がされている場合、ダッシュボードのアプリケーションのタイトルの下に「アプリ内サービス」と表示されていますので、ここからアイテムを登録します。

サンプルアプリのアプリ内サービス IDはそれぞれ「sword_001」と「potion_001」です。こちらは公開する必要があります。

■実機でテスト

署名されているアプリケーションからリクエストをする必要がありますので、以下のコマンドをクライアントで実行しアップロードしたapkファイルを直接端末にインストールします。。

./adb install Dungeous.apk

※USBから直接インストールすると、RESULT_DEVELOPER_ERRORというエラーが返ってきて正しくテストできません。

参考

いかがでしょうか?androidではiOSのIn app purchaseとは違い実際の課金処理はマーケットアプリが行っています。この辺がandroidっぽくてドキドキしますね(♡´ω`♡)。次回はこのサンプルの動きを元にして実装を解説できたらと思います。