android 多線程 切換視頻圖片使用心得
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;
}
}
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.