コンテンツの自動更新

このチュートリアルではコンテンツの自動更新方法について学びます。
thumbnail.cgicommand.cgi を使用します。

作成した Android Tutorial 4: サムネイルの表示 に自動更新機能を追加します。
FlashAirの内容が更新されると、コンテンツリストも更新します。

メモ: このチュートリアルの学習効果を高めるため、FlashAirをお手持ちのデジタルカメラに挿入することをお勧めします。 新しい写真を撮影したり、撮影済みの写真を削除すると、このアプリケーションにFlashAirの変更内容が反映されます。

コンテンツのファイル名とサムネイルのペアを含むリストは次のようになります:

This image shows the content list

FlashAirを挿入したデジタルカメラで写真を撮ると、コンテンツリストが(指定した時間後)にリフレッシュされ、撮った写真が反映されます:

This image shows an updated content list

新しく追加されたイメージファイルの名前をクリック(タップ)すれば、撮影したばかりの写真を表示することもできます:

This image shows the new image in an image view

表示されているとおり、Android 端末に画像ファイルがダウンロードされます。

アプリケーションを作成するために、次のファイルを作成します:

  • MainActivity.java
  • activity_main.xml
  • ImageViewActivity.java
  • activity_image_view.xml

重要: Android application は、デフォルトの状態ではインターネットにアクセスすることができません。 そのため、設定ファイル AndroidManifest.xml を変更し、権限を与える必要があります。
パス: [Project_Folder]/AndroidManifest.xml AndroidManifest.xml に以下のコードを追加してください:

<uses-permission android:name="android.permission.INTERNET" />

リストのレイアウト作成

ではまず、 activity_main.xml を記述して、レイアウトを決定します。
このファイルは、layout フォルダに配置されています。
パス: [Project_Folder]/res/layout/activity_main.xml

activity_main.xmlAndroid Tutorial 3: コンテンツのダウンロードと同じになります。
実装の説明についてはそちらを参照してください。


イメージビューのレイアウト作成

次に、 activity_image_view.xml を記述して、レイアウトを決定します。
このファイルは、layout フォルダに配置されています。
パス: [Project_Folder]/res/layout/activity_image_view.xml

activity_image_view.xmlAndroid Tutorial 3: コンテンツのダウンロードと同じになります。 実装の説明についてはそちらを参照してください。


コンテンツリストの作成

さて、 MainActivity.java を修正します。
まずは FlashAir の任意のフォルダにあるファイル名の一覧を取得します(詳細は Android Tutorial 3: コンテンツのダウンロード を確認してください)。

次に、リスト中のファイル名とそのファイルのサムネイル画像をペアとして ListView に表示し、動作を設定します(詳細は Android Tutorial 4: サムネイルの表示 を確認してください)。

初期化

Android Tutorial 4: サムネイルの表示MainActivity.java をコピーし、それを新しい MainActivity.java としてご使用ください。

class MainActivity 宣言, メンバ変数、と onCreate(Bundle savedInstanceState) 関数を下記のように置き換えます:

MainActivity.java (1)
    public class MainActivity extends Activity implements AdapterView.OnItemClickListener {

        ListView listView;
        ImageView imageView;
        TextView currentDirText;
        TextView numFilesText;
        Button backButton;
        String rootDir = "DCIM";
        String directoryName = rootDir; // Initialize to rootDirectory
        SimpleAdapter listAdapter;
        int checkInterval = 5000;
        Handler updateHandler;
        boolean viewingList;

        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            viewingList = true; // Start out viewing the list
            try {
                // Set buttons
                getWindow().setTitleColor(Color.rgb(65, 183, 216));
                backButton = (Button)findViewById(R.id.button1);
                backButton.getBackground().setColorFilter(Color.rgb(65, 183, 216), PorterDuff.Mode.SRC_IN);
                backButton.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        if(directoryName.equals(rootDir)) {
                            listRootDirectory();
                        }
                        else {
                            int index = directoryName.lastIndexOf("/");
                            directoryName = directoryName.substring(0, index);
                            listDirectory(directoryName);
                        }
                    }
                });
                backButton.setEnabled(false); // Disable in root directory
                listRootDirectory();
            } catch(Exception e) {
                Log.e("ERROR", "ERROR: " + e.toString());
                e.printStackTrace();
            }
            updateHandler = new Handler();
            startUpdate();
        }

前回までに作成した MainActivity クラスにメンバ変数を追加しました。

  • 11行目
    FlashAirの状態をチェックする時間間隔を設定しています。

  • 12行目
    後述の関数で実装するRunnable を管理するHandler updateHandlerを宣言しています。

  • 13行目
    現在コンテンツリストや画像を表示ししているかを追跡するboolean viewingList を宣言しています 。

ルートのフォルダを”DCIM”としていますが(8行目)、他のフォルダをルートにしても構いません。
販売されている多くのデジタルカメラが撮影した画像を “DCIM” フォルダへ格納しているので、ここでは “DCIM” を設定しました。

残りの MainActivity.java はそのまま使用します(コンテンツリストの設定を含める必要があります)。

ビューの状態による制御

MainActivity.java に、更新の状態をチェックする処理を追加します。
この処理は、 以前作成した class MainActivity に含めます。

ユーザーがコンテンツリストを表示していない場合には、FlashAirの状態を監視する必要はありません。 コンテンツリストを表示する際に、最新の情報を取得するためです。
ユーザーがコンテンツリストを表示中の場合にだけ、FlashAirの状態を監視し、変更内容を反映するようにしましょう。

コンテンツリストのビューが表示されているかを判断するために、上記で宣言したフラグ viewingList (13行目)を更新するリスナー関数をオーバーライドします。

MainActivity.java (2)
        @Override
            public void onWindowFocusChanged(boolean hasFocus) {
                super.onWindowFocusChanged(hasFocus);
                if(hasFocus) {
                    viewingList = true;
                }
                else {
                    viewingList = false;
                }
            }


        public boolean checkIfListView() {
            // Check if user is viewing a content list
            if(viewingList) {
                return true;
            }
            return false;
        }

hasFocus 変数は、コンテンツリストを表示している場合に True です。 ユーザーが View を切り替えると通知されます。 これは、以下の Runnable の実装を容易にしています。

更新ハンドラの設定と コンテンツの更新

FlashAirの更新状態を取得するためには、以下のコマンドを使用します。

  • command.cgiop=102 を指定します。
    • コマンド: http://flashair/command.cgi?op=102
    • コマンドが返す情報:
      • 1 アップデートされている
      • 0 アップデートされていない

コマンドCGIは 1 を1度だけ返します。 その後別の変更が行われるまでは 0 を返します。

コマンドの実行には前項 Android Tutorial 3: コンテンツのダウンロードまでに作成した、 FlashAirRequest.java を使用します。

次の関数では、コンテンツリストを自動更新する動作と、その間隔を決定します。

MainActivity.java (3)
        public Runnable statusChecker = new Runnable() {
            @Override
            public void run() {
                if (checkIfListView() == true) {
                    new AsyncTask<String, Void, String>(){
                        @Override
                        protected String doInBackground(String... params) {
                            return FlashAirRequest.getString(params[0]);
                        }
                        @Override
                        protected void onPostExecute(String status) {
                            if(status.equals("1")) {
                                // Fetch current contents of FlashAir and display list
                                listDirectory(directoryName);
                            }
                        }
                    }.execute("http://flashair/command.cgi?op=102");
                }
                updateHandler.postDelayed(statusChecker, checkInterval);
            }
        };


        public void startUpdate() {
            statusChecker.run();
        }


        public void stopUpdate() {
            updateHandler.removeCallbacks(statusChecker);
        }
  • 3-20行目
    Runnable class のメイン処理run() 関数を設定しています。

  • 19行目
    updateHandlerに対し、statusCheckerrun()関数が、checkIntervalミリ秒後に実行されるよう設定しています。 このコードが自身の関数内のrun() 関数で実行されていることに注意してください。 これは長い時間updateHandler が停止せず、checkInterval にミリ秒単位で設定した時間ごとに、再度実行されることを意味します。


画像表示画面の作成

class ImageViewActivityAndroid Tutorial 3: コンテンツのダウンロードと同じです。 実装の詳細についてはこのチュートリアルを参照してください。


サンプルコード

android_tutorial_05.zip (533KB)

このサイトのサンプルコードは二条項BSDライセンスで提供されています。