Android에서 이미지를 다운로드하고 저장하는 방법
Android의 지정된 URL에서 이미지를 어떻게 다운로드하고 저장합니까?
2015 년 12 월 30 일 편집-이미지 다운로드에 대한 궁극적 인 가이드
마지막 주요 업데이트 : 2016 년 3 월 31 일
TL; DR 일명 그만 얘기해, 그냥 코드를 줘 !!
이 게시물의 맨 아래로 건너 뛰고
BasicImageDownloader
( 여기에서 javadoc 버전 ) 프로젝트에 복사 하고OnImageLoaderListener
인터페이스를 구현하면 완료됩니다.참고 :에서
BasicImageDownloader
가능한 오류를 처리하고 문제가 발생할 경우 앱이 다운되는 것을 방지 하지만 다운로드 한 .NET에서 사후 처리 (예 : 크기 축소)를 수행하지 않습니다Bitmaps
.
이 게시물은 많은 관심을 받았기 때문에 사람들이 더 이상 사용되지 않는 기술, 나쁜 프로그래밍 관행을 사용하거나 어리석은 일을하는 것을 방지하기 위해 완전히 재 작업하기로 결정했습니다. 모든 SSL 인증서를 수락합니다.
필자는 자체 다운로더 구현, Android 내장 및 DownloadManager
일부 인기있는 오픈 소스 라이브러리를 사용하여 이미지를 다운로드 (및 저장)하는 방법을 보여주는 "Image Downloader"라는 데모 프로젝트를 만들었습니다 . 전체 소스 코드를 보거나 GitHub 에서 프로젝트 를 다운로드 할 수 있습니다 .
참고 : 아직 SDK 23+ (Marshmallow)에 대한 권한 관리를 조정하지 않았으므로 프로젝트는 SDK 22 (Lollipop)를 대상으로합니다.
내에서 결론 이 게시물의 끝에 나는 공유 할 것입니다 내 소견 내가 언급 한 이미지 다운로드의 각각의 특정 방법에 대한 적절한 사용 사례에 대한합니다.
자체 구현부터 시작하겠습니다 (게시물 끝에서 코드를 찾을 수 있음). 우선 이것은 기본 ImageDownloader이고 그게 다입니다. 그것이하는 일은 주어진 URL에 연결하고, 데이터를 읽고, 그것을으로 디코딩하려고 시도하고 Bitmap
, OnImageLoaderListener
적절한 경우 인터페이스 콜백을 트리거하는 것 입니다. 이 접근 방식의 장점은 간단하며 진행 상황에 대한 명확한 개요를 제공합니다. 메모리 / 디스크 캐시를 유지하는 데 신경 쓰지 않는 동안 필요한 모든 이미지를 다운로드 / 표시 및 저장하는 것이 좋은 방법입니다.
참고 : 큰 이미지의 경우 축소 해야 할 수 있습니다 .
-
Android DownloadManager 는 시스템이 다운로드를 처리하도록하는 방법입니다. 실제로 이미지뿐만 아니라 모든 종류의 파일을 다운로드 할 수 있습니다. 다운로드가 조용하고 사용자에게 표시되지 않도록하거나 사용자가 알림 영역에서 다운로드를 볼 수 있도록 할 수 있습니다. BroadcastReceiver
다운로드가 완료된 후 알림을 받도록 등록 할 수도 있습니다 . 설정은 매우 간단합니다. 샘플 코드는 링크 된 프로젝트를 참조하십시오.
(가) 사용 DownloadManager
당신은 또한 이미지를 표시하려는 경우 읽고 바로 다운로드 설정하는 대신 저장된 파일을 디코딩해야하는 것 때문에, 일반적으로 좋은 생각이 아니다 Bitmap
로 ImageView
. 은 DownloadManager
당신이 다운로드 진행 상황을 추적하는 앱도 어떤 API를 제공하지 않습니다.
-
이제 훌륭한 물건 인 도서관을 소개합니다. 메모리 / 디스크 캐시 생성 및 관리, 이미지 크기 조정, 이미지 변환 등을 포함하여 이미지를 다운로드하고 표시하는 것 이상을 수행 할 수 있습니다.
Google에서 만들고 공식 문서로 다루는 강력한 라이브러리 인 Volley 부터 시작하겠습니다 . Volley는 이미지를 전문으로하지 않는 범용 네트워킹 라이브러리이지만 이미지 관리를위한 강력한 API를 제공합니다.
Volley 요청을 관리하기 위해 Singleton 클래스 를 구현해야합니다 .
ImageView
를 Volley 's 로 바꾸고 싶을 수 있으므로 NetworkImageView
다운로드는 기본적으로 한 줄짜리가됩니다.
((NetworkImageView) findViewById(R.id.myNIV)).setImageUrl(url, MySingleton.getInstance(this).getImageLoader());
더 많은 제어가 필요한 경우 ImageRequest
Volley 로 만드는 것이 다음과 같습니다 .
ImageRequest imgRequest = new ImageRequest(url, new Response.Listener<Bitmap>() {
@Override
public void onResponse(Bitmap response) {
//do stuff
}
}, 0, 0, ImageView.ScaleType.CENTER_CROP, Bitmap.Config.ARGB_8888,
new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
//do stuff
}
});
Volley는 오류 VolleyError
의 정확한 원인을 파악하는 데 도움이 되는 클래스를 제공하여 뛰어난 오류 처리 메커니즘을 제공한다는 점을 언급 할 가치가 있습니다. 앱이 많은 네트워킹을 수행하고 이미지를 관리하는 것이 주요 목적이 아니라면 Volley가 적합합니다.
-
Square의 Picasso 는 모든 이미지 로딩 작업을 수행하는 잘 알려진 라이브러리입니다. Picasso를 사용하여 이미지를 표시하는 것은 다음과 같이 간단합니다.
Picasso.with(myContext)
.load(url)
.into(myImageView);
기본적으로 Picasso는 디스크 / 메모리 캐시를 관리하므로 걱정할 필요가 없습니다. 더 많은 제어를 위해 Target
인터페이스를 구현하고 이를 사용하여 이미지를로드 할 수 있습니다. 그러면 Volley 예제와 유사한 콜백이 제공됩니다. 예제는 데모 프로젝트를 확인하십시오.
Picasso를 사용하면 다운로드 한 이미지에 변환을 적용 할 수 있으며 해당 API를 확장하는 다른 라이브러리 도 있습니다. 또한 RecyclerView
/ ListView
/ 에서 매우 잘 작동합니다 GridView
.
-
Universal Image Loader 는 이미지 관리 목적을 제공하는 또 다른 매우 인기있는 라이브러리입니다. ImageLoader
한 줄의 코드로 이미지를 다운로드하는 데 사용할 수있는 전역 인스턴스 (초기화되면)가있는 자체 를 사용합니다.
ImageLoader.getInstance().displayImage(url, myImageView);
다운로드 진행 상황을 추적하거나 다운로드 한 파일에 액세스하려는 경우 Bitmap
:
ImageLoader.getInstance().displayImage(url, myImageView, opts,
new ImageLoadingListener() {
@Override
public void onLoadingStarted(String imageUri, View view) {
//do stuff
}
@Override
public void onLoadingFailed(String imageUri, View view, FailReason failReason) {
//do stuff
}
@Override
public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) {
//do stuff
}
@Override
public void onLoadingCancelled(String imageUri, View view) {
//do stuff
}
}, new ImageLoadingProgressListener() {
@Override
public void onProgressUpdate(String imageUri, View view, int current, int total) {
//do stuff
}
});
opts
이 예제 의 인수는 DisplayImageOptions
객체입니다. 자세한 내용은 데모 프로젝트를 참조하십시오.
Volley와 마찬가지로 UIL은 FailReason
다운로드 실패시 무엇이 잘못되었는지 확인할 수 있는 클래스를 제공합니다 . 기본적으로 UIL은 명시 적으로 지정하지 않으면 메모리 / 디스크 캐시를 유지합니다.
참고 : 저자는 2015 년 11 월 27 일 현재 더 이상 프로젝트를 유지하지 않는다고 언급했습니다.하지만 많은 기여자가 있기 때문에 Universal Image Loader가 계속 유지되기를 바랍니다.
-
Facebook의 Fresco 는 최신 버전이며 (IMO)는 이미지 관리를 새로운 수준으로 끌어 올리는 가장 진보 된 라이브러리입니다 Bitmaps
. Java 힙 (Lollipop 이전)에서 애니메이션 형식 및 점진적 JPEG 스트리밍 지원에 이르기까지 .
Fresco의 아이디어와 기술에 대한 자세한 내용은 이 게시물을 참조하십시오 .
기본적인 사용법은 아주 간단합니다. 클래스 Fresco.initialize(Context);
에서 선호하는 한 번만 호출 하면 Application
됩니다. Fresco를 두 번 이상 초기화하면 예기치 않은 동작과 OOM 오류가 발생할 수 있습니다.
Fresco는 Drawee
s를 사용 하여 이미지를 표시하므로 다음과 같이 생각할 수 있습니다 ImageView
.
<com.facebook.drawee.view.SimpleDraweeView
android:id="@+id/drawee"
android:layout_width="match_parent"
android:layout_height="match_parent"
fresco:fadeDuration="500"
fresco:actualImageScaleType="centerCrop"
fresco:placeholderImage="@drawable/placeholder_grey"
fresco:failureImage="@drawable/error_orange"
fresco:placeholderImageScaleType="fitCenter"
fresco:failureImageScaleType="centerInside"
fresco:retryImageScaleType="centerCrop"
fresco:progressBarImageScaleType="centerInside"
fresco:progressBarAutoRotateInterval="1000"
fresco:roundAsCircle="false" />
보시다시피 변환 옵션을 포함한 많은 항목이 이미 XML로 정의되어 있으므로 이미지를 표시하는 데 필요한 것은 한 줄만 있으면됩니다.
mDrawee.setImageURI(Uri.parse(url));
Fresco는 확장 된 사용자 정의 API를 제공하는데, 상황에서는 매우 복잡 할 수 있으며 사용자가 문서를주의 깊게 읽어야합니다 (예, 때로는 RTFM 이 필요함 ).
프로그레시브 JPEG와 애니메이션 이미지에 대한 예제를 샘플 프로젝트에 포함했습니다.
결론- "대단한 것들을 배웠습니다. 이제 무엇을 사용해야합니까?"
다음 텍스트는 내 개인적인 의견을 반영하며 가정으로 간주해서는 안됩니다.
- 일부 이미지 만 다운로드 / 저장 / 표시
Recycler-/Grid-/ListView
할 필요가 있고 이미지를 a 에서 사용할 계획 이없고 전체 이미지를 표시 할 필요가없는 경우 BasicImageDownloader 가 사용자의 요구에 맞아야합니다. - 앱이 사용자 또는 자동화 된 작업의 결과로 이미지 (또는 기타 파일)를 저장하고 이미지를 자주 표시 할 필요가없는 경우 Android DownloadManager를 사용 하세요 .
- 앱이 많은 네트워킹을 수행하고,
JSON
데이터를 전송 / 수신 하고, 이미지로 작동하지만 이것이 앱의 주요 목적이 아닌 경우 Volley를 사용하십시오 . - 앱이 이미지 / 미디어 중심이며 이미지에 일부 변형을 적용하고 복잡한 API를 사용하고 싶지 않습니다. Picasso를 사용하십시오 (참고 : 중간 다운로드 상태를 추적하는 API를 제공하지 않음) 또는 Universal Image 짐을 싣는 사람
- 앱이 이미지에 관한 것이라면 애니메이션 형식 표시와 같은 고급 기능이 필요하고 문서를 읽을 준비가 된 경우 Fresco를 사용하십시오 .
그것을 놓친 경우 데모 프로젝트에 대한 Github 링크 .
그리고 여기에 BasicImageDownloader.java
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.support.annotation.NonNull;
import android.util.Log;
import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
import java.util.HashSet;
import java.util.Set;
public class BasicImageDownloader {
private OnImageLoaderListener mImageLoaderListener;
private Set<String> mUrlsInProgress = new HashSet<>();
private final String TAG = this.getClass().getSimpleName();
public BasicImageDownloader(@NonNull OnImageLoaderListener listener) {
this.mImageLoaderListener = listener;
}
public interface OnImageLoaderListener {
void onError(ImageError error);
void onProgressChange(int percent);
void onComplete(Bitmap result);
}
public void download(@NonNull final String imageUrl, final boolean displayProgress) {
if (mUrlsInProgress.contains(imageUrl)) {
Log.w(TAG, "a download for this url is already running, " +
"no further download will be started");
return;
}
new AsyncTask<Void, Integer, Bitmap>() {
private ImageError error;
@Override
protected void onPreExecute() {
mUrlsInProgress.add(imageUrl);
Log.d(TAG, "starting download");
}
@Override
protected void onCancelled() {
mUrlsInProgress.remove(imageUrl);
mImageLoaderListener.onError(error);
}
@Override
protected void onProgressUpdate(Integer... values) {
mImageLoaderListener.onProgressChange(values[0]);
}
@Override
protected Bitmap doInBackground(Void... params) {
Bitmap bitmap = null;
HttpURLConnection connection = null;
InputStream is = null;
ByteArrayOutputStream out = null;
try {
connection = (HttpURLConnection) new URL(imageUrl).openConnection();
if (displayProgress) {
connection.connect();
final int length = connection.getContentLength();
if (length <= 0) {
error = new ImageError("Invalid content length. The URL is probably not pointing to a file")
.setErrorCode(ImageError.ERROR_INVALID_FILE);
this.cancel(true);
}
is = new BufferedInputStream(connection.getInputStream(), 8192);
out = new ByteArrayOutputStream();
byte bytes[] = new byte[8192];
int count;
long read = 0;
while ((count = is.read(bytes)) != -1) {
read += count;
out.write(bytes, 0, count);
publishProgress((int) ((read * 100) / length));
}
bitmap = BitmapFactory.decodeByteArray(out.toByteArray(), 0, out.size());
} else {
is = connection.getInputStream();
bitmap = BitmapFactory.decodeStream(is);
}
} catch (Throwable e) {
if (!this.isCancelled()) {
error = new ImageError(e).setErrorCode(ImageError.ERROR_GENERAL_EXCEPTION);
this.cancel(true);
}
} finally {
try {
if (connection != null)
connection.disconnect();
if (out != null) {
out.flush();
out.close();
}
if (is != null)
is.close();
} catch (Exception e) {
e.printStackTrace();
}
}
return bitmap;
}
@Override
protected void onPostExecute(Bitmap result) {
if (result == null) {
Log.e(TAG, "factory returned a null result");
mImageLoaderListener.onError(new ImageError("downloaded file could not be decoded as bitmap")
.setErrorCode(ImageError.ERROR_DECODE_FAILED));
} else {
Log.d(TAG, "download complete, " + result.getByteCount() +
" bytes transferred");
mImageLoaderListener.onComplete(result);
}
mUrlsInProgress.remove(imageUrl);
System.gc();
}
}.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
public interface OnBitmapSaveListener {
void onBitmapSaved();
void onBitmapSaveError(ImageError error);
}
public static void writeToDisk(@NonNull final File imageFile, @NonNull final Bitmap image,
@NonNull final OnBitmapSaveListener listener,
@NonNull final Bitmap.CompressFormat format, boolean shouldOverwrite) {
if (imageFile.isDirectory()) {
listener.onBitmapSaveError(new ImageError("the specified path points to a directory, " +
"should be a file").setErrorCode(ImageError.ERROR_IS_DIRECTORY));
return;
}
if (imageFile.exists()) {
if (!shouldOverwrite) {
listener.onBitmapSaveError(new ImageError("file already exists, " +
"write operation cancelled").setErrorCode(ImageError.ERROR_FILE_EXISTS));
return;
} else if (!imageFile.delete()) {
listener.onBitmapSaveError(new ImageError("could not delete existing file, " +
"most likely the write permission was denied")
.setErrorCode(ImageError.ERROR_PERMISSION_DENIED));
return;
}
}
File parent = imageFile.getParentFile();
if (!parent.exists() && !parent.mkdirs()) {
listener.onBitmapSaveError(new ImageError("could not create parent directory")
.setErrorCode(ImageError.ERROR_PERMISSION_DENIED));
return;
}
try {
if (!imageFile.createNewFile()) {
listener.onBitmapSaveError(new ImageError("could not create file")
.setErrorCode(ImageError.ERROR_PERMISSION_DENIED));
return;
}
} catch (IOException e) {
listener.onBitmapSaveError(new ImageError(e).setErrorCode(ImageError.ERROR_GENERAL_EXCEPTION));
return;
}
new AsyncTask<Void, Void, Void>() {
private ImageError error;
@Override
protected Void doInBackground(Void... params) {
FileOutputStream fos = null;
try {
fos = new FileOutputStream(imageFile);
image.compress(format, 100, fos);
} catch (IOException e) {
error = new ImageError(e).setErrorCode(ImageError.ERROR_GENERAL_EXCEPTION);
this.cancel(true);
} finally {
if (fos != null) {
try {
fos.flush();
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return null;
}
@Override
protected void onCancelled() {
listener.onBitmapSaveError(error);
}
@Override
protected void onPostExecute(Void result) {
listener.onBitmapSaved();
}
}.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
public static Bitmap readFromDisk(@NonNull File imageFile) {
if (!imageFile.exists() || imageFile.isDirectory()) return null;
return BitmapFactory.decodeFile(imageFile.getAbsolutePath());
}
public interface OnImageReadListener {
void onImageRead(Bitmap bitmap);
void onReadFailed();
}
public static void readFromDiskAsync(@NonNull File imageFile, @NonNull final OnImageReadListener listener) {
new AsyncTask<String, Void, Bitmap>() {
@Override
protected Bitmap doInBackground(String... params) {
return BitmapFactory.decodeFile(params[0]);
}
@Override
protected void onPostExecute(Bitmap bitmap) {
if (bitmap != null)
listener.onImageRead(bitmap);
else
listener.onReadFailed();
}
}.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, imageFile.getAbsolutePath());
}
public static final class ImageError extends Throwable {
private int errorCode;
public static final int ERROR_GENERAL_EXCEPTION = -1;
public static final int ERROR_INVALID_FILE = 0;
public static final int ERROR_DECODE_FAILED = 1;
public static final int ERROR_FILE_EXISTS = 2;
public static final int ERROR_PERMISSION_DENIED = 3;
public static final int ERROR_IS_DIRECTORY = 4;
public ImageError(@NonNull String message) {
super(message);
}
public ImageError(@NonNull Throwable error) {
super(error.getMessage(), error.getCause());
this.setStackTrace(error.getStackTrace());
}
public ImageError setErrorCode(int code) {
this.errorCode = code;
return this;
}
public int getErrorCode() {
return errorCode;
}
}
}
나는 방금이 문제를 해결하면서 왔으며 다운로드, sdcard에 저장 (및 파일 이름 숨기기)하고 이미지를 검색하고 마지막으로 이미지가 이미 있는지 확인하는 완전한 코드를 공유하고 싶습니다. URL은 데이터베이스에서 가져 오므로 파일 이름은 id를 사용하여 쉽게 고유 할 수 있습니다.
첫 번째 다운로드 이미지
private class GetImages extends AsyncTask<Object, Object, Object> {
private String requestUrl, imagename_;
private ImageView view;
private Bitmap bitmap ;
private FileOutputStream fos;
private GetImages(String requestUrl, ImageView view, String _imagename_) {
this.requestUrl = requestUrl;
this.view = view;
this.imagename_ = _imagename_ ;
}
@Override
protected Object doInBackground(Object... objects) {
try {
URL url = new URL(requestUrl);
URLConnection conn = url.openConnection();
bitmap = BitmapFactory.decodeStream(conn.getInputStream());
} catch (Exception ex) {
}
return null;
}
@Override
protected void onPostExecute(Object o) {
if(!ImageStorage.checkifImageExists(imagename_))
{
view.setImageBitmap(bitmap);
ImageStorage.saveToSdCard(bitmap, imagename_);
}
}
}
그런 다음 파일을 저장하고 검색하기위한 클래스를 만듭니다.
public class ImageStorage {
public static String saveToSdCard(Bitmap bitmap, String filename) {
String stored = null;
File sdcard = Environment.getExternalStorageDirectory() ;
File folder = new File(sdcard.getAbsoluteFile(), ".your_specific_directory");//the dot makes this directory hidden to the user
folder.mkdir();
File file = new File(folder.getAbsoluteFile(), filename + ".jpg") ;
if (file.exists())
return stored ;
try {
FileOutputStream out = new FileOutputStream(file);
bitmap.compress(Bitmap.CompressFormat.JPEG, 90, out);
out.flush();
out.close();
stored = "success";
} catch (Exception e) {
e.printStackTrace();
}
return stored;
}
public static File getImage(String imagename) {
File mediaImage = null;
try {
String root = Environment.getExternalStorageDirectory().toString();
File myDir = new File(root);
if (!myDir.exists())
return null;
mediaImage = new File(myDir.getPath() + "/.your_specific_directory/"+imagename);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return mediaImage;
}
public static boolean checkifImageExists(String imagename)
{
Bitmap b = null ;
File file = ImageStorage.getImage("/"+imagename+".jpg");
String path = file.getAbsolutePath();
if (path != null)
b = BitmapFactory.decodeFile(path);
if(b == null || b.equals(""))
{
return false ;
}
return true ;
}
}
그런 다음 이미지에 액세스하려면 먼저 이미지가 이미 있는지 확인한 다음 다운로드하십시오.
if(ImageStorage.checkifImageExists(imagename))
{
File file = ImageStorage.getImage("/"+imagename+".jpg");
String path = file.getAbsolutePath();
if (path != null){
b = BitmapFactory.decodeFile(path);
imageView.setImageBitmap(b);
}
} else {
new GetImages(imgurl, imageView, imagename).execute() ;
}
다운로드하려면 왜 자신의 코드가 필요합니까? URI를 다운로드 관리자에 전달하는 것은 어떻습니까?
public void downloadFile(String uRl) {
File direct = new File(Environment.getExternalStorageDirectory()
+ "/AnhsirkDasarp");
if (!direct.exists()) {
direct.mkdirs();
}
DownloadManager mgr = (DownloadManager) getActivity().getSystemService(Context.DOWNLOAD_SERVICE);
Uri downloadUri = Uri.parse(uRl);
DownloadManager.Request request = new DownloadManager.Request(
downloadUri);
request.setAllowedNetworkTypes(
DownloadManager.Request.NETWORK_WIFI
| DownloadManager.Request.NETWORK_MOBILE)
.setAllowedOverRoaming(false).setTitle("Demo")
.setDescription("Something useful. No, really.")
.setDestinationInExternalPublicDir("/AnhsirkDasarp", "fileName.jpg");
mgr.enqueue(request);
}
도움이 될지도 ..
Button download_image = (Button)bigimagedialog.findViewById(R.id.btn_downloadimage);
download_image.setOnClickListener(new View.OnClickListener()
{
public void onClick(View v)
{
boolean success = (new File("/sdcard/dirname")).mkdir();
if (!success)
{
Log.w("directory not created", "directory not created");
}
try
{
URL url = new URL("YOUR_URL");
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setDoInput(true);
connection.connect();
InputStream input = connection.getInputStream();
Bitmap myBitmap = BitmapFactory.decodeStream(input);
String data1 = String.valueOf(String.format("/sdcard/dirname/%d.jpg",System.currentTimeMillis()));
FileOutputStream stream = new FileOutputStream(data1);
ByteArrayOutputStream outstream = new ByteArrayOutputStream();
myBitmap.compress(Bitmap.CompressFormat.JPEG, 85, outstream);
byte[] byteArray = outstream.toByteArray();
stream.write(byteArray);
stream.close();
Toast.makeText(getApplicationContext(), "Downloading Completed", Toast.LENGTH_SHORT).show();
}
catch (Exception e)
{
e.printStackTrace();
}
}
});
완벽하게 작동하는 간단한 솔루션이 있습니다. 코드는 내 것이 아닙니다 . 이 링크 에서 찾았습니다 . 따라야 할 단계는 다음과 같습니다.
1. 이미지를 다운로드하기 전에 안드로이드 내부 저장소에 이미지 파일로 비트 맵을 저장하는 방법을 작성해 보겠습니다. 컨텍스트가 필요하며 getApplicationContext ()에 의해 애플리케이션 컨텍스트에서 패스를 사용하는 것이 좋습니다. 이 메서드는 Activity 클래스 또는 다른 util 클래스에 덤프 될 수 있습니다.
public void saveImage(Context context, Bitmap b, String imageName)
{
FileOutputStream foStream;
try
{
foStream = context.openFileOutput(imageName, Context.MODE_PRIVATE);
b.compress(Bitmap.CompressFormat.PNG, 100, foStream);
foStream.close();
}
catch (Exception e)
{
Log.d("saveImage", "Exception 2, Something went wrong!");
e.printStackTrace();
}
}
2. 이제 andorid의 이미지 파일에 비트 맵을 저장하는 방법이 생겼습니다. URL로 이미지를 다운로드하는 AsyncTask를 작성해 보겠습니다. 이 개인 클래스는 Activity 클래스에 하위 클래스로 배치되어야합니다. 이미지를 다운로드 한 후 onPostExecute 메서드에서 위에서 정의한 saveImage 메서드를 호출하여 이미지를 저장합니다. 이미지 이름은 "my_image.png"로 하드 코딩됩니다.
private class DownloadImage extends AsyncTask<String, Void, Bitmap> {
private String TAG = "DownloadImage";
private Bitmap downloadImageBitmap(String sUrl) {
Bitmap bitmap = null;
try {
InputStream inputStream = new URL(sUrl).openStream(); // Download Image from URL
bitmap = BitmapFactory.decodeStream(inputStream); // Decode Bitmap
inputStream.close();
} catch (Exception e) {
Log.d(TAG, "Exception 1, Something went wrong!");
e.printStackTrace();
}
return bitmap;
}
@Override
protected Bitmap doInBackground(String... params) {
return downloadImageBitmap(params[0]);
}
protected void onPostExecute(Bitmap result) {
saveImage(getApplicationContext(), result, "my_image.png");
}
}
3. 이미지 다운로드를위한 AsyncTask가 정의되어 있지만 해당 AsyncTask를 실행하려면 실행해야합니다. 이렇게하려면 Activity 클래스의 onCreate 메서드 또는 버튼의 onClick 메서드 또는 적합하다고 생각되는 다른 위치에이 줄을 작성합니다.
new DownloadImage().execute("http://developer.android.com/images/activity_lifecycle.png");
이미지는 /data/data/your.app.packagename/files/my_image.jpeg에 저장되어야합니다. 장치에서이 디렉토리에 액세스하려면이 게시물을 확인하십시오.
IMO 이것은 문제를 해결합니다! 이미지로드와 같은 추가 단계를 원하는 경우 다음 추가 단계를 수행 할 수 있습니다.
4. 이미지를 다운로드 한 후 내부 저장소에서 이미지 비트 맵을로드하여 사용할 수있는 방법이 필요합니다. 이미지 비트 맵을로드하는 방법을 작성해 보겠습니다. 이 메서드는 전체 경로없이 컨텍스트와 이미지 파일 이름이라는 두 개의 매개 변수를 사용합니다. context.openFileInput (imageName)은이 파일 이름이 위의 saveImage 메서드에 저장되었을 때 저장 디렉터리에서 파일을 조회합니다.
public Bitmap loadImageBitmap(Context context, String imageName) {
Bitmap bitmap = null;
FileInputStream fiStream;
try {
fiStream = context.openFileInput(imageName);
bitmap = BitmapFactory.decodeStream(fiStream);
fiStream.close();
} catch (Exception e) {
Log.d("saveImage", "Exception 3, Something went wrong!");
e.printStackTrace();
}
return bitmap;
}
5. 이제 ImageView 또는 이미지를 사용하려는 다른보기의 이미지를 설정하는 데 필요한 모든 것이 있습니다. 이미지를 저장할 때 이미지 이름을 "my_image.jpeg"로 하드 코딩했습니다. 이제이 이미지 이름을 위의 loadImageBitmap 메서드에 전달하여 비트 맵을 가져와 ImageView로 설정할 수 있습니다.
someImageView.setImageBitmap(loadImageBitmap(getApplicationContext(), "my_image.jpeg"));
6. 이미지 이름으로 이미지 전체 경로를 얻으려면.
File file = getApplicationContext().getFileStreamPath("my_image.jpeg");
String imageFullPath = file.getAbsolutePath();
7. 이미지 파일이 있는지 확인합니다.
파일 파일 =
getApplicationContext().getFileStreamPath("my_image.jpeg");
if (file.exists()) Log.d("file", "my_image.jpeg exists!");
이미지 파일을 삭제합니다.
파일 파일 = getApplicationContext (). getFileStreamPath ( "my_image.jpeg"); if (file.delete ()) Log.d ( "file", "my_image.jpeg가 삭제되었습니다!");
이 코드는 내 프로젝트에서 완벽하게 실행됩니다.
downloadImagesToSdCard(imagepath,imagepath);
private void downloadImagesToSdCard(String downloadUrl,String imageName)
{
try
{
URL url = new URL("www.xxx.com"+downloadUrl);
/* making a directory in sdcard */
// String sdCard=Environment.getExternalStorageDirectory().toString();
ContextWrapper cw = new ContextWrapper(getActivity());
// path to /data/data/yourapp/app_data/imageDir
File directory = cw.getDir("files", Context.MODE_PRIVATE);
File myDir = new File(directory,"folder");
/* if specified not exist create new */
if(!myDir.exists())
{
myDir.mkdir();
Log.v("", "inside mkdir");
}
/* checks the file and if it already exist delete */
String fname = imageName;
File file = new File (myDir, fname);
Log.d("file===========path", ""+file);
if (file.exists ())
file.delete ();
/* Open a connection */
URLConnection ucon = url.openConnection();
InputStream inputStream = null;
HttpURLConnection httpConn = (HttpURLConnection)ucon;
httpConn.setRequestMethod("GET");
httpConn.connect();
inputStream = httpConn.getInputStream();
/*if (httpConn.getResponseCode() == HttpURLConnection.HTTP_OK)
{
inputStream = httpConn.getInputStream();
}*/
FileOutputStream fos = new FileOutputStream(file);
int totalSize = httpConn.getContentLength();
int downloadedSize = 0;
byte[] buffer = new byte[1024];
int bufferLength = 0;
while ( (bufferLength = inputStream.read(buffer)) >0 )
{
fos.write(buffer, 0, bufferLength);
downloadedSize += bufferLength;
Log.i("Progress:","downloadedSize:"+downloadedSize+"totalSize:"+ totalSize) ;
}
fos.close();
Log.d("test", "Image Saved in sdcard..");
viewimage();
}
catch(IOException io)
{
io.printStackTrace();
}
catch(Exception e)
{
e.printStackTrace();
}
}
public void viewimage()
{
String path = serialnumber+".png";
ContextWrapper cw = new ContextWrapper(getActivity());
//path to /data/data/yourapp/app_data/dirName
File directory = cw.getDir("files", Context.MODE_PRIVATE);
File mypath=new File(directory,"folder/"+path);
Bitmap b;
try {
b = BitmapFactory.decodeStream(new FileInputStream(mypath));
// b.compress(format, quality, stream)
profile_image.setImageBitmap(Bitmap.createScaledBitmap(b, 120, 120, false));
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
이 시도
try
{
Bitmap bmp = null;
URL url = new URL("Your_URL");
URLConnection conn = url.openConnection();
bmp = BitmapFactory.decodeStream(conn.getInputStream());
File f = new File(Environment.getExternalStorageDirectory(),System.currentTimeMillis() + ".jpg");
if(f.exists())
f.delete();
f.createNewFile();
Bitmap bitmap = bmp;
ByteArrayOutputStream bos = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.PNG, 0 /*ignored for PNG*/, bos);
byte[] bitmapdata = bos.toByteArray();
FileOutputStream fos = new FileOutputStream(f);
fos.write(bitmapdata);
fos.flush();
fos.close();
Log.e(TAG, "imagepath: "+f );
}
catch (Exception e)
{
e.printStackTrace();
}
public class testCrop extends AppCompatActivity {
ImageView iv;
String imagePath = "https://style.pk/wp-content/uploads/2015/07/omer-Shahzad-performed-umrah-600x548.jpg";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.testcrpop);
iv = (ImageView) findViewById(R.id.testCrop);
imageDownload image = new imageDownload(testCrop.this, iv);
image.execute(imagePath);
}
class imageDownload extends AsyncTask<String, Integer, Bitmap> {
Context context;
ImageView imageView;
Bitmap bitmap;
InputStream in = null;
int responseCode = -1;
//constructor.
public imageDownload(Context context, ImageView imageView) {
this.context = context;
this.imageView = imageView;
}
@Override
protected void onPreExecute() {
}
@Override
protected Bitmap doInBackground(String... params) {
try {
URL url = new URL(params[0]);
HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection();
httpURLConnection.setDoOutput(true);
httpURLConnection.connect();
responseCode = httpURLConnection.getResponseCode();
if (responseCode == HttpURLConnection.HTTP_OK) {
in = httpURLConnection.getInputStream();
bitmap = BitmapFactory.decodeStream(in);
in.close();
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return bitmap;
}
@Override
protected void onPostExecute(Bitmap data) {
imageView.setImageBitmap(data);
saveImage(data);
}
private void saveImage(Bitmap data) {
File createFolder = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES),"test");
createFolder.mkdir();
File saveImage = new File(createFolder,"downloadimage.jpg");
try {
OutputStream outputStream = new FileOutputStream(saveImage);
data.compress(Bitmap.CompressFormat.JPEG,100,outputStream);
outputStream.flush();
outputStream.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
메모리에 데이터 쓰기 권한을 추가했는지 확인하십시오.
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
Google이 말했듯이 지금은 매니페스트의 외부 저장소에서도 읽을 수 있음을 추가하는 것을 잊지 마십시오.
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
출처 : http://developer.android.com/training/basics/data-storage/files.html#GetWritePermission
참고 URL : https://stackoverflow.com/questions/15549421/how-to-download-and-save-an-image-in-android
'IT story' 카테고리의 다른 글
Android Studio : Gradle을 사용하여 서명 된 APK를 생성하는 방법은 무엇입니까? (0) | 2020.09.13 |
---|---|
C ++에서 INI 파일을 구문 분석하는 가장 쉬운 방법은 무엇입니까? (0) | 2020.09.12 |
iOS7에서 투명한 UIToolbar 또는 UINavigationBar를 그리는 방법 (0) | 2020.09.12 |
ngStyle (angular2)을 사용하여 배경 이미지를 추가하는 방법은 무엇입니까? (0) | 2020.09.12 |
Sublime Text-왼쪽에 열린 파일 표시 (0) | 2020.09.12 |