android 多執行緒 切換視訊圖片使用心得
阿新 • • 發佈:2018-12-16
package com.tk.box.activity;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnCompletionListener;
import android.media.MediaPlayer.OnErrorListener;
import android.media.MediaPlayer.OnPreparedListener;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.Display;
import android.view.KeyEvent;
import android.widget.ImageView;
import android.widget.ImageView.ScaleType;
import android.widget.LinearLayout;
import android.widget.MediaController;
import android.widget.RelativeLayout;
import android.widget.Toast;
import android.widget.VideoView;
import com.tk.box.bo.task.AreaModel;
import com.tk.box.bo.task.MediaModel;
import com.tk.box.bo.task.TaskModel;
import com.tk.box.service.TaskService;
import com.tk.box.service.impl.TaskServiceImpl;
/**
* 總結下 多執行緒的使用心得; 1 像是這種 多個佈局 同時播放; 但是不同步 更新(每個佈局裡面的內容不一樣) 肯定是 每個佈局使用一個多執行緒進行管理;
* 因為每個佈局的播放時間不一樣;不同步; 所以每個 執行緒裡面肯定都各自有 是否改變介面的變數 以及 各自對應的 mediaList; 還有 對應的佈局 ;
* 所以構造器如下;
*
* public MyThread(Integer layoutId, List<MediaModel> mediaList, String
* palyIngType, String threadId) {
*
* 每個佈局對應一個執行緒; 把每個佈局裡面的media素材 裝到 list 裡面; 取出來第一個進行顯示; 每個佈局對應一個執行緒 ; 開始計時 ;
* 線上程裡面; 先 簡單的sleep 一下;(原來的時候我根據不同的素材型別進行不同的sleep; 比如 在播放 素材是視訊的時候; 我用變數
* videoIsEnd 以及palyIngType 進行控制; 後來發現 不理想; 我在主執行緒 根據子執行緒的id 改變 某個子執行緒的 palyIngType
* 變數的時候 發現 效果不理想;介面沒有及時更新; 仔細分析了下; 很可能是 在 執行sleep程式碼的時候(因為sleep
* 時間比較長;遠遠超過了程式碼執行的時間)) 比如原來的palyIngType 是image; 判斷完畢進入到if
* (!"video".equals(palyIngType)) { Thread.sleep(sleepTime);} 裡面的時候;此時正在sleep;
* 我在主執行緒裡面改變了次執行緒的palyIngType 為video; 這個時候我本來想 讓 介面不進行切換; 繼續 播放 視訊檔案;
* 也就是希望執行while ("video".equals(palyIngType) && !videoIsEnd) {//
* 沒有播放完成;Thread.sleep(sleepTime);} 這段程式碼; 實際上 卻沒有執行; 導致切換不理想;
*
* 解決方案: 就是線上程裡面簡單的sleep; 不進行邏輯的判斷; 如下; 控制是否切換的邏輯在核心的 控制是否發生訊息 來解決 ; 而不是在 控制睡多久來
* 控制業務邏輯; 大不了跑一圈什麼也不做;
*
*
*
*
* 原來不好的程式碼如下; long sleepTime=10000; if (!"video".equals(palyIngType)) {// 圖片
* Thread.sleep(sleepTime);
*
* } else { // 原來播放的是視訊;如果是視訊的話 一直等待; 上一個 播放的是視訊; 並且沒有播放完; 就一直等待;
*
* while ("video".equals(palyIngType) && !videoIsEnd) {// 沒有播放完成;
*
* Thread.sleep(sleepTime);
*
* }
*
*
*
*
*
*/
public class InquiryMainActivity extends Activity {
private TaskService taskService = null;
private boolean videoIsEnd = false;
private String TAG = "InquiryMainActivity";
private LinearLayout videoviewlayout = null;
private Uri mUri = null;
private VideoView vv = null;
private List<MyThread> threadList = new ArrayList<InquiryMainActivity.MyThread>();
// video view begin ;
private Handler handler = new UIHander();
private final class UIHander extends Handler {
private ImageView imageView = null;
private RelativeLayout layout = null;
public void handleMessage(Message msg) {
switch (msg.what) {
case 1:
case 2:
case 3:
String path = msg.getData().getString("path");
String threadId = msg.getData().getString("threadId");
Integer currentIndex = msg.getData().getInt("currentIndex");
Integer layoutId = msg.getData().getInt("layoutId");
layout = (RelativeLayout) InquiryMainActivity.this
.findViewById(layoutId);
layout.removeAllViews();
if (path.endsWith(".mp4")) {// 下個播放的 是mp4
initVideoView();
layout.addView(videoviewlayout,
new RelativeLayout.LayoutParams(
RelativeLayout.LayoutParams.FILL_PARENT,
RelativeLayout.LayoutParams.FILL_PARENT));
for (MyThread perThread : threadList) {
//
// Log.i(TAG, threadId + "threadId便利每個 執行緒的id-----"
// + perThread.getThreadId());
if (threadId.equals(perThread.getThreadId())) {
Log.i(TAG, threadId
+ "的獲取到threadId----- 進行 設定playType"
+ perThread.getThreadId());
perThread.setPalyIngType("video");
videoIsEnd = false;// 沒有結束; 否則不等待;
}
// perThread.getth threadId
}
// perAreaLayout.addView(videoviewlayout, 0,
// new RelativeLayout.LayoutParams(
// RelativeLayout.LayoutParams.FILL_PARENT,
// RelativeLayout.LayoutParams.FILL_PARENT));
// palyIngType = "video";
showMp4();
} else if (path.endsWith(".jpg")) {
imageView = new ImageView(InquiryMainActivity.this);
Bitmap bitmap = getLoacalBitmap(Environment
.getExternalStorageDirectory() + "/" + path); // 從本地取圖片(在cdcard中獲取)
imageView.setScaleType(ScaleType.FIT_XY);// 充滿;
imageView = new ImageView(InquiryMainActivity.this);
imageView.setImageBitmap(bitmap);
layout.addView(imageView, new RelativeLayout.LayoutParams(
RelativeLayout.LayoutParams.FILL_PARENT,
RelativeLayout.LayoutParams.FILL_PARENT));
for (MyThread perThread : threadList) {
if (threadId.equals(perThread.getThreadId())) {
// Log.i(TAG, threadId
// + "的獲取到threadId----- 進行 設定playType"
// + perThread.getThreadId());
perThread.setPalyIngType("image");
// videoIsEnd = true;//
}
// perThread.getth threadId
}
} else if (path.endsWith("")) {
}
break;
}
}
}
private void initVideoView() {
// mIntent = getIntent();
// if (mIntent != null) {
// 把播放地址取出來
// mUri =mIntent.getData();
// file:///mnt/sdcard/pptv/download/%E5%AE%AB%E9%94%81%E7%8F%A0%E5%B8%98(%E7%AC%AC06%E9%9B%86).mp4
// mUri
// =Uri.parse("file:///mnt/sdcard/pptv/download/%E5%AE%AB%E9%94%81%E7%8F%A0%E5%B8%98(%E7%AC%AC06%E9%9B%86).mp4");
// mUri = Uri.parse("file:///data/data/02.avi");
// mUri = Uri.parse("file:///data/data/01.mp4");
mUri = Uri.parse("file:///mnt/sdcard/video/01.mp4");
if (mUri != null) {
// 傳播放地址給播放器
vv.setVideoURI(mUri);
}
// }
// 當準備好了,會有回撥
vv.setOnPreparedListener(new OnPreparedListener() {
@Override
public void onPrepared(MediaPlayer mp) {
// TODO Auto-generated method stub
// 1,定位到上次播放的地方(seekTo());2,取消等待畫面
// 當準備好了,開始播放
if (vv != null)
vv.start();
}
});
// 當播放出錯了,也會有一個回撥
vv.setOnErrorListener(new OnErrorListener() {
@Override
public boolean onError(MediaPlayer mp, int what, int extra) {
// 進行錯誤處理:1,提示使用者;2,重試,3,進入第三方播放器繼續播放;
Toast.makeText(InquiryMainActivity.this, "播放出錯了", 1).show();
return true;
}
});
// 監聽播放完成
vv.setOnCompletionListener(new OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mp) {
// 播放完成:1,退出播放器、提示使用者是否進入你的軟體;2,播放下一個視訊
Toast.makeText(InquiryMainActivity.this, "播放完了", 1).show();
videoIsEnd = true;
}
});
// 顯示系統空間
MediaController me = new MediaController(InquiryMainActivity.this);
me.setPadding(200, 0, 0, 0);
vv.setMediaController(me);
}
private void showMp4() {
initVideoView();
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
videoviewlayout = (LinearLayout) getLayoutInflater().inflate(
R.layout.videoview, null); // 通過這種方式初始化佈局檔案;
vv = (VideoView) videoviewlayout.findViewById(R.id.vv);
taskService = new TaskServiceImpl(this);
// 訪問sd 卡 ;需要加上 路徑;
String path = Environment.getExternalStorageDirectory() + "/task.xml";
TaskModel task = taskService.readTaskFromTaskXMl(path);
if (task == null) {
Toast.makeText(this, "讀取xml檔案失敗", 1).show();
} else {
String taskname = task.getName();
String startDate = task.getStartDate();
String endDate = task.getEndDate();
Integer weeks = task.getWeek();
}
Display mDisplay = getWindowManager().getDefaultDisplay();
int w = mDisplay.getWidth();
int h = mDisplay.getHeight();
// 1920 1080 1280 752 ;
double widthScalPercent = 1920.0 / w;
double heightScalePercent = 1080.0 / h;
RelativeLayout global = (RelativeLayout) getLayoutInflater().inflate(
R.layout.inquiry_main, null);
// TextView mTextView = new TextView(this);
//
// mTextView.setText("測試--------------------------");
ImageView view = new ImageView(this);
view.setBackgroundColor(Color.RED);
// android.widget.RelativeLayout.LayoutParams lineimageViewlayoutParams
// = new RelativeLayout.LayoutParams(
// 100, 100);// 也就是設定imgaeview 的寬高; 也就是設定要新增的控制元件的寬高;
// lineimageViewlayoutParams.topMargin = 100.0;// 設定上邊距;
// global.addView(view, lineimageViewlayoutParams);
// global.addView(view, 200, 200);// 也可以通過這種設定寬高; 放前面或者後面都可以;
setContentView(global);
// global.addView(view, lineimageViewlayoutParams);
List<AreaModel> areaList = task.getProgram().getAreaList();
Integer index = 0;
List<Integer> areIndex = new ArrayList<Integer>();
areIndex.add(Color.RED);
areIndex.add(Color.BLUE);
areIndex.add(Color.GRAY);
areIndex.add(Color.YELLOW);
List<Map<Integer, List<MediaModel>>> mapModelList = new ArrayList<Map<Integer, List<MediaModel>>>();
boolean isFirst = true;
for (AreaModel area : areaList) {
Map<Integer, List<MediaModel>> map = new HashMap<Integer, List<MediaModel>>();
List<MediaModel> mediaList = area.getMediaModelList();
Double height = area.getHeight();
Double width = area.getWidth();
Double startX = area.getStartX();
Double startY = area.getStartY();
Integer newHeight = (int) (height / heightScalePercent);
Integer newWidth = (int) (width / widthScalPercent);
Integer newstartX = (int) (startX / widthScalPercent);
Integer newstartY = (int) (startY / heightScalePercent);
RelativeLayout perAreaLayout = new RelativeLayout(this);
perAreaLayout.setBackgroundColor(areIndex.get(index));
Integer layoutId = 1000 + index;
perAreaLayout.setId(layoutId);
map.put(layoutId, mediaList);
mapModelList.add(map);
android.widget.RelativeLayout.LayoutParams arealayoutParams = new RelativeLayout.LayoutParams(
newWidth, newHeight);
arealayoutParams.topMargin = newstartY;// 設定上邊距;
arealayoutParams.leftMargin = newstartX;
String palyIngType = "";// image 圖片 2 video; 正在播放的型別;
if (mediaList != null && mediaList.size() > 0
&& mediaList.get(0).getName().endsWith(".jpg")) {
// 設定預設的顯示;
ImageView imageView = new ImageView(this);
// step1 讓 圖片充滿控制元件; 不僅僅要設定模式為scaleType
imageView.setScaleType(ScaleType.FIT_XY);//
imageView.setBackgroundResource(R.drawable.icon);
// 有些事情必須在 addView 之前做; 否則不顯示;
// step2讓 圖片充滿控制元件; // 還需要設定圖片寬高都是填充父元素; 如下
perAreaLayout.addView(imageView, 0,
new RelativeLayout.LayoutParams(
RelativeLayout.LayoutParams.FILL_PARENT,
RelativeLayout.LayoutParams.FILL_PARENT));
palyIngType = "image";
} else if (mediaList != null && mediaList.size() > 0
&& mediaList.get(0).getName().endsWith(".mp4")) {
perAreaLayout.addView(videoviewlayout, 0,
new RelativeLayout.LayoutParams(
RelativeLayout.LayoutParams.FILL_PARENT,
RelativeLayout.LayoutParams.FILL_PARENT));
// isPlayingVideo = true;
showMp4();
palyIngType = "video";
videoIsEnd = false;
}
global.addView(perAreaLayout, arealayoutParams);
// Thread.sleep(time)
MyThread thread = new MyThread(layoutId, mediaList, palyIngType,
(UUID.randomUUID().toString()));
threadList.add(thread);
thread.start();
index++;
}
}
private boolean flag = true;
private class MyThread extends Thread {
private String threadId = null;
private Integer layoutId = null;
private String palyIngType = "";// 上一個是否是播放的型別;
public String getThreadId() {
return threadId;
}
public void setPalyIngType(String palyIngType) {
this.palyIngType = palyIngType;
}
List<MediaModel> mediaList = null;
private Integer currentIndex = null;
private RelativeLayout layout = null;
private String threadName = "";
public MyThread(Integer layoutId, List<MediaModel> mediaList,
String palyIngType, String threadId) {
this.layoutId = layoutId;
threadName = "ThreadName-" + layoutId;
this.threadId = threadId;
this.mediaList = mediaList;
layout = (RelativeLayout) InquiryMainActivity.this
.findViewById(layoutId);
this.palyIngType = palyIngType;
if (mediaList != null && mediaList.size() > 0) {
currentIndex = 0;
}
// Log.i(TAG, "建立的是" + threadName + " palyIngType:" + palyIngType);
}
@Override
public void run() {
// super.run();
// 訪問sd 卡 ;需要加上 路徑;
try {
while (flag) {
try {
long sleepTime = 10000;
// 有可能判斷完成了; 原來是已經判斷完是image; 在這裡睡呢;沉睡的時候改變成為video;
// 導致不能等待;
Thread.sleep(sleepTime);
/**
* 自己感覺儘量不要在 if 語句裡面判斷是否進行 sleep ; 因為有可能 判斷 完成之後 在sleep的
* 時候 進行狀態的改變; 導致 判斷出現不準確的情況; 我是在最後發生給主執行緒的訊息的時候進行狀態的判斷;
* 如果播放完畢; 就 傳送訊息 ; 如果沒有播放完成的話; 就 繼續播放; 繼續while 迴圈 ;
*
*
*/
// if (!"video".equals(palyIngType)) {// 圖片的話一秒跳一次;
// if (threadName.indexOf("002") >= 0)
// Log.i(TAG, threadName
// + "切換圖片三秒------palyIngType:"
// + palyIngType + "threadId:" + threadId);
// Thread.sleep(sleepTime);
//
// } else { // 原來播放的是視訊;
// // 如果是視訊的話 一直等待; 上一個 播放的是視訊; 並且沒有播放完; 就一直等待;
// if (threadName.indexOf("002") >= 0)
// Log.i(TAG, threadName + "----palyIngType:-----"
// + palyIngType + "threadId:" + threadId);
// while ("video".equals(palyIngType) && !videoIsEnd)
// {// 沒有播放完成;
// if (threadName.indexOf("002") >= 0)
// Log.i(TAG, threadName
// + "播放的是視訊---等待三秒------palyIngType:"
// + palyIngType + "threadId:"
// + threadId);
// Thread.sleep(sleepTime);
//
// }
//
// }
} catch (Exception e) {
e.printStackTrace();
}
currentIndex += 1;
if (currentIndex >= mediaList.size()) {
currentIndex = 0;
}
// 下一個要播放的媒體;
MediaModel toBePlayedMedia = mediaList.get(currentIndex);
String path = toBePlayedMedia.getName();
if (threadName.indexOf("002") >= 0)
Log.i(TAG, " 傳送訊息前 ---------------------path:" + path
+ "playType:" + palyIngType + "videoIsEnd"
+ videoIsEnd);
// if (path.endsWith(".jpg") &&
// !"video".equals(palyIngType)) {// 如果上次播放的不是
// 視訊;
// 並且下次播放的也是圖片
if (path.endsWith(".jpg") && "image".equals(palyIngType)) {// 如果上次播放的不是
Message msg = new Message();
msg.what = 1;
msg.getData().putString("path", path);
msg.getData().putInt("currentIndex", currentIndex);
msg.getData().putInt("layoutId", layoutId);
msg.getData().putString("threadId", threadId);
handler.sendMessage(msg);
if (threadName.indexOf("002") >= 0)
Log.i(TAG,
" 傳送訊息---------------------------------1-----palyIngTypeold:"
+ palyIngType + "被改為image;");
// palyIngType = "image";// 正在播放的是圖片; 在handler 進行控制就好了;
} else if ("video".equals(palyIngType)
&& path.endsWith(".jpg")) {
// 如果上次播放的是 視訊; 並且下次播放的也是圖片
if (threadName.indexOf("002") >= 0)
Log.i(TAG,
" 傳送訊息---------------------------------2-----palyIngTypeold:---"
+ palyIngType + "依舊;");
// if (videoIsEnd) {// 因為 前面的話 有可能判斷成為 image 之後
// Log.i(TAG, threadName + "視訊--------->圖片 傳送訊息;");
if (videoIsEnd) { // 控制是否切換介面
Message msg = new Message();
msg.what = 2;
msg.getData().putString("path", path);
msg.getData().putString("palyIngType", palyIngType);// 把之前的播放型別發過去;
msg.getData().putInt("currentIndex", currentIndex);
msg.getData().putInt("layoutId", layoutId);
msg.getData().putString("threadId", threadId);
handler.sendMessage(msg);
}
// }
// isPlayingVideo = false;// 傳送訊息並且這次播放的不是視訊;
// palyIngType = "image";//
} else if ("image".equals(palyIngType)
&& path.endsWith(".mp4")) {// 圖片轉視訊ok;
if (threadName.indexOf("002") >= 0)
Log.i(TAG,
" 傳送訊息---------------------------------3-----palyIngTypeold:"
+ palyIngType + "依舊;");
// if (!videoIsEnd) {//
// 正在播放的是 圖片; 下次播放視訊;
Message msg = new Message();
msg.what = 3;
msg.getData().putString("path", path);
msg.getData().putString("palyIngType", palyIngType);// 把之前的播放型別發過去;
msg.getData().putInt("currentIndex", currentIndex);
msg.getData().putInt("layoutId", layoutId);
msg.getData().putString("threadId", threadId);
handler.sendMessage(msg);
// }
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
/**
* // 測試; 具體還沒有細化; 還沒有細化 控制執行緒變數 什麼的 ;
*/
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) { // 監控/攔截/遮蔽返回鍵
// do something
// 返回鍵; 執行了;可以再這裡進行監聽;
Log.i(TAG, "back------被執行了; 執行緒要關閉了 ----");
flag = false;
// 如果返回false 那麼阻止事件繼續執行;
// return false;
} else if (keyCode == KeyEvent.KEYCODE_MENU) {
// 點選未執行;
Log.i(TAG, "MENU------被執行了; 執行緒要關閉了 ----");
flag = false;
// do something
} else if (keyCode == KeyEvent.KEYCODE_HOME) {
// 點選未執行;
Log.i(TAG, "KEYCODE_HOME------被執行了; 執行緒要關閉了 ----");
// 這裡操作是沒有返回結果的
}
return super.onKeyDown(keyCode, event);
}
/**
* 載入本地圖片
*
* @param url
* @return
*/
public static Bitmap getLoacalBitmap(String url) {
try {
FileInputStream fis = new FileInputStream(url);
return BitmapFactory.decodeStream(fis); // /把流轉化為Bitmap圖片
} catch (FileNotFoundException e) {
e.printStackTrace();
return null;
}
}
}
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnCompletionListener;
import android.media.MediaPlayer.OnErrorListener;
import android.media.MediaPlayer.OnPreparedListener;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.Display;
import android.view.KeyEvent;
import android.widget.ImageView;
import android.widget.ImageView.ScaleType;
import android.widget.LinearLayout;
import android.widget.MediaController;
import android.widget.RelativeLayout;
import android.widget.Toast;
import android.widget.VideoView;
import com.tk.box.bo.task.AreaModel;
import com.tk.box.bo.task.MediaModel;
import com.tk.box.bo.task.TaskModel;
import com.tk.box.service.TaskService;
import com.tk.box.service.impl.TaskServiceImpl;
/**
* 總結下 多執行緒的使用心得; 1 像是這種 多個佈局 同時播放; 但是不同步 更新(每個佈局裡面的內容不一樣) 肯定是 每個佈局使用一個多執行緒進行管理;
* 因為每個佈局的播放時間不一樣;不同步; 所以每個 執行緒裡面肯定都各自有 是否改變介面的變數 以及 各自對應的 mediaList; 還有 對應的佈局 ;
* 所以構造器如下;
*
* public MyThread(Integer layoutId, List<MediaModel> mediaList, String
* palyIngType, String threadId) {
*
* 每個佈局對應一個執行緒; 把每個佈局裡面的media素材 裝到 list 裡面; 取出來第一個進行顯示; 每個佈局對應一個執行緒 ; 開始計時 ;
* 線上程裡面; 先 簡單的sleep 一下;(原來的時候我根據不同的素材型別進行不同的sleep; 比如 在播放 素材是視訊的時候; 我用變數
* videoIsEnd 以及palyIngType 進行控制; 後來發現 不理想; 我在主執行緒 根據子執行緒的id 改變 某個子執行緒的 palyIngType
* 變數的時候 發現 效果不理想;介面沒有及時更新; 仔細分析了下; 很可能是 在 執行sleep程式碼的時候(因為sleep
* 時間比較長;遠遠超過了程式碼執行的時間)) 比如原來的palyIngType 是image; 判斷完畢進入到if
* (!"video".equals(palyIngType)) { Thread.sleep(sleepTime);} 裡面的時候;此時正在sleep;
* 我在主執行緒裡面改變了次執行緒的palyIngType 為video; 這個時候我本來想 讓 介面不進行切換; 繼續 播放 視訊檔案;
* 也就是希望執行while ("video".equals(palyIngType) && !videoIsEnd) {//
* 沒有播放完成;Thread.sleep(sleepTime);} 這段程式碼; 實際上 卻沒有執行; 導致切換不理想;
*
* 解決方案: 就是線上程裡面簡單的sleep; 不進行邏輯的判斷; 如下; 控制是否切換的邏輯在核心的 控制是否發生訊息 來解決 ; 而不是在 控制睡多久來
* 控制業務邏輯; 大不了跑一圈什麼也不做;
*
*
*
*
* 原來不好的程式碼如下; long sleepTime=10000; if (!"video".equals(palyIngType)) {// 圖片
* Thread.sleep(sleepTime);
*
* } else { // 原來播放的是視訊;如果是視訊的話 一直等待; 上一個 播放的是視訊; 並且沒有播放完; 就一直等待;
*
* while ("video".equals(palyIngType) && !videoIsEnd) {// 沒有播放完成;
*
* Thread.sleep(sleepTime);
*
* }
*
*
*
*
*
*/
public class InquiryMainActivity extends Activity {
private TaskService taskService = null;
private boolean videoIsEnd = false;
private String TAG = "InquiryMainActivity";
private LinearLayout videoviewlayout = null;
private Uri mUri = null;
private VideoView vv = null;
private List<MyThread> threadList = new ArrayList<InquiryMainActivity.MyThread>();
// video view begin ;
private Handler handler = new UIHander();
private final class UIHander extends Handler {
private ImageView imageView = null;
private RelativeLayout layout = null;
public void handleMessage(Message msg) {
switch (msg.what) {
case 1:
case 2:
case 3:
String path = msg.getData().getString("path");
String threadId = msg.getData().getString("threadId");
Integer currentIndex = msg.getData().getInt("currentIndex");
Integer layoutId = msg.getData().getInt("layoutId");
layout = (RelativeLayout) InquiryMainActivity.this
.findViewById(layoutId);
layout.removeAllViews();
if (path.endsWith(".mp4")) {// 下個播放的 是mp4
initVideoView();
layout.addView(videoviewlayout,
new RelativeLayout.LayoutParams(
RelativeLayout.LayoutParams.FILL_PARENT,
RelativeLayout.LayoutParams.FILL_PARENT));
for (MyThread perThread : threadList) {
//
// Log.i(TAG, threadId + "threadId便利每個 執行緒的id-----"
// + perThread.getThreadId());
if (threadId.equals(perThread.getThreadId())) {
Log.i(TAG, threadId
+ "的獲取到threadId----- 進行 設定playType"
+ perThread.getThreadId());
perThread.setPalyIngType("video");
videoIsEnd = false;// 沒有結束; 否則不等待;
}
// perThread.getth threadId
}
// perAreaLayout.addView(videoviewlayout, 0,
// new RelativeLayout.LayoutParams(
// RelativeLayout.LayoutParams.FILL_PARENT,
// RelativeLayout.LayoutParams.FILL_PARENT));
// palyIngType = "video";
showMp4();
} else if (path.endsWith(".jpg")) {
imageView = new ImageView(InquiryMainActivity.this);
Bitmap bitmap = getLoacalBitmap(Environment
.getExternalStorageDirectory() + "/" + path); // 從本地取圖片(在cdcard中獲取)
imageView.setScaleType(ScaleType.FIT_XY);// 充滿;
imageView = new ImageView(InquiryMainActivity.this);
imageView.setImageBitmap(bitmap);
layout.addView(imageView, new RelativeLayout.LayoutParams(
RelativeLayout.LayoutParams.FILL_PARENT,
RelativeLayout.LayoutParams.FILL_PARENT));
for (MyThread perThread : threadList) {
if (threadId.equals(perThread.getThreadId())) {
// Log.i(TAG, threadId
// + "的獲取到threadId----- 進行 設定playType"
// + perThread.getThreadId());
perThread.setPalyIngType("image");
// videoIsEnd = true;//
}
// perThread.getth threadId
}
} else if (path.endsWith("")) {
}
break;
}
}
}
private void initVideoView() {
// mIntent = getIntent();
// if (mIntent != null) {
// 把播放地址取出來
// mUri =mIntent.getData();
// file:///mnt/sdcard/pptv/download/%E5%AE%AB%E9%94%81%E7%8F%A0%E5%B8%98(%E7%AC%AC06%E9%9B%86).mp4
// mUri
// =Uri.parse("file:///mnt/sdcard/pptv/download/%E5%AE%AB%E9%94%81%E7%8F%A0%E5%B8%98(%E7%AC%AC06%E9%9B%86).mp4");
// mUri = Uri.parse("file:///data/data/02.avi");
// mUri = Uri.parse("file:///data/data/01.mp4");
mUri = Uri.parse("file:///mnt/sdcard/video/01.mp4");
if (mUri != null) {
// 傳播放地址給播放器
vv.setVideoURI(mUri);
}
// }
// 當準備好了,會有回撥
vv.setOnPreparedListener(new OnPreparedListener() {
@Override
public void onPrepared(MediaPlayer mp) {
// TODO Auto-generated method stub
// 1,定位到上次播放的地方(seekTo());2,取消等待畫面
// 當準備好了,開始播放
if (vv != null)
vv.start();
}
});
// 當播放出錯了,也會有一個回撥
vv.setOnErrorListener(new OnErrorListener() {
@Override
public boolean onError(MediaPlayer mp, int what, int extra) {
// 進行錯誤處理:1,提示使用者;2,重試,3,進入第三方播放器繼續播放;
Toast.makeText(InquiryMainActivity.this, "播放出錯了", 1).show();
return true;
}
});
// 監聽播放完成
vv.setOnCompletionListener(new OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mp) {
// 播放完成:1,退出播放器、提示使用者是否進入你的軟體;2,播放下一個視訊
Toast.makeText(InquiryMainActivity.this, "播放完了", 1).show();
videoIsEnd = true;
}
});
// 顯示系統空間
MediaController me = new MediaController(InquiryMainActivity.this);
me.setPadding(200, 0, 0, 0);
vv.setMediaController(me);
}
private void showMp4() {
initVideoView();
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
videoviewlayout = (LinearLayout) getLayoutInflater().inflate(
R.layout.videoview, null); // 通過這種方式初始化佈局檔案;
vv = (VideoView) videoviewlayout.findViewById(R.id.vv);
taskService = new TaskServiceImpl(this);
// 訪問sd 卡 ;需要加上 路徑;
String path = Environment.getExternalStorageDirectory() + "/task.xml";
TaskModel task = taskService.readTaskFromTaskXMl(path);
if (task == null) {
Toast.makeText(this, "讀取xml檔案失敗", 1).show();
} else {
String taskname = task.getName();
String startDate = task.getStartDate();
String endDate = task.getEndDate();
Integer weeks = task.getWeek();
}
Display mDisplay = getWindowManager().getDefaultDisplay();
int w = mDisplay.getWidth();
int h = mDisplay.getHeight();
// 1920 1080 1280 752 ;
double widthScalPercent = 1920.0 / w;
double heightScalePercent = 1080.0 / h;
RelativeLayout global = (RelativeLayout) getLayoutInflater().inflate(
R.layout.inquiry_main, null);
// TextView mTextView = new TextView(this);
//
// mTextView.setText("測試--------------------------");
ImageView view = new ImageView(this);
view.setBackgroundColor(Color.RED);
// android.widget.RelativeLayout.LayoutParams lineimageViewlayoutParams
// = new RelativeLayout.LayoutParams(
// 100, 100);// 也就是設定imgaeview 的寬高; 也就是設定要新增的控制元件的寬高;
// lineimageViewlayoutParams.topMargin = 100.0;// 設定上邊距;
// global.addView(view, lineimageViewlayoutParams);
// global.addView(view, 200, 200);// 也可以通過這種設定寬高; 放前面或者後面都可以;
setContentView(global);
// global.addView(view, lineimageViewlayoutParams);
List<AreaModel> areaList = task.getProgram().getAreaList();
Integer index = 0;
List<Integer> areIndex = new ArrayList<Integer>();
areIndex.add(Color.RED);
areIndex.add(Color.BLUE);
areIndex.add(Color.GRAY);
areIndex.add(Color.YELLOW);
List<Map<Integer, List<MediaModel>>> mapModelList = new ArrayList<Map<Integer, List<MediaModel>>>();
boolean isFirst = true;
for (AreaModel area : areaList) {
Map<Integer, List<MediaModel>> map = new HashMap<Integer, List<MediaModel>>();
List<MediaModel> mediaList = area.getMediaModelList();
Double height = area.getHeight();
Double width = area.getWidth();
Double startX = area.getStartX();
Double startY = area.getStartY();
Integer newHeight = (int) (height / heightScalePercent);
Integer newWidth = (int) (width / widthScalPercent);
Integer newstartX = (int) (startX / widthScalPercent);
Integer newstartY = (int) (startY / heightScalePercent);
RelativeLayout perAreaLayout = new RelativeLayout(this);
perAreaLayout.setBackgroundColor(areIndex.get(index));
Integer layoutId = 1000 + index;
perAreaLayout.setId(layoutId);
map.put(layoutId, mediaList);
mapModelList.add(map);
android.widget.RelativeLayout.LayoutParams arealayoutParams = new RelativeLayout.LayoutParams(
newWidth, newHeight);
arealayoutParams.topMargin = newstartY;// 設定上邊距;
arealayoutParams.leftMargin = newstartX;
String palyIngType = "";// image 圖片 2 video; 正在播放的型別;
if (mediaList != null && mediaList.size() > 0
&& mediaList.get(0).getName().endsWith(".jpg")) {
// 設定預設的顯示;
ImageView imageView = new ImageView(this);
// step1 讓 圖片充滿控制元件; 不僅僅要設定模式為scaleType
imageView.setScaleType(ScaleType.FIT_XY);//
imageView.setBackgroundResource(R.drawable.icon);
// 有些事情必須在 addView 之前做; 否則不顯示;
// step2讓 圖片充滿控制元件; // 還需要設定圖片寬高都是填充父元素; 如下
perAreaLayout.addView(imageView, 0,
new RelativeLayout.LayoutParams(
RelativeLayout.LayoutParams.FILL_PARENT,
RelativeLayout.LayoutParams.FILL_PARENT));
palyIngType = "image";
} else if (mediaList != null && mediaList.size() > 0
&& mediaList.get(0).getName().endsWith(".mp4")) {
perAreaLayout.addView(videoviewlayout, 0,
new RelativeLayout.LayoutParams(
RelativeLayout.LayoutParams.FILL_PARENT,
RelativeLayout.LayoutParams.FILL_PARENT));
// isPlayingVideo = true;
showMp4();
palyIngType = "video";
videoIsEnd = false;
}
global.addView(perAreaLayout, arealayoutParams);
// Thread.sleep(time)
MyThread thread = new MyThread(layoutId, mediaList, palyIngType,
(UUID.randomUUID().toString()));
threadList.add(thread);
thread.start();
index++;
}
}
private boolean flag = true;
private class MyThread extends Thread {
private String threadId = null;
private Integer layoutId = null;
private String palyIngType = "";// 上一個是否是播放的型別;
public String getThreadId() {
return threadId;
}
public void setPalyIngType(String palyIngType) {
this.palyIngType = palyIngType;
}
List<MediaModel> mediaList = null;
private Integer currentIndex = null;
private RelativeLayout layout = null;
private String threadName = "";
public MyThread(Integer layoutId, List<MediaModel> mediaList,
String palyIngType, String threadId) {
this.layoutId = layoutId;
threadName = "ThreadName-" + layoutId;
this.threadId = threadId;
this.mediaList = mediaList;
layout = (RelativeLayout) InquiryMainActivity.this
.findViewById(layoutId);
this.palyIngType = palyIngType;
if (mediaList != null && mediaList.size() > 0) {
currentIndex = 0;
}
// Log.i(TAG, "建立的是" + threadName + " palyIngType:" + palyIngType);
}
@Override
public void run() {
// super.run();
// 訪問sd 卡 ;需要加上 路徑;
try {
while (flag) {
try {
long sleepTime = 10000;
// 有可能判斷完成了; 原來是已經判斷完是image; 在這裡睡呢;沉睡的時候改變成為video;
// 導致不能等待;
Thread.sleep(sleepTime);
/**
* 自己感覺儘量不要在 if 語句裡面判斷是否進行 sleep ; 因為有可能 判斷 完成之後 在sleep的
* 時候 進行狀態的改變; 導致 判斷出現不準確的情況; 我是在最後發生給主執行緒的訊息的時候進行狀態的判斷;
* 如果播放完畢; 就 傳送訊息 ; 如果沒有播放完成的話; 就 繼續播放; 繼續while 迴圈 ;
*
*
*/
// if (!"video".equals(palyIngType)) {// 圖片的話一秒跳一次;
// if (threadName.indexOf("002") >= 0)
// Log.i(TAG, threadName
// + "切換圖片三秒------palyIngType:"
// + palyIngType + "threadId:" + threadId);
// Thread.sleep(sleepTime);
//
// } else { // 原來播放的是視訊;
// // 如果是視訊的話 一直等待; 上一個 播放的是視訊; 並且沒有播放完; 就一直等待;
// if (threadName.indexOf("002") >= 0)
// Log.i(TAG, threadName + "----palyIngType:-----"
// + palyIngType + "threadId:" + threadId);
// while ("video".equals(palyIngType) && !videoIsEnd)
// {// 沒有播放完成;
// if (threadName.indexOf("002") >= 0)
// Log.i(TAG, threadName
// + "播放的是視訊---等待三秒------palyIngType:"
// + palyIngType + "threadId:"
// + threadId);
// Thread.sleep(sleepTime);
//
// }
//
// }
} catch (Exception e) {
e.printStackTrace();
}
currentIndex += 1;
if (currentIndex >= mediaList.size()) {
currentIndex = 0;
}
// 下一個要播放的媒體;
MediaModel toBePlayedMedia = mediaList.get(currentIndex);
String path = toBePlayedMedia.getName();
if (threadName.indexOf("002") >= 0)
Log.i(TAG, " 傳送訊息前 ---------------------path:" + path
+ "playType:" + palyIngType + "videoIsEnd"
+ videoIsEnd);
// if (path.endsWith(".jpg") &&
// !"video".equals(palyIngType)) {// 如果上次播放的不是
// 視訊;
// 並且下次播放的也是圖片
if (path.endsWith(".jpg") && "image".equals(palyIngType)) {// 如果上次播放的不是
Message msg = new Message();
msg.what = 1;
msg.getData().putString("path", path);
msg.getData().putInt("currentIndex", currentIndex);
msg.getData().putInt("layoutId", layoutId);
msg.getData().putString("threadId", threadId);
handler.sendMessage(msg);
if (threadName.indexOf("002") >= 0)
Log.i(TAG,
" 傳送訊息---------------------------------1-----palyIngTypeold:"
+ palyIngType + "被改為image;");
// palyIngType = "image";// 正在播放的是圖片; 在handler 進行控制就好了;
} else if ("video".equals(palyIngType)
&& path.endsWith(".jpg")) {
// 如果上次播放的是 視訊; 並且下次播放的也是圖片
if (threadName.indexOf("002") >= 0)
Log.i(TAG,
" 傳送訊息---------------------------------2-----palyIngTypeold:---"
+ palyIngType + "依舊;");
// if (videoIsEnd) {// 因為 前面的話 有可能判斷成為 image 之後
// Log.i(TAG, threadName + "視訊--------->圖片 傳送訊息;");
if (videoIsEnd) { // 控制是否切換介面
Message msg = new Message();
msg.what = 2;
msg.getData().putString("path", path);
msg.getData().putString("palyIngType", palyIngType);// 把之前的播放型別發過去;
msg.getData().putInt("currentIndex", currentIndex);
msg.getData().putInt("layoutId", layoutId);
msg.getData().putString("threadId", threadId);
handler.sendMessage(msg);
}
// }
// isPlayingVideo = false;// 傳送訊息並且這次播放的不是視訊;
// palyIngType = "image";//
} else if ("image".equals(palyIngType)
&& path.endsWith(".mp4")) {// 圖片轉視訊ok;
if (threadName.indexOf("002") >= 0)
Log.i(TAG,
" 傳送訊息---------------------------------3-----palyIngTypeold:"
+ palyIngType + "依舊;");
// if (!videoIsEnd) {//
// 正在播放的是 圖片; 下次播放視訊;
Message msg = new Message();
msg.what = 3;
msg.getData().putString("path", path);
msg.getData().putString("palyIngType", palyIngType);// 把之前的播放型別發過去;
msg.getData().putInt("currentIndex", currentIndex);
msg.getData().putInt("layoutId", layoutId);
msg.getData().putString("threadId", threadId);
handler.sendMessage(msg);
// }
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
/**
* // 測試; 具體還沒有細化; 還沒有細化 控制執行緒變數 什麼的 ;
*/
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) { // 監控/攔截/遮蔽返回鍵
// do something
// 返回鍵; 執行了;可以再這裡進行監聽;
Log.i(TAG, "back------被執行了; 執行緒要關閉了 ----");
flag = false;
// 如果返回false 那麼阻止事件繼續執行;
// return false;
} else if (keyCode == KeyEvent.KEYCODE_MENU) {
// 點選未執行;
Log.i(TAG, "MENU------被執行了; 執行緒要關閉了 ----");
flag = false;
// do something
} else if (keyCode == KeyEvent.KEYCODE_HOME) {
// 點選未執行;
Log.i(TAG, "KEYCODE_HOME------被執行了; 執行緒要關閉了 ----");
// 這裡操作是沒有返回結果的
}
return super.onKeyDown(keyCode, event);
}
/**
* 載入本地圖片
*
* @param url
* @return
*/
public static Bitmap getLoacalBitmap(String url) {
try {
FileInputStream fis = new FileInputStream(url);
return BitmapFactory.decodeStream(fis); // /把流轉化為Bitmap圖片
} catch (FileNotFoundException e) {
e.printStackTrace();
return null;
}
}
}