Skip to content

Instantly share code, notes, and snippets.

@yukpiz
Created August 24, 2015 05:03
Show Gist options
  • Save yukpiz/49e60d89ce1592824097 to your computer and use it in GitHub Desktop.
Save yukpiz/49e60d89ce1592824097 to your computer and use it in GitHub Desktop.

Samba共有へアクセスするjcifsをAndroidで

JavaでSambaサーバへアクセス

  • JavaでSambaアクセスをキーワードに色々ググる
  • JCIFSというライブラリを使う方法がスタンダードな感じ

jarをプロジェクトで読み込む

外部jarの読み込みは、GradleのバージョンとかIDEの有無によって方法も異なるので、
ここではgradle buildで試してできた方法だけ書いておきます。

以下からjarファイルをダウンロードします。
jcifs - Download

以下をbuild.gradleに設定します。

dependencies {
    compile fileTree(dir: 'libs', include: '*.jar')
    compile files('libs/jcifs-1.3.18.jar')
}

import jcifs.smb.*;がビルド通るようになれば問題ありません。

Androidパーミッションの設定

以下をAndroidManifest.xmlに追加します。

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

使ってみる

各APIのドキュメントは以下にあります。
jcifs - API Document

Androidでメインスレッド上での ネットワークアクセス処理を許可していません(NetworkOnMainThreadException)。
ですので、jcifsによるネットワークアクセス処理を 新しく定義したスレッド上で実行する必要があります。

Android上での非同期処理については細かく書きませんが、 Sambaサーバへアクセスして処理を行った後、
その結果を取得するためにThread.join()を使う方法と、 Android.os.Handlerを使う方法を紹介します。

Thread.join()

ここではThread.join()を使って、Sambaサーバへの接続確認を行う機能を実装してみます。
Thread.join()は処理を開始したスレッドが完了するまで待機する機能を持ちます。

別のスレッドとして処理を呼び出すクラスを書きます。

import java.lang.InterrupteException;
import java.io.IOException;
import jcifs.smb.SmbFile;

public class Samba
{
    private int _isConnectionCode = -1;
    /**
      * 指定されたホストへのSamba接続を試行します。
      * 接続に成功したらtrue、失敗したらfalseを返します。
      */
    public boolean connect(
        final String host)
    {
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                //thread.start()で処理される
                try {
                    //smb://{host}の接続文字列を作る
                    SmbFile smb = new SmbFile("smb://" + host);
                    smb.connect();
                    _isConnectionCode = 0;
                } catch (IOException e) {
                    //Process of error.
                    _isConnectionCode = 1;
                }
            }
        });
        thread.start();
        try {
            thread.join();
        } catch (InterrupteException e) {
            //Process of error.
            _isConnectionCode = 1;
        }
        return _isConnectionCode != 0 ? false : true;
    }
}

スレッドの定義と完了待ちのThread.join()を実行する機能はできました。
あとはどこからでも呼び出すだけで、Sambaサーバへの接続確認ができます。

//必要なら上で作ったクラスをimport
import {package}.Samba;

import android.app.Activity;
import android.os.Bundle;

public class MainActivity
    extends Activity
{
    @Override
    public void onCreate(
        Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);

        Samba samba = new Samba();
        if (samba.connect("192.168.1.1")) {
            System.out.println("Sambaサーバの接続に成功");
        } else {
            System.out.println("Sambaサーバの接続に失敗");
        }
    }
}

せっかくの非同期処理をわざわざ待つという方法ではありますが、
上記のような接続確認などを前処理として行いたい場合などに使えます。

Android.os.Handler

ここではandroid.os.Handlerを使って、
Sambaサーバ上のファイルやディレクトリの存在確認を行う機能を実装してみます。

android.os.Handlerは、ある処理の完了を通知する為に使われます。
Sambaアクセスのように、非同期で行われるような処理の結果通知を受ける事ができます。

import android.os.Handler;
import jcifs.smb.SmbFile;
import jcifs.smb.SmbException;

public class Samba
{
    public void exists(
        final Handler handler,
        final String host,
        final String target)
    {
        new Thread(new Runnable() {
            @Override
            public void run() {
                //thread.start()で処理される
                Message message = Message.obtain(handler);
                try {
                    //smb://{host}/{target}
                    SmbFile smb = new SmbFile("smb://" + host + target);
                    message.what = 0;
                    message.obj = smb.exists();
                } catch (SmbException e) {
                    //Process of error.
                    message.what = 1;
                    message.obj = e.getMessage();
                } finally {
                    handler.sendMessage(message);
                }
            }
        }).start();
    }
}

スレッドの定義と完了、例外通知を実行する機能はできました。
呼び出し元では、非同期処理の完了通知を受ける為のハンドラの定義を行い、
処理を呼び出す事で、Sambaサーバ上のファイル・ディレクトリの存在確認ができます。

//必要なら上で作ったクラスをimport
import {package}.Samba;

import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;

public class MainActivity
    extends Activity
{
    @Override
    public void onCreate(
        Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);

        Handler handler = new Handler() {
            @Override
            public void handleMessage(Message message) {
                switch (message.what) {
                    case 0:
                        //ファイルが存在していればtrue
                        //ファイルが存在していなければfalse
                        System.out.println(message.obj);
                        break;
                    case 1:
                        //Process of error.
                        break;
                }
            }
        };

        Samba samba = new Samba();
        samba.exists(handler, "192.168.1.1", "/share/exists.txt");
    }
}

このように、Handlerを利用すると非同期で行われる 処理結果の通知を受け取ることが可能になります。

あとがき

他にも、認証を使った接続やSambaサーバ上でのファイル操作はもちろん、
ローカルにあるファイルとのやり取り等、色々とできそうです。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment