前提・実現したいこと
今回、Androidアプリを作成する過程で、
画面のキャプチャをストレージに保存するという処理を書きました。
ですが、実際に稼働させてみるとエラーが発生してしまい、
フォルダの作成ができず、手動でフォルダを作成してもエラーとなってしまいました。
権限に関してはAndroidManifest.xlsに以下の記述をしております。
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
あわせて、権限を取得するための関数は以下の通り記載しております。
public class WritingArFragment extends ArFragment { @Override public String[] getAdditionalPermissions() { String[] additionalPermissions = super.getAdditionalPermissions(); int permissionLength = additionalPermissions != null ? additionalPermissions.length : 0; String[] permissions = new String[permissionLength + 1]; permissions[0] = Manifest.permission.WRITE_EXTERNAL_STORAGE; if (permissionLength > 0) { System.arraycopy(additionalPermissions, 0, permissions, 1, additionalPermissions.length); } return permissions; } }
また、端末の設定を確認しても、正常にカメラとファイルへのアクセスは許可になっておりました。
発生している問題・エラーメッセージ
フォルダが作成できない
android.system.ErrnoException: open failed: ENOENT (No such file or directory)
権限が無い
failed: EACCES (Permission denied)
該当のソースコード
下記コードの"out.getParentFile().mkdirs();"が稼働せずに、
フォルダが作成されておりませんでした。
また、明示的にフォルダを作成して実行しても、
上述のEACCESというエラーが発生してしまい、
"FileOutputStream outputStream = new FileOutputStream(filename);"という記述でエラーとなってしまいました。
Java
1 private void saveBitmapToDisk(Bitmap bitmap, String filename) throws IOException { 2 3 File out = new File(filename); 4 if (!out.getParentFile().exists()) { 5 out.getParentFile().mkdirs(); 6 } 7 try (FileOutputStream outputStream = new FileOutputStream(filename); 8 ByteArrayOutputStream outputData = new ByteArrayOutputStream()) { 9 bitmap.compress(Bitmap.CompressFormat.PNG, 100, outputData); 10 outputData.writeTo(outputStream); 11 outputStream.flush(); 12 outputStream.close(); 13 } 14 catch (IOException ex) { 15 throw new IOException("Failed to save bitmap to disk" + ex, ex); 16 } 17 } 18
補足情報(FW/ツールのバージョンなど)
- Android Studio 3.5.3
- API 29 Android 10.0 (Q)
参考サイト様:https://ktaka.github.io/codelab/sceneform-ar-ja/#15
この問題につきまして、何か誤り等があれば教えていただければ幸いです。
念の為、以下に関連する処理を張っておきます。
よろしくお願い致します。
private String generateFilename() { String date = new SimpleDateFormat("yyyyMMddHHmmss", java.util.Locale.getDefault()).format(new Date()); return Environment.getExternalStoragePublicDirectory( Environment.DIRECTORY_PICTURES) + File.separator + "Sceneform/" + date + "_screenshot.jpg"; } private void saveBitmapToDisk(Bitmap bitmap, String filename) throws IOException { File out = new File(filename); if (!out.getParentFile().exists()) { out.getParentFile().mkdirs(); } try (FileOutputStream outputStream = new FileOutputStream(filename); ByteArrayOutputStream outputData = new ByteArrayOutputStream()) { bitmap.compress(Bitmap.CompressFormat.PNG, 100, outputData); outputData.writeTo(outputStream); outputStream.flush(); outputStream.close(); } catch (IOException ex) { throw new IOException("Failed to save bitmap to disk" + ex, ex); } } private void takePhoto() { final String filename = generateFilename(); ArSceneView view = fragment.getArSceneView(); // Create a bitmap the size of the scene view. final Bitmap bitmap = Bitmap.createBitmap(view.getWidth(), view.getHeight(), Bitmap.Config.ARGB_8888); // Create a handler thread to offload the processing of the image. final HandlerThread handlerThread = new HandlerThread("PixelCopier"); handlerThread.start(); // Make the request to copy. PixelCopy.request(view, bitmap, (copyResult) -> { if (copyResult == PixelCopy.SUCCESS) { try { saveBitmapToDisk(bitmap, filename); } catch (IOException e) { Toast toast = Toast.makeText(MainActivity.this, e.toString(), Toast.LENGTH_LONG); toast.show(); return; } Snackbar snackbar = Snackbar.make(findViewById(android.R.id.content), "Photo saved", Snackbar.LENGTH_LONG); snackbar.setAction("Open in Photos", v -> { File photoFile = new File(filename); Uri photoURI = FileProvider.getUriForFile(MainActivity.this, MainActivity.this.getPackageName() + ".ar.codelab.name.provider", photoFile); Intent intent = new Intent(Intent.ACTION_VIEW, photoURI); intent.setDataAndType(photoURI, "image/*"); intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); startActivity(intent); }); snackbar.show(); } else { Toast toast = Toast.makeText(MainActivity.this, "Failed to copyPixels: " + copyResult, Toast.LENGTH_LONG); toast.show(); } handlerThread.quitSafely(); }, new Handler(handlerThread.getLooper())); }
回答2件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。