SSIDとパスワードの変更

このチュートリアルではSSIDとパスワードの取得と更新方法について学びます。
command.cgiconfig.cgi を使用します。

ここでは、SSIDとパスワードを取得し表示する画面、SSIDとパスワードを新しい内容で更新する画面の、2つの画面を持つアプリケーションとして作ってみましょう。

1つ目の画面はボタンを2つ用意します:

This image shows the first screen with only the two buttons

“Get” をクリック(タップ)すると、テキストフィールドに現在のSSIDとパスワードを表示することができます:

This image shows the get screen with SSID and password

“Set” をクリック(タップ)すると次の画面へ遷移し、 新しいSSIDとパスワードを設定することができます:

This image shows the set screen with empty text fields

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

  • MainActivity.java
  • activity_main.xml
  • SetScreenActivity.java
  • activity_set_screen.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


Get 画面のレイアウト作成

activity_main.xml に以下のように記述してください:

activity_main.xml
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="fill_parent"
        android:layout_height="match_parent"
        android:gravity="center_horizontal"
        android:orientation="vertical"
        tools:context=".MainActivity" >

        <Button
            android:id="@+id/button1"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:cacheColorHint="#00000000"
            android:text="Get"
            android:textColor="@android:color/white"
            android:textSize="20sp" />

        <Button
            android:id="@+id/button2"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:cacheColorHint="#00000000"
            android:text="Set"
            android:textColor="@android:color/white"
            android:textSize="20sp" />

        <TextView
            android:id="@+id/SSIDlabelView"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="left"
            android:layout_marginTop="25dp"
            android:paddingLeft="10dp"
            android:text="SSID:"
            android:textSize="18sp" />

        <TextView
            android:id="@+id/textView4"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textSize="18sp"
            android:text="Current SSID will be here" />

        <TextView
            android:id="@+id/passwordView"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="left"
            android:layout_marginTop="25dp"
            android:paddingLeft="10dp"
            android:text="Password:"
            android:textSize="18sp" />

        <TextView
            android:id="@+id/textView5"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textSize="18sp"
            android:text="Current password will be here" />

    </LinearLayout>

Set 画面のレイアウト作成

次に、activity_set_screen.xml を記述して、SSIDとパスワードを設定できるレイアウトを決定します。
この画面は、ネットワークの変更に重要な役割をつとめる4つの入力欄から構成されます。
入力欄は、このXMLファイルに設定する方法となっており、テキスト入力欄を選択した際、キーボードが表示されるようにします

このファイルは、layout フォルダに配置されています。
パス: [Project_Folder]/res/layout/activity_set_screen.xml

activity_set_screen.xml
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="fill_parent"
        android:layout_height="match_parent"
        android:gravity="center_horizontal"
        android:orientation="vertical"
        tools:context=".MainActivity" >

        <Button
            android:id="@+id/button1"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:cacheColorHint="#00000000"
            android:text="Back"
            android:textColor="@android:color/white"
            android:textSize="20sp" />

        <TextView
            android:id="@+id/mastercodeView"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="left"
            android:layout_marginTop="12dp"
            android:paddingLeft="10dp"
            android:text="Mastercode:"
            android:textSize="18sp" />

        <EditText
            android:id="@+id/editMC"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:ems="10"
            android:hint="Mastercode"
            android:inputType="text"
            android:textStyle="italic" />

        <TextView
            android:id="@+id/warningView"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="left"
            android:layout_marginTop="8dp"
            android:paddingLeft="10dp"
            android:text="Warning: We have displayed the Mastercode in this tutorial application to demonstrate how the FlashAir device works. This information is provided for tutorial purposes only. For security reasons, we highly discourage you from publicly displaying your Mastercode."
            android:textSize="12sp"
            android:textStyle="italic" />

        <TextView
            android:id="@+id/SSIDlabelView"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="left"
            android:layout_marginTop="20dp"
            android:paddingLeft="10dp"
            android:text="SSID:"
            android:textSize="18sp" />

        <EditText
            android:id="@+id/editText1"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:ems="10"
            android:hint="New SSID"
            android:inputType="text"
            android:textStyle="italic" >

        </EditText>

        <TextView
            android:id="@+id/passwordView"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="left"
            android:layout_marginTop="20dp"
            android:paddingLeft="10dp"
            android:text="Password:"
            android:textSize="18sp" />

        <EditText
            android:id="@+id/editText2"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:ems="10"
            android:hint="New Password"
            android:inputType="textPassword"
            android:textStyle="italic" />

         <EditText
             android:id="@+id/editText3"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
             android:ems="10"
             android:hint="New Password"
             android:inputType="textPassword"
             android:textStyle="italic" />

        <Button
            android:id="@+id/button2"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="12dp"
            android:cacheColorHint="#00000000"
            android:text="Done"
            android:textColor="@android:color/white"
            android:textSize="20sp" />

    </LinearLayout>

Get 画面の作成

まず、SSIDとパスワードの取得と設定が可能な2つの Button を初期化します。
また、SSIDとパスワードの取得も実装します。このアプリケーションの他の部分でも使用します。

初期化

メンバ変数の宣言と画面の書式を設定します。 それから、各ボタンの onClickListener を設定します。
それぞれ動作が異なるので、2つの onClick() 関数を記述します:

MainActivity.java (1)
    public class MainActivity extends Activity {

        TextView SSID;
        TextView password;
        Button getButton;
        Button setButton;

        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            getWindow().setTitleColor(Color.rgb(65, 183, 216));
            getButton = (Button)findViewById(R.id.button1);
            setButton = (Button)findViewById(R.id.button2);
            getButton.getBackground().setColorFilter(Color.rgb(65, 183, 216), PorterDuff.Mode.SRC_IN);
            setButton.getBackground().setColorFilter(Color.rgb(65, 183, 216), PorterDuff.Mode.SRC_IN);
            try {
                getButton.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        // Set button to show current SSID and Password
                        getSSID();
                        getPassword();
                    }
                });
            } catch(Exception e) {
                Log.e("ERROR", "ERROR: " + e.toString());
                e.printStackTrace();
            }
            try {
                setButton.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        // Set button to start new intent to allow new SSID and password input
                        Intent setSSIDPassword = new Intent(getBaseContext(), SetScreenActivity.class);
                        MainActivity.this.startActivity(setSSIDPassword);
                    }
                });
            } catch(Exception e) {
                Log.e("ERROR", "ERROR: " + e.toString());
                e.printStackTrace();
            }
        }


        @Override
        public boolean onCreateOptionsMenu(Menu menu) {
            // Inflate the menu; this adds items to the action bar if it is present.
            getMenuInflater().inflate(R.menu.main, menu);
            return true;
        }
  • 18-25行目
    getButton のクリックリスナーを設定しています。
    Buttonがクリックされた時、FlashAirから現在のSSIDを取得する関数と、FlashAirから現在のパスワードを取得する関数を呼びます(両方とも実装は後述します)。

  • 33-38行目
    setButton のクリックリスナーを設定しています。 SSIDとパスワードは他のclass と 別の画面を使用して設定するので、このリスナーは単に次の画面を開始するためのIntent を設定しています。 次の画面へ引き継ぐ情報はありませんので、追加でBundle データは送りません。

SSIDの取得

上記の関数から呼び出されている getSSID() 関数は、FlashAirから現在のSSIDを取得します。 FlashAirのSSIDは最大32文字まで設定可能です。

FlashAirの現在のSSIDを取得するためには、以下のコマンドを使用します:

  • command.cgiop=104 を指定します。
    • コマンド: http://flashair/command.cgi?op=104
    • コマンドが返す情報:<SSID>

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

MainActivity.java (2)
        public void getSSID() {
            new AsyncTask<String, Void, String>(){
                @Override
                protected String doInBackground(String... params) {
                    return FlashAirRequest.getString(params[0]);
                }
                @Override
                protected void onPostExecute(String currentSSID) {
                    SSID = (TextView)findViewById(R.id.textView4);
                    SSID.setText(currentSSID);
                }
            }.execute("http://flashair/command.cgi?op=104");
        }

パスワードの取得

前述した onClick() 関数から呼び出されている getPassword() は、FlashAirから現在のパスワードを取得します。 FlashAirのパスワードは最大64文字まで設定可能です。

FlashAirの現在のパスワードを取得するためには、以下のコマンドを使用します:

  • command.cgiop=105 を指定します。
    • コマンド: http://flashair/command.cgi?op=105
    • コマンドが返す情報: <networkPassword>

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

MainActivity.java (3)
        public void getPassword() {
            new AsyncTask<String, Void, String>(){
                @Override
                protected String doInBackground(String... params) {
                    return FlashAirRequest.getString(params[0]);
                }
                @Override
                protected void onPostExecute(String currentPassword) {
                    password = (TextView)findViewById(R.id.textView5);
                    password.setText(currentPassword);
                }
            }.execute("http://flashair/command.cgi?op=105");
        }

では、 setButton がクリックされた後の一連の処理を行う SetScreenActivity を、記述します。


設定画面の作成

注意: MASTERCODEは、FlashAirの新しいSSIDやパスワードを設定する際に使用します。 MASTERCODEを確認するには、PCなどにFlashAirを挿入し、”/SD_WLAN/” フォルダに保存されているCONFIGファイルを、お手持ちのテキストエディタなどで開きます(FlashAirの初期設定を終えていない場合は確認ができませんので、先に済ませるようにしてください)。
また、このフォルダは隠しフォルダとなっていますので、隠しフォルダを扱う事が出来るツールを使いましょう。
Mastercodeは、このファイルに保存されています:

This image shows the Mastercode in the config file

Mastercode を入手すれば、 config.cgi が使用できるようになります。

初期化

FlashAirに新しい SSID とパスワードを送るためのボタンを用意します。ラベルは ‘Done’ とし、全ての入力欄への入力が終わるまでは無効にします。

新しい画面ではユーザーの入力が必要なので、 ユーザーが入力ための EditText と 入力欄を監視するための TextWatcher を初期化します。 全部で4つの入力欄が必要であり、 Mastercode用、新しいSSID用, 新しいパスワード用、 新しいパスワードの確認用(ミスを避けるため)です。 TextWatcher class をオーバーライドし fieldWatcher をカスタマイズします。 fieldWatcher は全ての入力欄の入力内容をチェックし、その後 ‘Done’ ボタンを有効にします。

SetScreenActivity.java (1)
    public class SetScreenActivity extends Activity {

        EditText mastercodeField;
        EditText SSIDfield;
        EditText passwordField;
        EditText passwordField2;
        Button backButton;
        Button doneButton;
        String newSSID = "";
        String newPassword = "";
        String newPassword2 = "";
        String mastercode = "";
        Boolean SSIDset = false;
        Boolean passwordSet = false;
        TextWatcher fieldWatcher = new TextWatcher(){
            @Override
            public void afterTextChanged(Editable e) {
                if(mastercodeField.getText().toString().isEmpty() 
                   || SSIDfield.getText().toString().isEmpty()
                   || passwordField.getText().toString().isEmpty()
                   || passwordField2.getText().toString().isEmpty() ) {
                    doneButton.setEnabled(false);
                }
                else {
                    doneButton.setEnabled(true);
                }
            }

            @Override
            public void beforeTextChanged(CharSequence cs, int start, int count, int after) {
                // Do nothing
            }

            @Override
            public void onTextChanged(CharSequence cs, int start, int before, int count) {
                // Do nothing
            }
        };
  • 17-27行目
    入力欄で変更があるたび、fieldWatcher が 全ての入力欄に何かしらの入力があるかどうかをチェックします。
    このチェックはdoneButton ボタンを制御するためのものです。

各フィールドに何かしらの入力があると判断した場合、 doneButton は有効になります:

This image shows the set screen with enabled Done button

ユーザーがいずれかの入力欄をクリアした場合は、 doneButton は無効になります:

This image shows the set screen with disabled Done button

全ての Activityを初期化する onCreate(Bundle savedInstanceState) 関数をオーバーライドします。 この関数は、画面の書式、全ての .xml 要素の識別、そして class MainActivity から渡された Intent を設定します。 また、上記で記した fieldWatcher がそれぞれの EditText を監視するよう設定します。

SetScreenActivity.java (2)
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_set_screen);
            getWindow().setTitleColor(Color.rgb(65, 183, 216));
            backButton = (Button)findViewById(R.id.button1);
            doneButton = (Button)findViewById(R.id.button2);
            backButton.getBackground().setColorFilter(Color.rgb(65, 183, 216), PorterDuff.Mode.SRC_IN);
            doneButton.getBackground().setColorFilter(Color.rgb(65, 183, 216), PorterDuff.Mode.SRC_IN);
            doneButton.setEnabled(false); // Disable until text fields have been filled
            mastercodeField = (EditText)findViewById(R.id.editMC);
            SSIDfield = (EditText)findViewById(R.id.editText1);
            passwordField = (EditText)findViewById(R.id.editText2);
            passwordField2 = (EditText)findViewById(R.id.editText3);
            mastercodeField.setHintTextColor(Color.rgb(65, 183, 216));
            SSIDfield.setHintTextColor(Color.rgb(65, 183, 216));
            passwordField.setHintTextColor(Color.rgb(65, 183, 216));
            passwordField2.setHintTextColor(Color.rgb(65, 183, 216));
            try {
                getIntent();
                backButton.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        SetScreenActivity.this.finish();
                    }
                });
                doneButton.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        getInput();
                        setNewSSIDPassword();
                    }
                });
                mastercodeField.addTextChangedListener(fieldWatcher);
                SSIDfield.addTextChangedListener(fieldWatcher);
                passwordField.addTextChangedListener(fieldWatcher);
                passwordField2.addTextChangedListener(fieldWatcher);
            } catch(Exception e) {
                Log.e("ERROR", "ERROR: " + e.toString());
                e.printStackTrace();
            }
        }


        @Override
        public boolean onCreateOptionsMenu(Menu menu) {
            // Inflate the menu; this adds items to the action bar if it is present.
            getMenuInflater().inflate(R.menu.set_screen, menu);
            return true;
        }
  • 10行目
    doneButton はインスタンス化するとすぐに無効になります。
    ユーザーは全ての入力が終わるまで、FlashAirにCGIコマンドを送信することができなくなります。これにより、CGIコマンドを実行した際のエラーを回避することができます。

  • 11-18行目
    各入力欄にヒントを設定しています(ユーザーが入力を開始するまで表示します)。

  • 34-37行目
    各入力欄にfieldWatcherを追加しています。これによりユーザーが入力または削除をした際、処理を行えるようになります。

入力値の取得

次の関数は、ユーザーの入力値を取得します。 この関数は doneButtononClick() 関数に呼ばれます。 fieldWatcher が4つの入力欄全ての入力を見つけたときにのみ、値を取得し格納します。

SetScreenActivity.java (3)
        public void getInput() {
                mastercode = mastercodeField.getText().toString();
                newSSID = SSIDfield.getText().toString();
                newPassword = passwordField.getText().toString();
                newPassword2 = passwordField2.getText().toString();
        }

確認用パスワードの一致

新しいパスワードを入力する際の入力ミスを避けるために、このアプリケーションは2回パスワードを入力する必要があり、2つのパスワードが一致するかどうかを確認します。次の関数は、2つのパスワードが一致するかどうかをチェックし、一致する場合はCGIコマンドを送信しても安全であるということを示しています。

SetScreenActivity.java (4)
        public Boolean passwordConfirmed() {
            if(newPassword.equals(newPassword2)) {
                return true;
            }
            return false;
        }

もし passwordConfirmed()falseを返した場合は、 後述する関数 ( setNewSSIDPassword()) でパスワードをクリアし ( doneButton が無効になる)、 パスワードが異なっていることを指し示す Toastを表示します:

This image shows the set screen with the password mismatch toast

SSIDとパスワードの設定

次の機能は、FlashAirにCGIコマンドを送信し、その応答を処理します。
コマンドを送信する前に、パスワードが正しく入力されていることを保証するため、上記の passwordConfirmed() を呼び出しています。

SSIDを設定するためには、以下のコマンドを使用します:

  • config.cgi に Mastercode と 新しいSSIDを指定します。
    • Mastercode = 0123456789AB、SSID = flashair である場合は、このようになります:
      http://flashair/config.cgi?MASTERCODE=0123456789AB&APPSSID=flashair
    • コマンドが返す情報:
      • SUCCESS SSIDの変更に成功
      • ERROR SSIDの変更に失敗

SSIDをパスワードを設定するためには、以下のコマンドを使用します:

  • config.cgi に Mastercode と 新しいパスワードを指定します
    • Mastercode = 0123456789AB、パスワード = 12345678 である場合は、このようになります:
      http://flashair/config.cgi?MASTERCODE=0123456789AB&APPNETWORKKEY=12345678
    • コマンドが返す情報:
      • SUCCESS パスワードの変更に成功
      • ERROR パスワードの変更に失敗

結合して同時に指定する場合はこのようになります:
http://flashair/config.cgi?MASTERCODE=0123456789AB&APPNETWORKKEY=12345678&APPSSID=flashair

新しいSSIDは、1 ~ 32 文字でなければならず、パスワードは、8 ~ 64 文字の間でなければなりません。 これらの条件のいずれかに反した場合は、コマンドCGIは ERROR を返します。

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

SetScreenActivity.java (5)
    public void setNewSSIDPassword() {
        if(passwordConfirmed()) {

            // If passwords match, do HTTP command, catch and display if command fails
            new AsyncTask<String, Void, String>(){
                @Override
                protected String doInBackground(String... params) {
                    return FlashAirRequest.getString(params[0]);
                }
                @Override
                protected void onPostExecute(String result) {
                    if(result.toUpperCase(Locale.getDefault()).equals("SUCCESS")) {
                        Toast.makeText(SetScreenActivity.this, "Remember to reconnect to your FlashAir device using the new SSID and password!", Toast.LENGTH_LONG).show();
                        SetScreenActivity.this.finish(); // Go back to Get screen
                    }
                }
            }.execute("http://flashair/config.cgi?MASTERCODE=" + mastercode + "&APPNETWORKKEY=" + newPassword + "&APPSSID=" + newSSID);
        }
        else {
            // If passwords don't match, display toast
            Toast.makeText(this, "Password mismatch!", Toast.LENGTH_SHORT).show();
            passwordField.setText("");
            passwordField2.setText("");
        }
    }
  • 13行目
    Toast を表示し、FlashAir に再接続する必要がある旨を伝えます。 元の画面(古いSSIDとパスワードデータを含む)に戻ってもToastはまだしばらくの間表示されます:

  • 14行目
    現在のActivity を終了し、最初の画面 (class MainActivity) へ戻り、再度新しいSSIDとパスワードを設定します。
    SSIDとパスワードの変更に成功した場合は、AndroidはFlashAirのSSIDとパスワードが変わってしまっているので、FlashAirとの接続は切れます。


実行結果

Toastはこのように表示されます。

This image shows the get screen with the toast

新しいSSIDとパスワードに変更しFlashAirに再接続した後、”Get”をタップすると、新たに変更されたSSIDとネットワークパスワードを取得します:

This image shows the get screen with the toast


サンプルコード

android_tutorial_06.zip (532KB)

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