Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> Android

วิธีดาวน์โหลดและบันทึกรูปภาพจาก URL ใน Android

ภาพรวม

ตัวอย่างนี้สาธิตวิธีดาวน์โหลดรูปภาพจาก URL แบบ Asynchronous ด้วย AsyncTask แสดง ProgressDialog และแสดงผลใน ImageView

ขั้นตอนที่ 1: สร้างโปรเจกต์ใหม่

สร้างโปรเจกต์ Android ใหม่ใน Android Studio

ขั้นตอนที่ 2: จัดทำ Layout (activity_main.xml)

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout
    xmlns:android="https://schemas.android.com/apk/res/android"
    xmlns:app="https://schemas.android.com/apk/res-auto"
    android:id="@+id/coordinatorLayout"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <Button
        android:id="@+id/btnDownload"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="ดาวน์โหลดรูปภาพ"
        android:layout_margin="25dp"
        android:layout_gravity="top|center_horizontal" />
    <ImageView
        android:id="@+id/imageView"
        android:layout_width="match_parent"
        android:layout_height="200dp"
        android:scaleType="centerCrop"
        app:layout_anchor="@id/btnDownload"
        android:layout_gravity="bottom"
        app:layout_anchorGravity="bottom"
        android:layout_margin="10dp" />
</android.support.design.widget.CoordinatorLayout>

ขั้นตอนที่ 3: MainActivity.java

import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.support.design.widget.CoordinatorLayout;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.Toast;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;

public class MainActivity extends AppCompatActivity {
    Context context;
    Activity activity;
    CoordinatorLayout coordinatorLayout;
    Button button;
    ProgressDialog mProgressDialog;
    ImageView mImageView;
    URL url;
    AsyncTask mMyTask;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        context = getApplicationContext();
        activity = MainActivity.this;
        coordinatorLayout = findViewById(R.id.coordinatorLayout);
        button = findViewById(R.id.btnDownload);
        mImageView = findViewById(R.id.imageView);
        
        mProgressDialog = new ProgressDialog(activity);
        mProgressDialog.setIndeterminate(true);
        mProgressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
        mProgressDialog.setTitle("กำลังดาวน์โหลด");
        mProgressDialog.setMessage("กรุณารอสักครู่ กำลังดาวน์โหลดรูปภาพ...");
        
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                mMyTask = new DownloadTask().execute(stringToURL());
            }
        });
    }

    private class DownloadTask extends AsyncTask<URL, Void, Bitmap> {
        @Override
        protected void onPreExecute() {
            mProgressDialog.show();
        }

        @Override
        protected Bitmap doInBackground(URL... urls) {
            URL url = urls[0];
            HttpURLConnection connection = null;
            try {
                connection = (HttpURLConnection) url.openConnection();
                connection.connect();
                InputStream inputStream = connection.getInputStream();
                BufferedInputStream bufferedInputStream = new BufferedInputStream(inputStream);
                return BitmapFactory.decodeStream(bufferedInputStream);
            } catch (IOException e) {
                e.printStackTrace();
            }
            return null;
        }

        @Override
        protected void onPostExecute(Bitmap result) {
            mProgressDialog.dismiss();
            if (result != null) {
                mImageView.setImageBitmap(result);
            } else {
                Toast.makeText(MainActivity.this, "ดาวน์โหลดล้มเหลว", Toast.LENGTH_SHORT).show();
            }
        }
    }

    protected URL stringToURL() {
        try {
            url = new URL("https://wallpapersite.com/images/pages/pic_w/6408.jpg");
            return url;
        } catch (MalformedURLException e) {
            e.printStackTrace();
        }
        return null;
    }
}

ขั้นตอนที่ 4: AndroidManifest.xml - สิทธิ์

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

⚠️ หมายเหตุสำคัญ: AsyncTask ถูก Deprecated (API 30+)

Google แนะนำให้ใช้วิธีทันสมัยแทน:

วิธีที่ 1: Coroutines + Coil/Glide/Picasso (แนะนำมากที่สุด)

// build.gradle
implementation "io.coil-kt:coil:2.4.0"

// ใช้งาน - 1 บรรทัด!
ImageView imageView = findViewById(R.id.imageView);
ImageLoader imageLoader = ImageLoader.Builder(this).build();
imageLoader.execute(ImageRequest.Builder(this)
    .data("https://example.com/image.jpg")
    .target(imageView)
    .build());

วิธีที่ 2: Coroutines + OkHttp (Manual)

// build.gradle
implementation "com.squareup.okhttp3:okhttp:4.11.0"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.3"

// ใช้งาน
lifecycleScope.launch(Dispatchers.IO) {
    try {
        Request request = new Request.Builder().url(url).build();
        Response response = client.newCall(request).execute();
        Bitmap bitmap = BitmapFactory.decodeStream(response.body().byteStream());
        withContext(Dispatchers.Main) {
            imageView.setImageBitmap(bitmap);
        }
    } catch (IOException e) { e.printStackTrace(); }
}

วิธีที่ 3: Java - ExecutorService (ไม่ใช้ Coroutines)

ExecutorService executor = Executors.newSingleThreadExecutor();
Handler handler = new Handler(Looper.getMainLooper());

executor.execute(() -> {
    try {
        URL url = new URL(imageUrl);
        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
        Bitmap bitmap = BitmapFactory.decodeStream(conn.getInputStream());
        handler.post(() -> imageView.setImageBitmap(bitmap));
    } catch (IOException e) { e.printStackTrace(); }
});

บันทึกลง External Storage (ถ้าต้องการ)

// ต้องขอสิทธิ์ WRITE_EXTERNAL_STORAGE และ requestLegacyExternalStorage="true" ใน Manifest (API 29+)
File file = new File(getExternalFilesDir(Environment.DIRECTORY_PICTURES), "downloaded.jpg");
FileOutputStream fos = new FileOutputStream(file);
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fos);
fos.flush(); fos.close();

// แจ้ง MediaScanner
MediaScannerConnection.scanFile(this, new String[]{file.getAbsolutePath()}, null, null);

การทดสอบ

รันแอป กดปุ่ม "ดาวน์โหลดรูปภาพ" จะแสดง ProgressDialog แล้วแสดงรูปใน ImageView