Android多媒体编程
多媒體概念
- 文字、圖片、音頻、視頻
計(jì)算機(jī)圖片大小的計(jì)算
圖片大小 = 圖片的總像素 * 每個(gè)像素占用的大小
- 單色圖:每個(gè)像素占用1/8個(gè)字節(jié)
- 16色圖:每個(gè)像素占用1/2個(gè)字節(jié)
- 256色圖:每個(gè)像素占用1個(gè)字節(jié)
- 24位圖:每個(gè)像素占用3個(gè)字節(jié)
加載大圖片到內(nèi)存
Android系統(tǒng)以ARGB表示每個(gè)像素,所以每個(gè)像素占用4個(gè)字節(jié),很容易內(nèi)存溢出
對(duì)圖片進(jìn)行縮放
- 獲取屏幕寬高
- 獲取圖片寬高
- 圖片的寬高除以屏幕寬高,算出寬和高的縮放比例,取較大值作為圖片的縮放比例
- 按縮放比例加載圖片
在內(nèi)存中創(chuàng)建圖片的副本
直接加載的bitmap對(duì)象是只讀的,無(wú)法修改,要修改圖片只能在內(nèi)存中創(chuàng)建出一個(gè)一模一樣的bitmap副本,然后修改副本
//加載原圖Bitmap srcBm = BitmapFactory.decodeFile("sdcard/photo3.jpg");iv_src.setImageBitmap(srcBm);//創(chuàng)建與原圖大小一致的空白bitmapBitmap copyBm = Bitmap.createBitmap(srcBm.getWidth(), srcBm.getHeight(), srcBm.getConfig());//定義畫筆Paint paint = new Paint();//把紙鋪在畫版上Canvas canvas = new Canvas(copyBm);//把srcBm的內(nèi)容繪制在copyBm上canvas.drawBitmap(srcBm, new Matrix(), paint);iv_copy.setImageBitmap(copyBm);對(duì)圖片進(jìn)行特效處理
- 首先定義一個(gè)矩陣對(duì)象
Matrix mt = new Matrix(); - 縮放效果
- 旋轉(zhuǎn)效果
- 平移
- 鏡面
- 倒影
畫畫板
在Android 中可以給View 控件設(shè)置觸摸事件監(jiān)聽(tīng),這些觸摸事件包括用戶點(diǎn)擊下去
(ACTION_DOWN),移動(dòng)(ACTION_MOVE)和抬起(ACTION_UP)。隨手涂鴉就是給ImageView(所有的控件都是View 的子類,都具備觸摸監(jiān)聽(tīng)功能)設(shè)置觸摸監(jiān)聽(tīng)事件,然后在ImageView 控件上進(jìn)行繪制線條操作。
當(dāng)用戶ACTION_DOWN 的時(shí)候獲取當(dāng)前的x 和y 坐標(biāo)作為要繪制線條的起始坐標(biāo),當(dāng)
ACTION_MOVE(該事件只要用戶在滑動(dòng)就不斷的被調(diào)用)的時(shí)候不斷的獲取新的x 和y 坐標(biāo),將新的坐標(biāo)作為要繪制線條的結(jié)束坐標(biāo)就可以繪制一條直線,然后將結(jié)束坐標(biāo)再作為新線條的起始坐標(biāo),依次類推,就能繪制出無(wú)限多個(gè)小直線,這些直線最終看起來(lái)就像是曲線的效果了。
最后可以將繪制好的圖片保存到本地文件中。
記錄用戶觸摸事件的XY坐標(biāo),繪制直線。給ImageView設(shè)置觸摸偵聽(tīng),得到用戶的觸摸事件,并獲知用戶觸摸ImageView的坐標(biāo)
iv.setOnTouchListener(new OnTouchListener() {@Overridepublic boolean onTouch(View v, MotionEvent event) {// TODO Auto-generated method stubswitch (event.getAction()) {//觸摸屏幕case MotionEvent.ACTION_DOWN://得到觸摸屏幕時(shí)手指的坐標(biāo)startX = (int) event.getX();startY = (int) event.getY();break;//在屏幕上滑動(dòng)case MotionEvent.ACTION_MOVE://用戶滑動(dòng)手指,坐標(biāo)不斷的改變,獲取最新坐標(biāo)int newX = (int) event.getX();int newY = (int) event.getY();//用上次onTouch方法得到的坐標(biāo)和本次得到的坐標(biāo)繪制直線canvas.drawLine(startX, startY, newX, newY, paint);iv.setImageBitmap(copyBm);startX = newX;startY = newY;break;}return true;} });- 刷子效果,加粗畫筆
- 調(diào)色板,改變畫筆顏色
- 保存圖片至SD卡
- 系統(tǒng)每次收到SD卡就緒廣播時(shí),都會(huì)去遍歷sd卡的所有文件和文件夾,把遍歷到的所有多媒體文件都在MediaStore數(shù)據(jù)庫(kù)保存一個(gè)索引,這個(gè)索引包含多媒體文件的文件名、路徑、大小
- 圖庫(kù)每次打開(kāi)時(shí),并不會(huì)去遍歷sd卡獲取圖片,而是通過(guò)內(nèi)容提供者從MediaStore數(shù)據(jù)庫(kù)中獲取圖片的信息,然后讀取該圖片
- 系統(tǒng)開(kāi)機(jī)或者點(diǎn)擊加載sd卡按鈕時(shí),系統(tǒng)會(huì)發(fā)送sd卡就緒廣播,我們也可以手動(dòng)發(fā)送就緒廣播
案例4:畫畫板
public class MainActivity extends Activity {private ImageView iv;int startX;int startY;private Canvas canvas;private Paint paint;private Bitmap bmCopy;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);//加載畫畫板的背景圖Bitmap bmSrc = BitmapFactory.decodeResource(getResources(), R.drawable.bg);bmCopy = Bitmap.createBitmap(bmSrc.getWidth(), bmSrc.getHeight(), bmSrc.getConfig());paint = new Paint();canvas = new Canvas(bmCopy);//繪制canvas.drawBitmap(bmSrc, new Matrix(), paint);iv = (ImageView) findViewById(R.id.iv);iv.setImageBitmap(bmCopy);//設(shè)置觸摸偵聽(tīng)iv.setOnTouchListener(new OnTouchListener() {//觸摸屏幕時(shí),觸摸事件產(chǎn)生時(shí),此方法調(diào)用@Overridepublic boolean onTouch(View v, MotionEvent event) {int action = event.getAction();switch (action) {//用戶手指摸到屏幕case MotionEvent.ACTION_DOWN:startX = (int) event.getX();startY = (int) event.getY();break;//用戶手指正在滑動(dòng)case MotionEvent.ACTION_MOVE:int x = (int) event.getX();int y = (int) event.getY();canvas.drawLine(startX, startY, x, y, paint);//每次繪制完畢之后,本次繪制的結(jié)束坐標(biāo)變成下一次繪制的初始坐標(biāo)startX = x;startY = y;iv.setImageBitmap(bmCopy);break;//用戶手指離開(kāi)屏幕case MotionEvent.ACTION_UP:break;}//true:告訴系統(tǒng),這個(gè)觸摸事件由我來(lái)處理//false:告訴系統(tǒng),這個(gè)觸摸事件我不處理,這時(shí)系統(tǒng)會(huì)把觸摸事件傳遞給imageview的父節(jié)點(diǎn)return true;}});}public void red(View v){paint.setColor(Color.RED);}public void green(View v){paint.setColor(Color.GREEN);}public void brush(View v){paint.setStrokeWidth(7);}public void save(View v){File file = new File("sdcard/dazuo.png");FileOutputStream fos = null;try {fos = new FileOutputStream(file);} catch (FileNotFoundException e) {// TODO Auto-generated catch blocke.printStackTrace();}bmCopy.compress(CompressFormat.PNG, 100, fos);//發(fā)送sd卡就緒廣播Intent intent = new Intent();intent.setAction(Intent.ACTION_MEDIA_MOUNTED);intent.setData(Uri.fromFile(Environment.getExternalStorageDirectory()));sendBroadcast(intent);} }撕衣服
把穿內(nèi)衣和穿外衣的照片重疊顯示,內(nèi)衣照在下面,用戶滑動(dòng)屏幕時(shí),觸摸的是外衣照,把手指經(jīng)過(guò)的像素都置為透明,內(nèi)衣照就顯示出來(lái)了
使用幀布局疊加2 個(gè)ImageView,每個(gè)ImageView 負(fù)責(zé)顯示一張圖片,一張圖片有衣服,一張圖片沒(méi)有衣服,沒(méi)有衣服的圖片放置在下面,有衣服的圖片放置在上面。給上面的ImageView 設(shè)置觸摸的事件,當(dāng)手指觸摸到圖片上時(shí),將手指觸摸到的點(diǎn)周邊的圖片的像素點(diǎn)設(shè)置為透明的,這樣下面的圖片就一點(diǎn)一點(diǎn)顯示出來(lái)了,從而有一種“撕衣服”的感覺(jué)。
在編寫該案例的時(shí)候應(yīng)該注意的事項(xiàng)如下:
1、 觸摸事件onTouch 的返回值必須設(shè)置為true,否則觸摸的事件將不被處理
2、 使用BitmapFactory 的decodeResouces 方法得到的圖片是沒(méi)有透明度的,即圖片格式為RGB_565,所
以若想能夠修改透明度,需要使用Canvas 對(duì)象對(duì)圖片進(jìn)行重繪,重新繪制的圖片格式采用ARGB。
3、 加載圖片時(shí)需要對(duì)其進(jìn)行一下壓縮,防止圖片與控件大小不匹配,導(dǎo)致觸摸時(shí)點(diǎn)對(duì)不上,達(dá)不到觸
摸哪里就設(shè)置哪里的像素點(diǎn)透明的效果。
每次只設(shè)置一個(gè)像素點(diǎn)太慢,以觸摸的像素為圓心,半徑為5畫圓,圓內(nèi)的像素全部置為透明
for (int i = -5; i < 6; i++) {for (int j = -5; j < 6; j++) {if(Math.sqrt(i * i + j * j) <= 5)copyBm.setPixel(newX + i, newY + j, Color.TRANSPARENT);} }案例5:撕衣服
public class MainActivity extends Activity {private Bitmap bmCopy;private ImageView iv;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);Bitmap bmSrc = BitmapFactory.decodeResource(getResources(), R.drawable.awaiyi);bmCopy = Bitmap.createBitmap(bmSrc.getWidth(), bmSrc.getHeight(), bmSrc.getConfig());Paint paint = new Paint();Canvas canvas = new Canvas(bmCopy);canvas.drawBitmap(bmSrc, new Matrix(), paint);iv = (ImageView) findViewById(R.id.iv);iv.setOnTouchListener(new OnTouchListener() {@Overridepublic boolean onTouch(View v, MotionEvent event) {switch (event.getAction()) {case MotionEvent.ACTION_MOVE:int x = (int) event.getX();int y = (int) event.getY();for(int i = -5; i <= 5; i++){for(int j = -5; j <= 5; j++){//把用戶劃過(guò)的坐標(biāo)置為透明色//改變指定的像素顏色if(Math.sqrt(i*i + j*j) <= 5){if(x + i < bmCopy.getWidth() && y + j < bmCopy.getHeight() && x + i >= 0 && y + j >= 0){bmCopy.setPixel(x + i, y + j, Color.TRANSPARENT);iv.setImageBitmap(bmCopy);}}}}break;}return true;}});} }音樂(lè)播放器
播放服務(wù)
- 播放音頻的代碼應(yīng)該運(yùn)行在服務(wù)中,定義一個(gè)播放服務(wù)MusicService
- 服務(wù)里定義play、stop、pause、continuePlay等方法
- 把這幾個(gè)方法抽取成一個(gè)接口MusicInterface
- 定義一個(gè)中間人類,繼承Binder,實(shí)現(xiàn)MusicInterface
- 先start啟動(dòng)MusicService,再bind
根據(jù)播放進(jìn)度設(shè)置進(jìn)度條
- 獲取當(dāng)前的播放時(shí)間和當(dāng)前音頻的最長(zhǎng)時(shí)間
- 播放進(jìn)度需要不停的獲取,不停的刷新進(jìn)度條,使用計(jì)時(shí)器每500毫秒獲取一次播放進(jìn)度
- 發(fā)消息至Handler,把播放進(jìn)度放進(jìn)Message對(duì)象中,在Handler中更新SeekBar的進(jìn)度
- 在Activity中定義Handler
拖動(dòng)進(jìn)度條改變播放進(jìn)度
//給sb設(shè)置一個(gè)拖動(dòng)偵聽(tīng)sb.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {//停止拖動(dòng)時(shí)調(diào)用@Overridepublic void onStopTrackingTouch(SeekBar seekBar) {// TODO Auto-generated method stubint progress = seekBar.getProgress();mi.seekTo(progress);}//開(kāi)始拖動(dòng)時(shí)調(diào)用 @Overridepublic void onStartTrackingTouch(SeekBar seekBar) {// TODO Auto-generated method stub}//拖動(dòng)的時(shí)候不斷調(diào)用 @Overridepublic void onProgressChanged(SeekBar seekBar, int progress,boolean fromUser) {// TODO Auto-generated method stub} });視頻播放器
SurfaceView
- 對(duì)畫面的實(shí)時(shí)更新要求較高
- 雙緩沖技術(shù):內(nèi)存中有兩個(gè)畫布,A畫布顯示至屏幕,B畫布在內(nèi)存中繪制下一幀畫面,繪制完畢后B顯示至屏幕,A在內(nèi)存中繼續(xù)繪制下一幀畫面
- 播放視頻也是用MediaPlayer,不過(guò)跟音頻不同,要設(shè)置顯示在哪個(gè)SurfaceView
- SurfaceView是重量級(jí)組件,可見(jiàn)時(shí)才會(huì)創(chuàng)建
- 給SurfaceHolder設(shè)置CallBack,類似于偵聽(tīng),可以知道SurfaceView的狀態(tài)
- SurfaceView一旦不可見(jiàn),就會(huì)被銷毀,一旦可見(jiàn),就會(huì)被創(chuàng)建,銷毀時(shí)停止播放,再次創(chuàng)建時(shí)再開(kāi)始播放
攝像頭
- 啟動(dòng)系統(tǒng)提供的拍照程序
- 啟動(dòng)系統(tǒng)提供的攝像程序
多媒體編程
- 文本、圖片、音頻、視頻
圖片
- 圖片在計(jì)算機(jī)中的大小
- 圖片的總大小 = 圖片的總像素 * 每個(gè)像素占用的大小
- 單色位圖:只能表示2種顏色
- 使用兩個(gè)數(shù)字:0和1
- 使用一個(gè)長(zhǎng)度為1的二進(jìn)制數(shù)字就可以表示了
- 每個(gè)像素占用1/8個(gè)字節(jié)
- 16色位圖:能表示16種顏色
- 需要16個(gè)數(shù)字:0-15,0000 - 1111
- 使用一個(gè)長(zhǎng)度為4的二進(jìn)制數(shù)組就可以表示了
- 每個(gè)像素占用1/2個(gè)字節(jié)
- 256色位圖:能表示256種顏色
- 需要256個(gè)數(shù)字:0 - 255,0000 0000 - 1111 1111
- 使用一個(gè)長(zhǎng)度為8的二進(jìn)制數(shù)字
- 每個(gè)像素占用1個(gè)字節(jié)
- 24位位圖:
- 每個(gè)像素占用24位,也就是3個(gè)字節(jié),所在叫24位位圖
- R:0-255,需要一個(gè)長(zhǎng)度為8的二進(jìn)制數(shù)字,占用1個(gè)字節(jié)
- G:0-255,需要一個(gè)長(zhǎng)度為8的二進(jìn)制數(shù)字,占用1個(gè)字節(jié)
- B:0-255,需要一個(gè)長(zhǎng)度為8的二進(jìn)制數(shù)字,占用1個(gè)字節(jié)
加載大圖片
- 計(jì)算機(jī)把圖片所有像素信息全部解析出來(lái),保存至內(nèi)存
- Android保存圖片像素信息,是用ARGB保存
- 手機(jī)屏幕320*480,總像素:153600
- 圖片寬高2400*3200,總像素7680000
- 2400 / 320 = 7
- 3200 / 480 = 6
創(chuàng)建圖片副本
- 在內(nèi)存中創(chuàng)建一個(gè)圖片的拷貝
保存圖片
- SD每次準(zhǔn)備的時(shí)候,系統(tǒng)其實(shí)是遍歷sd卡所有文件,系統(tǒng)會(huì)把所有的多媒體文件,都在MediaStore數(shù)據(jù)庫(kù)中生成一個(gè)索引,數(shù)據(jù)庫(kù)中保存了文件的文件名、路徑、大小、長(zhǎng)度和藝術(shù)家
- 圖庫(kù)、音樂(lè)、視頻程序每次啟動(dòng)時(shí),其實(shí)不會(huì)去遍歷sd卡尋找多媒體文件,而是直接從MediaStore數(shù)據(jù)庫(kù)中讀取多媒體文件,通過(guò)庫(kù)中的索引找到對(duì)應(yīng)的多媒體文件后,把文件顯示在界面
SurfaceView
- 雙緩沖技術(shù)
- 重量級(jí)組件
- 只要不可見(jiàn),就不會(huì)創(chuàng)建,可見(jiàn)時(shí),才會(huì)創(chuàng)建
- 只要不可見(jiàn),就會(huì)銷毀
FFMPEG
- 開(kāi)源免費(fèi)的音視頻編解碼器
Vitamio
- 封裝了FFMPEG的視頻播放框架
- 對(duì)外提供的api全部都是javaApi
案例1:加載大圖片
public class MainActivity extends Activity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);}public void click(View v){//解析圖片時(shí)需要使用到的參數(shù)都封裝在這個(gè)對(duì)象里了Options opt = new Options();//不為像素申請(qǐng)內(nèi)存,只獲取圖片寬高opt.inJustDecodeBounds = true;BitmapFactory.decodeFile("sdcard/dog.jpg", opt);//拿到圖片寬高int imageWidth = opt.outWidth;int imageHeight = opt.outHeight;Display dp = getWindowManager().getDefaultDisplay();//拿到屏幕寬高int screenWidth = dp.getWidth();int screenHeight = dp.getHeight();//計(jì)算縮放比例int scale = 1;int scaleWidth = imageWidth / screenWidth;int scaleHeight = imageHeight / screenHeight;if(scaleWidth >= scaleHeight && scaleWidth >= 1){scale = scaleWidth;}else if(scaleWidth < scaleHeight && scaleHeight >= 1){scale = scaleHeight;}//設(shè)置縮放比例opt.inSampleSize = scale;opt.inJustDecodeBounds = false;Bitmap bm = BitmapFactory.decodeFile("sdcard/dog.jpg", opt);ImageView iv = (ImageView) findViewById(R.id.iv);iv.setImageBitmap(bm);}}案例2:創(chuàng)建圖片的副本
public class MainActivity extends Activity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);//這個(gè)對(duì)象是只讀的Bitmap bmSrc = BitmapFactory.decodeFile("sdcard/photo3.jpg");//創(chuàng)建圖片副本//1.在內(nèi)存中創(chuàng)建一個(gè)與原圖一模一樣大小的bitmap對(duì)象,創(chuàng)建與原圖大小一致的白紙Bitmap bmCopy = Bitmap.createBitmap(bmSrc.getWidth(), bmSrc.getHeight(), bmSrc.getConfig());//2.創(chuàng)建畫筆對(duì)象Paint paint = new Paint();//3.創(chuàng)建畫板對(duì)象,把白紙鋪在畫板上Canvas canvas = new Canvas(bmCopy);//4.開(kāi)始作畫,把原圖的內(nèi)容繪制在白紙上canvas.drawBitmap(bmSrc, new Matrix(), paint);ImageView iv_src = (ImageView) findViewById(R.id.iv_src);ImageView iv_copy = (ImageView) findViewById(R.id.iv_copy);iv_src.setImageBitmap(bmSrc);iv_copy.setImageBitmap(bmCopy);} }案例3:圖片的簡(jiǎn)單特效
public class MainActivity extends Activity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);//這個(gè)對(duì)象是只讀的Bitmap bmSrc = BitmapFactory.decodeFile("sdcard/photo3.jpg");//創(chuàng)建圖片副本//1.在內(nèi)存中創(chuàng)建一個(gè)與原圖一模一樣大小的bitmap對(duì)象,創(chuàng)建與原圖大小一致的白紙Bitmap bmCopy = Bitmap.createBitmap(bmSrc.getWidth(), bmSrc.getHeight(), bmSrc.getConfig());//2.創(chuàng)建畫筆對(duì)象Paint paint = new Paint();//3.創(chuàng)建畫板對(duì)象,把白紙鋪在畫板上Canvas canvas = new Canvas(bmCopy);//4.開(kāi)始作畫,把原圖的內(nèi)容繪制在白紙上Matrix mt = new Matrix();//平移 // mt.setTranslate(20, 40);//縮放//sx:水平方向的縮放比例//sy:豎直方向的縮放比例 // mt.setScale(0.5f, 0.5f); // mt.setScale(0.5f, 0.5f, bmCopy.getWidth() / 2, bmCopy.getHeight() / 2);//旋轉(zhuǎn) // mt.setRotate(45, bmCopy.getWidth() / 2, bmCopy.getHeight() / 2);//鏡面 // mt.setScale(-1, 1); // mt.postTranslate(bmCopy.getWidth(), 0);//倒影mt.setScale(1, -1);mt.postTranslate(0, bmCopy.getHeight());canvas.drawBitmap(bmSrc, mt, paint);ImageView iv_src = (ImageView) findViewById(R.id.iv_src);ImageView iv_copy = (ImageView) findViewById(R.id.iv_copy);iv_src.setImageBitmap(bmSrc);iv_copy.setImageBitmap(bmCopy);} }案例6:播放音樂(lè)
package com.itheima.musicplayer;public interface MusicInterface {void play();void pause();void continuePlay();void seekTo(int progress); } public class MusicService extends Service {MediaPlayer player;private Timer timer;@Overridepublic IBinder onBind(Intent intent) {// TODO Auto-generated method stubreturn new MusicController();}class MusicController extends Binder implements MusicInterface{@Overridepublic void play() {MusicService.this.play();}@Overridepublic void pause() {MusicService.this.pause();}@Overridepublic void continuePlay() {MusicService.this.continuePlay();}@Overridepublic void seekTo(int progress) {MusicService.this.seekTo(progress);}}@Overridepublic void onCreate() {// TODO Auto-generated method stubsuper.onCreate();player = new MediaPlayer();}@Overridepublic void onDestroy() {// TODO Auto-generated method stubsuper.onDestroy();//停止播放player.stop();//釋放占用的資源,此時(shí)player對(duì)象已經(jīng)廢掉了player.release();player = null;if(timer != null){timer.cancel();timer = null;}}//播放音樂(lè)public void play(){//重置player.reset();try {//加載多媒體文件player.setDataSource("sdcard/zxmzf.mp3"); // player.setDataSource("http://192.168.13.119:8080/bzj.mp3"); // player.prepare();player.prepareAsync(); // player.start();player.setOnPreparedListener(new OnPreparedListener() {//準(zhǔn)備完畢時(shí),此方法調(diào)用@Overridepublic void onPrepared(MediaPlayer mp) {player.start();addTimer();}});} catch (Exception e) {// TODO Auto-generated catch blocke.printStackTrace();} }//繼續(xù)播放public void continuePlay(){player.start();}//暫停播放public void pause(){player.pause();}public void seekTo(int progress){player.seekTo(progress);}public void addTimer(){if(timer == null){timer = new Timer();timer.schedule(new TimerTask() {@Overridepublic void run() {//獲取歌曲總時(shí)長(zhǎng)int duration = player.getDuration();//獲取歌曲當(dāng)前播放進(jìn)度int currentPosition= player.getCurrentPosition();Message msg = MainActivity.handler.obtainMessage();//把進(jìn)度封裝至消息對(duì)象中Bundle bundle = new Bundle();bundle.putInt("duration", duration);bundle.putInt("currentPosition", currentPosition);msg.setData(bundle);MainActivity.handler.sendMessage(msg);}//開(kāi)始計(jì)時(shí)任務(wù)后的5毫秒,第一次執(zhí)行run方法,以后每500毫秒執(zhí)行一次}, 5, 500);}} } public class MainActivity extends Activity {static Handler handler = new Handler(){public void handleMessage(android.os.Message msg) {Bundle bundle = msg.getData();int duration = bundle.getInt("duration");int currentPostition = bundle.getInt("currentPosition");//刷新進(jìn)度條的進(jìn)度sb.setMax(duration);sb.setProgress(currentPostition);}};MusicInterface mi;private MyserviceConn conn;private Intent intent;private static SeekBar sb;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);sb = (SeekBar) findViewById(R.id.sb);sb.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {@Overridepublic void onStopTrackingTouch(SeekBar seekBar) {//根據(jù)拖動(dòng)的進(jìn)度改變音樂(lè)播放進(jìn)度int progress = seekBar.getProgress();//改變播放進(jìn)度mi.seekTo(progress);}@Overridepublic void onStartTrackingTouch(SeekBar seekBar) {}@Overridepublic void onProgressChanged(SeekBar seekBar, int progress,boolean fromUser) {}});intent = new Intent(this, MusicService.class);startService(intent);conn = new MyserviceConn();bindService(intent, conn, BIND_AUTO_CREATE);}class MyserviceConn implements ServiceConnection{@Overridepublic void onServiceConnected(ComponentName name, IBinder service) {mi = (MusicInterface) service;}@Overridepublic void onServiceDisconnected(ComponentName name) {// TODO Auto-generated method stub}}public void play(View v){mi.play();}public void continuePlay(View v){mi.continuePlay();}public void pause(View v){mi.pause();}public void exit(View v){unbindService(conn);stopService(intent);}}案例7:播放視頻
public class MainActivity extends Activity {private MediaPlayer player;static int currentPosition;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);SurfaceView sv = (SurfaceView) findViewById(R.id.sv);//拿到surfaceview的控制器final SurfaceHolder sh = sv.getHolder();// Thread t = new Thread(){ // @Override // public void run() { // // TODO Auto-generated method stub // try { // sleep(200); // } catch (InterruptedException e) { // // TODO Auto-generated catch block // e.printStackTrace(); // } // runOnUiThread(new Runnable() { // @Override // public void run() { // MediaPlayer player = new MediaPlayer(); // player.reset(); // try { // player.setDataSource("sdcard/2.3gp"); // player.setDisplay(sh); // player.prepare(); // player.start(); // } catch (Exception e) { // // TODO Auto-generated catch block // e.printStackTrace(); // } // // } // }); // // } // }; // t.start();sh.addCallback(new Callback() {//surfaceView銷毀時(shí)調(diào)用@Overridepublic void surfaceDestroyed(SurfaceHolder holder) {//每次surfaceview銷毀時(shí),同時(shí)停止播放視頻if(player != null){currentPosition = player.getCurrentPosition();player.stop();player.release();player = null;}}//surfaceView創(chuàng)建時(shí)調(diào)用@Overridepublic void surfaceCreated(SurfaceHolder holder) {//每次surfaceView創(chuàng)建時(shí)才去播放視頻if(player == null){player = new MediaPlayer();player.reset();try {player.setDataSource("sdcard/2.3gp");player.setDisplay(sh);player.prepare();player.start();player.seekTo(currentPosition);} catch (Exception e) {// TODO Auto-generated catch blocke.printStackTrace();} }}//surfaceView結(jié)構(gòu)改變時(shí)調(diào)用@Overridepublic void surfaceChanged(SurfaceHolder holder, int format, int width,int height) {// TODO Auto-generated method stub}});}}案例8:VideoView
public class MainActivity extends Activity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);//檢測(cè)是否支持vitamioif (!LibsChecker.checkVitamioLibs(this)) {return;}VideoView vv = (VideoView) findViewById(R.id.vv);vv.setVideoPath("sdcard/4.rmvb");vv.start();vv.setMediaController(new MediaController(this));} }案例9:攝像頭
public class MainActivity extends Activity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);}public void image(View v){//啟動(dòng)系統(tǒng)提供的拍照activityIntent intent = new Intent();intent.setAction(MediaStore.ACTION_IMAGE_CAPTURE);intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(new File(Environment.getExternalStorageDirectory(), "haha.jpg")));startActivityForResult(intent, 10);}@Overrideprotected void onActivityResult(int requestCode, int resultCode, Intent data) {// TODO Auto-generated method stubsuper.onActivityResult(requestCode, resultCode, data);if(requestCode == 10){Toast.makeText(this, "拍照成功", 0).show();}else if(requestCode == 20){Toast.makeText(this, "攝像成功", 0).show();}}public void video(View v){//啟動(dòng)系統(tǒng)提供的攝像activityIntent intent = new Intent();intent.setAction(MediaStore.ACTION_VIDEO_CAPTURE);intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(new File(Environment.getExternalStorageDirectory(), "haha.3gp")));intent.putExtra(MediaStore.EXTRA_VIDEO_QUALITY, 1);startActivityForResult(intent, 20);}}案例10:vitamio_lib
總結(jié)
以上是生活随笔為你收集整理的Android多媒体编程的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: Android应用开发:页面跳转和数据传
- 下一篇: Android应用开发:动画和Fragm