ぽんたのプログラミング勉強部屋(仮)

プログラミングについて色々勉強したことのメモ集です。どこにでも載っているような情報ばかりですw

Windowsの共有フォルダをAndroid端末から参照する方法

Android端末からWindowsの共有フォルダを参照する方法を調べたので、実装方法をメモ。

JCIFSのダウンロード

どうやらJCIFSというライブラリを使えば、AndroidからWindowsの共有フォルダを参照できる様子。
Windowsのファイル共有サービスで利用されているSMBを拡張し、Windows以外のOSやアプリで
利用できるようにしたものがCIFSだそうな。
で、Javaから利用できるようにしたものがJCIFSだとかなんとか…。

それはさておき、JCIFSのライブラリを以下からダウンロードします。
https://jcifs.samba.org/

jcifs-1.3.18.zipをダウンロードしたら展開し、jcifs-1.3.18.jarをAndroidのlibフォルダに配置します。

パーミッションの変更

AndroidManifest.xmlパーミッションの設定を追加します。
追加する内容は以下の通り。

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

実装

以下、実装のサンプル。
ボタンを押したら共有フォルダにアクセスして、そこにあるファイルの数を取得するだけのプログラムです。

public class MainActivity extends AppCompatActivity {
    private AccessTask task;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        TextView txtView = (TextView)findViewById(R.id.textView);

        task = new AccessTask(txtView);

        Button accessbtn = (Button)findViewById(R.id.button);
        accessbtn.setOnClickListener(AccessListener);
    }

    private View.OnClickListener AccessListener = new View.OnClickListener() {
        public void onClick(View v)
        {
            task.execute(1);
        }
    };
}

以下のプログラム内のhost、user、pswd、共有フォルダ名("/share/"の箇所)は適宜読み替えてください。

import jcifs.smb.SmbFile;

public class AccessTask extends AsyncTask<Integer, Integer, String> {
    private TextView textView;

    public AccessTask(TextView txtView)
    {
        super();
        textView = txtView;
    }

    @Override
    protected String doInBackground(Integer... value)
    {
        SmbFile dir;
        String host = "host-name";
        String user = "user";
        String pswd = "password";
        String str;

        try
        {
            String path = "smb://" + user + ":" + pswd + "@" + host + "/share/";
            dir = new SmbFile(path);

            SmbFile[] files = dir.listFiles();
            str = Integer.toString(files.length) + "個のファイルがあります。";
        }
        catch(Exception e)
        {
            Log.e("Err", e.toString());
        }

        return str;
    }

    @Override
    protected void onPostExecute(String param)
    {
        textView.setText(param);
    }
}

ここで重要なのが以下の2点。
①パスの最後はスラッシュ"/"を付けること
②共有フォルダにアクセスする処理はメインスレッドではなく、別スレッドで行うこと。

②についてですが、Android3.0以降でこのような動作になったらしく、
メインスレッドでアクセスしようものなら、もれなくNetworkOnMainThreadExceptionが付いてきます。

最初コレに気づかずに3時間くらい悩んだよ…。