Computer >> Hướng Dẫn Máy Tính >  >> Lập Trình >> Android

Cách tải và lưu ảnh từ URL trong Android

Giới thiệu

Ví dụ này minh họa cách tải ảnh từ URL trong background thread (AsyncTask) và hiển thị lên ImageView, kèm ProgressDialog.

Các bước thực hiện

Bước 1: Tạo dự án mới

Mở Android Studio, chọn File → New Project và điền thông tin cần thiết.

Bước 2: Layout với CoordinatorLayout (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="Tải ảnh"
        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>

Bước 3: MainActivity.java - AsyncTask tải ảnh

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("Đang tải");
        mProgressDialog.setMessage("Vui lòng chờ, đang tải ảnh...");
        
        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, "Lỗi tải ảnh", 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;
    }
}

Bước 4: Manifest với quyền (AndroidManifest.xml)

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="https://schemas.android.com/apk/res/android" package="app.com.sample">
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
    <uses-permission android:name="android.permission.INTERNET"/>
    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
</manifest>

Chạy ứng dụng

Kết nối thiết bị, nhấn Run. Nhấn nút "Tải ảnh" để xem ProgressDialog và ảnh hiển thị.

Cách tải và lưu ảnh từ URL trong Android

Cách tải và lưu ảnh từ URL trong Android

Cách hiện đại tốt hơn:
  • Dùng thư viện Glide, Picasso, Coil (Kotlin coroutines) - tự handle cache, lifecycle, placeholder, error
  • AsyncTask đã deprecated từ API 30. Dùng ExecutorService, Coroutines, RxJava hoặc WorkManager
  • ProgressDialog cũng deprecated, dùng ProgressBar trong layout
Ví dụ Glide: Glide.with(this).load(url).into(imageView);