Android 외부 저장소에 파일 저장
디렉토리를 만들고 Android 애플리케이션에 파일을 저장하는 데 약간의 문제가 있습니다. 이 코드를 사용하고 있습니다.
String filename = "MyApp/MediaTag/MediaTag-"+objectId+".png";
File file = new File(Environment.getExternalStorageDirectory(), filename);
FileOutputStream fos;
fos = new FileOutputStream(file);
fos.write(mediaTagBuffer);
fos.flush();
fos.close();
하지만 예외가 발생합니다.
java.io.FileNotFoundException : /mnt/sdcard/MyApp/MediaCard/MediaCard-0.png (해당 파일 또는 디렉토리 없음)
그 줄에 : fos = new FileOutputStream(file);
파일 이름을 다음과 같이 설정하면 "MyApp/MediaTag-"+objectId+"
작동하지만 파일을 만들고 다른 디렉토리에 저장하려고하면 예외가 발생합니다. 그래서 내가 뭘 잘못하고 있는지 어떤 아이디어?
그리고 또 다른 질문 : 사용자가 자신의 장치를 다음과 같이 연결하는 경우에만 사용자가 갤러리에서 파일을 볼 수 없도록 외부 저장소에서 내 파일을 비공개로 만들 수있는 방법이 Disk Drive
있습니까?
이 기능을 사용하여 SD 카드에 비트 맵을 저장하십시오.
private void SaveImage(Bitmap finalBitmap) {
String root = Environment.getExternalStorageDirectory().toString();
File myDir = new File(root + "/saved_images");
if (!myDir.exists()) {
myDir.mkdirs();
}
Random generator = new Random();
int n = 10000;
n = generator.nextInt(n);
String fname = "Image-"+ n +".jpg";
File file = new File (myDir, fname);
if (file.exists ())
file.delete ();
try {
FileOutputStream out = new FileOutputStream(file);
finalBitmap.compress(Bitmap.CompressFormat.JPEG, 90, out);
out.flush();
out.close();
} catch (Exception e) {
e.printStackTrace();
}
}
그리고 이것을 매니페스트에 추가하십시오
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
편집 : 이 라인을 사용하면 갤러리보기에서 저장된 이미지를 볼 수 있습니다.
sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED,
Uri.parse("file://" + Environment.getExternalStorageDirectory())));
이 링크도 http://rajareddypolam.wordpress.com/?p=3&preview=true 보세요
RajaReddy가 제시 한 코드는 더 이상 KitKat에서 작동하지 않습니다.
이것은 (2 개의 변경 사항) :
private void saveImageToExternalStorage(Bitmap finalBitmap) {
String root = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES).toString();
File myDir = new File(root + "/saved_images");
myDir.mkdirs();
Random generator = new Random();
int n = 10000;
n = generator.nextInt(n);
String fname = "Image-" + n + ".jpg";
File file = new File(myDir, fname);
if (file.exists())
file.delete();
try {
FileOutputStream out = new FileOutputStream(file);
finalBitmap.compress(Bitmap.CompressFormat.JPEG, 90, out);
out.flush();
out.close();
}
catch (Exception e) {
e.printStackTrace();
}
// Tell the media scanner about the new file so that it is
// immediately available to the user.
MediaScannerConnection.scanFile(this, new String[] { file.toString() }, null,
new MediaScannerConnection.OnScanCompletedListener() {
public void onScanCompleted(String path, Uri uri) {
Log.i("ExternalStorage", "Scanned " + path + ":");
Log.i("ExternalStorage", "-> uri=" + uri);
}
});
}
이에 대한 권한이 필요합니다.
< uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
public boolean saveImageOnExternalData(String filePath, byte[] fileData) {
boolean isFileSaved = false;
try {
File f = new File(filePath);
if (f.exists())
f.delete();
f.createNewFile();
FileOutputStream fos = new FileOutputStream(f);
fos.write(fileData);
fos.flush();
fos.close();
isFileSaved = true;
// File Saved
} catch (FileNotFoundException e) {
System.out.println("FileNotFoundException");
e.printStackTrace();
} catch (IOException e) {
System.out.println("IOException");
e.printStackTrace();
}
return isFileSaved;
// File Not Saved
}
앱에 외부 저장소에 쓸 수있는 적절한 권한이 있는지 확인하세요. http://developer.android.com/reference/android/Manifest.permission.html#WRITE_EXTERNAL_STORAGE
매니페스트 파일에서 다음과 같이 보일 것입니다.
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
이 시도 :
- 외부 저장 장치 확인
- 파일 쓰기
- 파일 읽기
public class WriteSDCard extends Activity {
private static final String TAG = "MEDIA";
private TextView tv;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
tv = (TextView) findViewById(R.id.TextView01);
checkExternalMedia();
writeToSDFile();
readRaw();
}
/**
* Method to check whether external media available and writable. This is
* adapted from
* http://developer.android.com/guide/topics/data/data-storage.html
* #filesExternal
*/
private void checkExternalMedia() {
boolean mExternalStorageAvailable = false;
boolean mExternalStorageWriteable = false;
String state = Environment.getExternalStorageState();
if (Environment.MEDIA_MOUNTED.equals(state)) {
// Can read and write the media
mExternalStorageAvailable = mExternalStorageWriteable = true;
} else if (Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) {
// Can only read the media
mExternalStorageAvailable = true;
mExternalStorageWriteable = false;
} else {
// Can't read or write
mExternalStorageAvailable = mExternalStorageWriteable = false;
}
tv.append("\n\nExternal Media: readable=" + mExternalStorageAvailable
+ " writable=" + mExternalStorageWriteable);
}
/**
* Method to write ascii text characters to file on SD card. Note that you
* must add a WRITE_EXTERNAL_STORAGE permission to the manifest file or this
* method will throw a FileNotFound Exception because you won't have write
* permission.
*/
private void writeToSDFile() {
// Find the root of the external storage.
// See http://developer.android.com/guide/topics/data/data-
// storage.html#filesExternal
File root = android.os.Environment.getExternalStorageDirectory();
tv.append("\nExternal file system root: " + root);
// See
// http://stackoverflow.com/questions/3551821/android-write-to-sd-card-folder
File dir = new File(root.getAbsolutePath() + "/download");
dir.mkdirs();
File file = new File(dir, "myData.txt");
try {
FileOutputStream f = new FileOutputStream(file);
PrintWriter pw = new PrintWriter(f);
pw.println("Hi , How are you");
pw.println("Hello");
pw.flush();
pw.close();
f.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
Log.i(TAG, "******* File not found. Did you"
+ " add a WRITE_EXTERNAL_STORAGE permission to the manifest?");
} catch (IOException e) {
e.printStackTrace();
}
tv.append("\n\nFile written to " + file);
}
/**
* Method to read in a text file placed in the res/raw directory of the
* application. The method reads in all lines of the file sequentially.
*/
private void readRaw() {
tv.append("\nData read from res/raw/textfile.txt:");
InputStream is = this.getResources().openRawResource(R.raw.textfile);
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr, 8192); // 2nd arg is buffer
// size
// More efficient (less readable) implementation of above is the
// composite expression
/*
* BufferedReader br = new BufferedReader(new InputStreamReader(
* this.getResources().openRawResource(R.raw.textfile)), 8192);
*/
try {
String test;
while (true) {
test = br.readLine();
// readLine() returns null if no more lines in the file
if (test == null) break;
tv.append("\n" + " " + test);
}
isr.close();
is.close();
br.close();
} catch (IOException e) {
e.printStackTrace();
}
tv.append("\n\nThat is all");
}
}
비트 맵을 저장하기 위해 AsyncTask를 만들었습니다.
public class BitmapSaver extends AsyncTask<Void, Void, Void>
{
public static final String TAG ="BitmapSaver";
private Bitmap bmp;
private Context ctx;
private File pictureFile;
public BitmapSaver(Context paramContext , Bitmap paramBitmap)
{
ctx = paramContext;
bmp = paramBitmap;
}
/** Create a File for saving an image or video */
private File getOutputMediaFile()
{
// To be safe, you should check that the SDCard is mounted
// using Environment.getExternalStorageState() before doing this.
File mediaStorageDir = new File(Environment.getExternalStorageDirectory()
+ "/Android/data/"
+ ctx.getPackageName()
+ "/Files");
// This location works best if you want the created images to be shared
// between applications and persist after your app has been uninstalled.
// Create the storage directory if it does not exist
if (! mediaStorageDir.exists()){
if (! mediaStorageDir.mkdirs()){
return null;
}
}
// Create a media file name
String timeStamp = new SimpleDateFormat("ddMMyyyy_HHmm").format(new Date());
File mediaFile;
String mImageName="MI_"+ timeStamp +".jpg";
mediaFile = new File(mediaStorageDir.getPath() + File.separator + mImageName);
return mediaFile;
}
protected Void doInBackground(Void... paramVarArgs)
{
this.pictureFile = getOutputMediaFile();
if (this.pictureFile == null) { return null; }
try
{
FileOutputStream localFileOutputStream = new FileOutputStream(this.pictureFile);
this.bmp.compress(Bitmap.CompressFormat.PNG, 90, localFileOutputStream);
localFileOutputStream.close();
}
catch (FileNotFoundException localFileNotFoundException)
{
return null;
}
catch (IOException localIOException)
{
}
return null;
}
protected void onPostExecute(Void paramVoid)
{
super.onPostExecute(paramVoid);
try
{
//it will help you broadcast and view the saved bitmap in Gallery
this.ctx.sendBroadcast(new Intent("android.intent.action.MEDIA_MOUNTED", Uri
.parse("file://" + Environment.getExternalStorageDirectory())));
Toast.makeText(this.ctx, "File saved", 0).show();
return;
}
catch (Exception localException1)
{
try
{
Context localContext = this.ctx;
String[] arrayOfString = new String[1];
arrayOfString[0] = this.pictureFile.toString();
MediaScannerConnection.scanFile(localContext, arrayOfString, null,
new MediaScannerConnection.OnScanCompletedListener()
{
public void onScanCompleted(String paramAnonymousString ,
Uri paramAnonymousUri)
{
}
});
return;
}
catch (Exception localException2)
{
}
}
}
}
아마도 MediaCard
subdir 이 없기 때문에 예외가 발생 합니다. 경로에있는 모든 디렉토리가 있는지 확인해야합니다.
파일 가시성 정보 : .nomedia
디렉토리에 이름이 지정된 파일을 넣으면 Android에 미디어 파일 검색을 원하지 않으며 갤러리에 표시되지 않는다고 말하는 것입니다.
업데이트 2018, SDK> = 23.
이제 다음을 사용하여 사용자가 외부 저장소에 대한 권한을 부여 했는지도 확인해야합니다.
public boolean isStoragePermissionGranted() {
String TAG = "Storage Permission";
if (Build.VERSION.SDK_INT >= 23) {
if (this.checkSelfPermission(android.Manifest.permission.WRITE_EXTERNAL_STORAGE)
== PackageManager.PERMISSION_GRANTED) {
Log.v(TAG, "Permission is granted");
return true;
} else {
Log.v(TAG, "Permission is revoked");
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1);
return false;
}
}
else { //permission is automatically granted on sdk<23 upon installation
Log.v(TAG,"Permission is granted");
return true;
}
}
public void saveImageBitmap(Bitmap image_bitmap, String image_name) {
String root = Environment.getExternalStorageDirectory().toString();
if (isStoragePermissionGranted()) { // check or ask permission
File myDir = new File(root, "/saved_images");
if (!myDir.exists()) {
myDir.mkdirs();
}
String fname = "Image-" + image_name + ".jpg";
File file = new File(myDir, fname);
if (file.exists()) {
file.delete();
}
try {
file.createNewFile(); // if file already exists will do nothing
FileOutputStream out = new FileOutputStream(file);
image_bitmap.compress(Bitmap.CompressFormat.JPEG, 90, out);
out.flush();
out.close();
} catch (Exception e) {
e.printStackTrace();
}
MediaScannerConnection.scanFile(this, new String[]{file.toString()}, new String[]{file.getName()}, null);
}
}
물론 다음을 추가하십시오 AndroidManifest.xml
.
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
안드로이드 4.4 이후 파일 저장이 변경되었습니다. 있다
ContextCompat.getExternalFilesDirs(context, name);
배열을 되돌립니다.
이름이 null 인 경우
첫 번째 값은 /storage/emulated/0/Android/com.my.package/files와 같습니다.
두 번째 값은 /storage/extSdCard/Android/com.my.package/files와 같습니다.
Android 4.3 이하에서는 단일 항목 배열을 반환합니다.
약간 지저분한 코드의 일부이지만 작동 방식을 보여줍니다.
/** Create a File for saving an image or video
* @throws Exception */
private File getOutputMediaFile(int type) throws Exception{
// Check that the SDCard is mounted
File mediaStorageDir;
if(internalstorage.isChecked())
{
mediaStorageDir = new File(getFilesDir().getAbsolutePath() );
}
else
{
File[] dirs=ContextCompat.getExternalFilesDirs(this, null);
mediaStorageDir = new File(dirs[dirs.length>1?1:0].getAbsolutePath() );
}
// Create the storage directory(MyCameraVideo) if it does not exist
if (! mediaStorageDir.exists()){
if (! mediaStorageDir.mkdirs()){
output.setText("Failed to create directory.");
Toast.makeText(this, "Failed to create directory.", Toast.LENGTH_LONG).show();
Log.d("myapp", "Failed to create directory");
return null;
}
}
// Create a media file name
// For unique file name appending current timeStamp with file name
java.util.Date date= new java.util.Date();
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss",Locale.ENGLISH) .format(date.getTime());
File mediaFile;
if(type == MEDIA_TYPE_VIDEO) {
// For unique video file name appending current timeStamp with file name
mediaFile = new File(mediaStorageDir.getPath() + File.separator + slpid + "_" + pwsid + "_" + timeStamp + ".mp4");
}
else if(type == MEDIA_TYPE_AUDIO) {
// For unique video file name appending current timeStamp with file name
mediaFile = new File(mediaStorageDir.getPath() + File.separator + slpid + "_" + pwsid + "_" + timeStamp + ".3gp");
} else {
return null;
}
return mediaFile;
}
/** Create a file Uri for saving an image or video
* @throws Exception */
private Uri getOutputMediaFileUri(int type) throws Exception{
return Uri.fromFile(getOutputMediaFile(type));
}
//usage:
try {
file=getOutputMediaFileUri(MEDIA_TYPE_AUDIO).getPath();
} catch (Exception e1) {
e1.printStackTrace();
return;
}
API 레벨 23 (Marshmallow) 이상에서는 매니페스트의 사용 권한 외에 팝업 권한도 구현해야하며, 사용자는 런타임에 앱을 사용하는 동안 권한을 부여해야합니다.
다음은 그림 디렉터리 내의 디렉터리 hello world!
에 myFile.txt
파일 내용 으로 저장하는 예 Test
입니다.
매니페스트에서 :
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
파일을 만들 위치 :
int permission = ActivityCompat.checkSelfPermission(MainActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE);
String[] PERMISSIONS_STORAGE = {Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE};
if (permission != PackageManager.PERMISSION_GRANTED)
{
ActivityCompat.requestPermissions(MainActivity.this,PERMISSIONS_STORAGE, 1);
}
File myDir = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), "Test");
myDir.mkdirs();
try
{
String FILENAME = "myFile.txt";
File file = new File (myDir, FILENAME);
String string = "hello world!";
FileOutputStream fos = new FileOutputStream(file);
fos.write(string.getBytes());
fos.close();
}
catch (IOException e) {
e.printStackTrace();
}
이 코드는 훌륭하게 작동하며 KitKat에서도 작동합니다. @RajaReddy PolamReddy에 감사드립니다.
여기에 몇 가지 단계가 더 추가되었으며 갤러리에도 표시됩니다.
public void SaveOnClick(View v){
File mainfile;
String fpath;
try {
//i.e v2:My view to save on own folder
v2.setDrawingCacheEnabled(true);
//Your final bitmap according to my code.
bitmap_tmp = v2.getDrawingCache();
File(getExternalFilesDir(Environment.DIRECTORY_PICTURES)+File.separator+"/MyFolder");
Random random=new Random();
int ii=100000;
ii=random.nextInt(ii);
String fname="MyPic_"+ ii + ".jpg";
File direct = new File(Environment.getExternalStorageDirectory() + "/MyFolder");
if (!direct.exists()) {
File wallpaperDirectory = new File("/sdcard/MyFolder/");
wallpaperDirectory.mkdirs();
}
mainfile = new File(new File("/sdcard/MyFolder/"), fname);
if (mainfile.exists()) {
mainfile.delete();
}
FileOutputStream fileOutputStream;
fileOutputStream = new FileOutputStream(mainfile);
bitmap_tmp.compress(CompressFormat.JPEG, 100, fileOutputStream);
Toast.makeText(MyActivity.this.getApplicationContext(), "Saved in Gallery..", Toast.LENGTH_LONG).show();
fileOutputStream.flush();
fileOutputStream.close();
fpath=mainfile.toString();
galleryAddPic(fpath);
} catch(FileNotFoundException e){
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
갤러리에서 볼 수있는 미디어 스캐너입니다.
private void galleryAddPic(String fpath) {
Intent mediaScanIntent = new Intent("android.intent.action.MEDIA_SCANNER_SCAN_FILE");
File f = new File(fpath);
Uri contentUri = Uri.fromFile(f);
mediaScanIntent.setData(contentUri);
this.sendBroadcast(mediaScanIntent);
}
전체 설명 및 소스 코드를 보려면 여기 를 클릭하십시오.
public void saveImage(Context mContext, Bitmap bitmapImage) {
File sampleDir = new File(Environment.getExternalStorageDirectory() + "/" + "ApplicationName");
TextView tvImageLocation = (TextView) findViewById(R.id.tvImageLocation);
tvImageLocation.setText("Image Store At : " + sampleDir);
if (!sampleDir.exists()) {
createpathForImage(mContext, bitmapImage, sampleDir);
} else {
createpathForImage(mContext, bitmapImage, sampleDir);
}
}
참고 URL : https://stackoverflow.com/questions/7887078/android-saving-file-to-external-storage
'program story' 카테고리의 다른 글
파이썬에서 int ()의 직관적이지 않은 동작 (0) | 2020.09.23 |
---|---|
2보다 큰 MySQL 수 발생 (0) | 2020.09.23 |
Visual Studio 2012의 모든 설정을 어떻게 재설정합니까? (0) | 2020.09.23 |
SharedPreferences에서 일부 키 / 값 쌍을 제거하는 방법은 무엇입니까? (0) | 2020.09.23 |
SQL Server 2005 데이터베이스에서 가장 많은 공간을 차지하는 테이블을 어떻게 알 수 있습니까? (0) | 2020.09.23 |