Android Java で CameraX の写真をキャプチャ2

今日は柴犬はお休みです。彼は別に病気とかではないですが、ただちょっと前の写真になってしまうのでカモにします。近くの公園に接する用水路で親ガモが2羽でその周りに子ガモたくさんいます。元気に育っているようです。
概要
FtpAccess では私の今の技量ではうまくいきませんでした。FtpAccessB を修正して次の FtpAccessC にしたところエミュレートではうまくいきましたので記録します。
1冊のみでは理解に苦しいところがあるので更に新しく本を購入しました。
翔泳社 齊藤 新三 著
2024年2月26日現在
WEBのみでは断片的で覚えにくいので最初に購入した Kotlin の本です。
FtpAccessC
引数にアップロードするファイルの InputStream を加えることにしました。
public void FtpAccessC(String filename, InputStream ips) {
Map<String, String> ftpmap = new HashMap<>();
ftpmap.put("ftpUsername",FTPUSERNAME);
ftpmap.put("ftpPassword",FTPPASSWORD);
ftpmap.put("ftpServer",FTPSERVER);
ftpmap.put("ftpDirectory",FTPDIRECTORY);
ftpmap.put("filename",filename);
Log.d(TAG, "FtpAccessC");
new FtpAsyncTaskC(){
@Override
protected void onPostExecute(String response) {
TextView tv = findViewById(R.id.tvinfo);
//アップロードしたフォルダーのファイル一覧を表示します。
tv.setText(response);
}
}.execute(new FtpTaskParamsC(ftpmap, ips));
}
//--------------------------------
public class FtpTaskParamsC {
InputStream _ips;
Map<String, String> _ftpData;
public FtpTaskParamsC(Map<String, String> ftpData, InputStream ips) {
this._ips = ips;
this._ftpData = ftpData;
Log.d(TAG, "FtpTaskParamsC");
}
}
//--------------------------------
public class FtpAsyncTaskC extends AsyncTask<FtpTaskParamsC, String, String> {
@Override
protected String doInBackground(FtpTaskParamsC... params) {
Map<String, String> ftpData = params[0]._ftpData;
InputStream _ips = params[0]._ips;
final String _ftpUsername = ftpData.get("ftpUsername");
final String _ftpPassword = ftpData.get("ftpPassword");
final String _ftpServer = ftpData.get("ftpServer");
final String _ftpDirectory = ftpData.get("ftpDirectory");
final String _filename = ftpData.get("filename");
Log.d(TAG, "FtpAsyncTaskC");
//ファイルの一覧表を返します
ArrayList<String> infolist = new ArrayList<>();
FTPClient ftpClient = new FTPClient();
try {
Log.d(TAG, _ftpServer);
//デフォルト ポートでリモート ホストに接続され、システムに割り当てられたポートで現在のホストから発信されるソケットを開きます
ftpClient.connect(_ftpServer);
Log.d(TAG, _ftpServer);
//指定されたユーザーとパスワードを使用して FTP サーバーにログインします
ftpClient.login(_ftpUsername, _ftpPassword);
Log.d(TAG, _ftpPassword);
//データ転送を行うために接続するデータ ポートを開くようにサーバーに指示されます
ftpClient.enterLocalPassiveMode();
//多くの FTP サーバーはデフォルトで BINARY になっています
ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
//文字化け対策
ftpClient.setControlEncoding("CP932");
Log.d("ServerFileAccess", ftpClient.getStatus());
//ディレクトリ移動
ftpClient.changeWorkingDirectory(_ftpDirectory);
Log.d(TAG, _ftpDirectory);
//
String[] filenames;
filenames = ftpClient.listNames();
for (String filename : filenames) {
Log.d("ServerFileAccess", filename);
infolist.add(filename);
}
//NASにファイルをアップロード
try {
// staoreFile関数の呼び出しでアップロードする。
ftpClient.storeFile(_filename, _ips);
// ログ出力
Log.d(TAG, "Upload - " + _filename);
infolist.add("Upload - " + _filename);
} catch(Exception e) {
e.printStackTrace();
}
} catch (Exception e) {
e.printStackTrace();
} finally {
Log.d("ServerFileAccess", "finally");
infolist.add("処理を終了します");
try {
ftpClient.logout();
ftpClient.disconnect();
} catch (Exception e) {
Log.d(TAG, "FTP開放エラー :", e);
}
}
return join("\n",infolist);
}
}
takePhoto/
imagecapture.takePicture
アップロード非同期処理を行う FtpAccessC 関数の引数に InputStream を加えました。
キャプチャー画像の URI が分かっているので resolver.openInputStream で InputStram を取得します。
private final String FTPUSERNAME = "sora";
private final String FTPPASSWORD = "Ryu<0220>Siba";
private final String FTPSERVER = "192.168.0.5";
private final String FTPDIRECTORY = "photo/JIJISora/";
@Override
protected void onCreate(Bundle savedInstanceState) {
略
}
private void startCamera() {
略
}
@UiThread
private void takePhoto() {
略
// 撮影後にトリガーされる画像キャプチャのリスナーを設定する
imagecapture.takePicture(
outputOptions,
ContextCompat.getMainExecutor(this),
new ImageCapture.OnImageSavedCallback() {
@Override
public void onError(ImageCaptureException error) {
Log.e(TAG, "Photo capture failed: " + error.toString(), error);
}
@Override
public void onImageSaved(ImageCapture.OutputFileResults outputFileResults) {
CharSequence msg = "Photo capture succeeded: " + outputFileResults.getSavedUri();
Toast.makeText(MainActivity.this, msg, Toast.LENGTH_SHORT).show();
Log.d(TAG, msg.toString());
// Uriの取得
Uri uri = Uri.parse(outputFileResults.getSavedUri().toString());
try {
Log.d(TAG,"begin try");
InputStream ips = resolver.openInputStream(uri);
Log.d(TAG,"InputStream");
// アップロード非同期処理
FtpAccessC(name + ".jpg", ips);
} catch (Exception ex) {
Log.d(TAG, "アップロードエラー :", ex);
}
}
});
}
エミュレートの状況
エミュレートの段階ではうまくいっているようです。
左が起動時の画面、右がボタン「Shutter」をクリックした時です。結果が表示されるまでに30秒程要しているのが気になります。

activity_main.xml
テキストビューをスクロールで表示できるようにしました。
ガイドラインを設定して形が崩れないようにしました。
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<androidx.camera.view.PreviewView
android:id="@+id/viewFinder"
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintBottom_toTopOf="@+id/guideline2"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.0"
tools:layout_editor_absoluteX="-2dp" />
<Button
android:id="@+id/bt_shutter"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/bt_shutter"
app:layout_constraintBottom_toTopOf="@+id/scrollView2"
app:layout_constraintEnd_toStartOf="@+id/guideline"
app:layout_constraintHorizontal_bias="0.25"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@+id/guideline2" />
<ScrollView
android:id="@+id/scrollView2"
android:layout_width="match_parent"
android:layout_height="0px"
android:layout_marginTop="65dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="1.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/viewFinder"
app:layout_constraintVertical_bias="0.0">
<TextView
android:id="@+id/tvinfo"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="TextView" />
</ScrollView>
<androidx.constraintlayout.widget.Guideline
android:id="@+id/guideline"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintGuide_percent="0.3" />
<androidx.constraintlayout.widget.Guideline
android:id="@+id/guideline2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintGuide_percent="0.6" />
</androidx.constraintlayout.widget.ConstraintLayout>

NAS
NAS の保存状況です。

次の画像は、保存ファイルのそのままです。
幅 960px 高さ1280px ファイルサイズ 220 KB (226,301 バイト) となりました。テスト画像がそうなのか、高解像度にするにどうすればいいのか今後調べていきたいと思います。
