Sibainu Relax Room

柴犬と過ごす

Android CameraX SMBにてNAS接続2

見ていられないと思ったのか横を向いちゃった柴犬です。

概要

Android CameraX SMBにてNAS接続1 でのAndroid ファイルをエミュレートで動かしてみました。

警告とエラーが出ました。ああ~。

上の警告は build.gradle.kts (:app) における依存関係の中の implementation(files(“libs/slf4j-api-2.0.11.jar”)) が原因と思われます。

下のエラーはキャストできなかったというエラーです。

警告について

次のURLを見ろとありますが、私の知識では何を言っているのか分かりませんでした。

https://www.slf4j.org/codes.html#noProviders 

WEBでいろいろ当たってみたところ次のようにするといいらしいです。

    implementation(files("libs/slf4j-api-2.0.11.jar"))

                ↓

    implementation("org.slf4j:slf4j-api:1.8.0-beta2")
    runtimeOnly("org.jlib:jlib-awslambda-logback:1.0.0")

エラーについて

MainActivity.kt の中の関数 NasAccess が原因と思われます。

関数の中の次の行の処理は

            Log.d("ServerFileAccess", sf.server)
            Log.d("ServerFileAccess", sf.share)
            Log.d("ServerFileAccess", sf.name)
            Log.d("ServerFileAccess", sf.path)

想定した情報を出力しています。

192.168.□□.□□
photo
□□□□□□□□□□□□□□□□□/
mb://192.168.□□.□□/□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□/

ですので、次の if ブロックがおかしい。その中で sf.exists() がエラーの原因と考えられます。

if (sf.exists()) {
                Log.d("ServerFileAccess", "ファイル有")
            } else {
                Log.d("ServerFileAccess", "ファイル無")
            }

jcifs-ng-2.1.10.jar のバージョン変更

最新バージョンではなく少し前のバージョンを試します。

MNV Repository のHPから使用状況が一番多い 2.1.7 を選んでダウンロードしました。

WEBトップ
https://mvnrepository.com/artifact/eu.agno3.jcifs/jcifs-ng

jcifs-ng-2.1.7.jarのダウロード先
https://repo1.maven.org/maven2/eu/agno3/jcifs/jcifs-ng/2.1.7/

依存関係が設定できたら AndroidStudio のエミュレータで実行してみます。

修正後の実行

警告、エラーとも発生しなくなりました。

自宅の NAS とも接続できターゲットのフォルダーの中にファイルがあるか否かの確認ができました。

現在最終の依存関係

現在最終の依存関係のコードを記載します。

copy

dependencies {

    implementation("androidx.core:core-ktx:1.9.0")
    implementation("androidx.appcompat:appcompat:1.6.1")
    implementation("com.google.android.material:material:1.11.0")
    implementation("androidx.constraintlayout:constraintlayout:2.1.4")
    testImplementation("junit:junit:4.13.2")
    androidTestImplementation("androidx.test.ext:junit:1.1.5")
    androidTestImplementation("androidx.test.espresso:espresso-core:3.5.1")

    // SMB
    implementation(files("libs/bcprov-jdk15on-1.70.jar"))

    //implementation(files("libs/slf4j-api-2.0.11.jar"))
    implementation("org.slf4j:slf4j-api:1.8.0-beta2")
    runtimeOnly("org.jlib:jlib-awslambda-logback:1.0.0")
    
    //https://mvnrepository.com/artifact/eu.agno3.jcifs/jcifs-ng/2.1.7
    //implementation(files("libs/jcifs-ng-2.1.10.jar"))
    implementation(files("libs/jcifs-ng-2.1.7.jar"))

    // コルーチン
    val kotlin_version = "1.3.9"
    implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:${kotlin_version}")
    implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:${kotlin_version}")
    //implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.8.0-RC2")
    val lifecycle_version = "2.7.0"
    implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:${lifecycle_version}")
    implementation("androidx.lifecycle:lifecycle-runtime-ktx:${lifecycle_version}")
}

現在最終のMainActivity.kt

エラーが原因で確かめるため少しいじりましたので載せます。

copy

package siba.inu.android.sibainuspp

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import android.widget.Button
import kotlinx.coroutines.*
import java.util.Properties
import jcifs.context.BaseContext
import jcifs.smb.NtlmPasswordAuthenticator
import jcifs.smb.SmbFile

class MainActivity : AppCompatActivity() {
    // コルーチン関連
    private val sibainujob = Job()
    private val sibainuscope = CoroutineScope(Dispatchers.Default + sibainujob)

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        initstart()
    }

    private fun initstart() {
        findViewById<Button>(R.id.button).setOnClickListener() {
            // 非同期処理
            sibainuscope.launch {
                NasAccess("user",
                          "password",
                          "domain",
                          "smbroot")
            }
        }
    }

    override fun onDestroy() {
        sibainujob.cancel()
        super.onDestroy()
    }

    private fun NasAccess(user: String,
                          password: String,
                          domain: String,
                          smbroot: String) {
        var prop = Properties()
        prop.setProperty("jcifs.smb.client.minVersion", "SMB202")
        prop.setProperty("jcifs.smb.client.maxVersion", "SMB311")
        var bc = BaseContext(jcifs.config.PropertyConfiguration(prop))
        var auth = NtlmPasswordAuthenticator(domain, user, password)
        var cifsCon = bc.withCredentials(auth)

        try {
            var sf = SmbFile(smbroot, cifsCon)
            Log.d("ServerFileAccess", sf.server)
            Log.d("ServerFileAccess", sf.share)
            Log.d("ServerFileAccess", sf.name)
            Log.d("ServerFileAccess", sf.path)
            if (sf.exists()) {                            // ←←←←←ここでエラー
                Log.d("ServerFileAccess", "ファイル有")
            } else {
                Log.d("ServerFileAccess", "ファイル無")
            }
        }catch (ex: Exception) {
            Log.d("ServerFileAccess", ex.toString())
        } finally {
            Log.d("ServerFileAccess", "finally")
        }
    }
}

現在最終のAndroidManifest.xml

copy

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">

    <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"/ -->

    <application
        android:allowBackup="true"
        android:dataExtractionRules="@xml/data_extraction_rules"
        android:fullBackupContent="@xml/backup_rules"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/Theme.Sibainuspp"
        tools:targetApi="31">
        <activity
            android:name=".MainActivity"
            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

追記:NASに接続してファイル一覧を表示

黄色の行が、何のことを言っているのか、ちゃんと取得できるのか気になって実行することにしました。

MainActivity.kt の中の NasAccess() 関数のこの部分を

            if (sf.exists()) {                            // ←←←←←ここでエラー
                Log.d("ServerFileAccess", "ファイル有")
            } else {
                Log.d("ServerFileAccess", "ファイル無")
            }

次のようにコードを加えて実行してみました。

黄色の行が何の意味なのかまだ分かりませんが、取得できているようです。

copy

            if (sf.exists()) {                            // ←←←←←ここでエラー
                Log.d("ServerFileAccess", "ファイル有")
                val filenames: Array<String> = sf.list()
                for (i in filenames.indices) {
                    Log.d("ServerFileAccess",filenames[i])
                }
            } else {
                Log.d("ServerFileAccess", "ファイル無")
            }

前回で終わったと思いましたが甘かったです。今回はこれで終わります。