天天看點

如何擷取線上/網絡視訊的縮略圖 

這個視訊播放器播放不了視訊,有時播放黑屏問題是我在最近這個項目中遇到最頭疼的問題,因為不知道哪個環節出了問題,網上也找不出線索,最後我發現是因為我之前做頁面時在manifest裡面開啟了硬體加速,即加了一句android:hardwareAccelerated="true"導緻的,去掉之後視訊就能正常播放了

擷取視訊縮略圖我覺得應該是背景所做的事情,背景擷取之後傳給前端用就行了,但有時也需要我們自己去擷取,一般實際開發中會讓我們擷取多個,例如視訊清單的所有視訊縮略圖,我在做這個需求的時候發現,擷取的過程是一個耗時的操作,直接在主線程中操作會非常卡頓,并且會出現程式崩潰的問題,是以我想到這個過程在子線程中進行,擷取到圖檔bitmap傳回給UI線程,擷取一張加載一張,體驗問題也好了許多。下面是具體的實作過程:

這裡耗時任務在繼承IntentService服務子類中進行,和線上程裡操作原理一樣

一、建立MyIntentService,并建立UpdateUI接口,給頁面回調資料使用

二、在onHandleIntent中拿到圖檔URL中之後,通過MediaMetadataRetriever擷取bitmap,傳回給頁面

package ui.zlz.fragment;
import android.app.IntentService;
import android.content.Intent;
import android.graphics.Bitmap;
import android.media.MediaMetadataRetriever;
import android.os.Message;
import android.support.annotation.Nullable;
import java.util.HashMap;
/**
 * created by yezhengyu on 2019/1/21 09:26
 */

public class MyIntentService extends IntentService {

    public static UpdateUI updateUI;

    public static void setUpdateUI(UpdateUI updateUIInterface){
        updateUI=updateUIInterface;
    }

    /**
     * Creates an IntentService.  Invoked by your subclass's constructor.
     *
     */
    public MyIntentService() {
        super("MyIntentService");
    }

    @Override
    public void onCreate() {
        super.onCreate();
    }

    @Override
    public void onStart(@Nullable Intent intent, int startId) {
        super.onStart(intent, startId);
    }

    @Override
    public int onStartCommand(@Nullable Intent intent, int flags, int startId) {
        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
    }

    public interface UpdateUI{
        void updateUI(Message message);
    }

    @Override
    protected void onHandleIntent(@Nullable Intent intent) {
        String image = intent.getStringExtra("image");
        int index = intent.getIntExtra("index", 0);
        MediaMetadataRetriever retr = new MediaMetadataRetriever();
        retr.setDataSource(image, new HashMap<String, String>());
        Bitmap bitmap = retr.getFrameAtTime();
        Message msg1 = new Message();
        msg1.what = index;
        msg1.obj = bitmap;
        if(updateUI!=null) {
            updateUI.updateUI(msg1);
        }
    }
}

           

三、拿到圖檔資料後啟動MyIntentService,頁面需要實作UpdateUI接口

Intent intent = new Intent(getActivity(), MyIntentService.class);
for (int i = 0; i < data.size(); i++) {
    String image = Constants.BASE_URL + data.get(i).getImg_url().replaceAll("\\\\", "");
    intent.putExtra("image", image);
    intent.putExtra("index", i);
    getActivity().startService(intent);
}
MyIntentService.setUpdateUI(VideoFragment.this);
           

四、頁面拿到第二步的資料之後,重新整理清單

private final Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            int index = msg.what;
            Bitmap bitmap = (Bitmap) msg.obj;
            if (list.get(index) != null) {
                list.get(index).setBitmap(bitmap);
                adapter.notifyDataSetChanged();
            }
            if (index == 0) {
                hideLoading();
            }
        }
    };
    @Override
    public void updateUI(Message message) {
        mHandler.sendMessageDelayed(message, 50);
    }