第十天 media 视频 音频

多媒体编程


1、什么是多媒体?
   多种媒体的综合。图片、音乐、视频。


##01_计算机表示图形的方式
1、bmp 以高质量保存所有类型的图片,用于计算机。
计算机使用像素点表示图形,每个像素点都是一个颜色,24位深度(24bit)。
        每个像素点的颜色是一个RGB,使用6个十六进制的数值来表示。
        文件头信息占用的数据大小。  体积比较大。
       
    2、jpg 以良好的质量保存图片,用于计算机、电子邮件或网络。
       
      jpg 工业图形的压缩算法,类似rar的算法。人眼识别精度有限,把相邻空间内类似的颜色使用同一个颜色来表示。 体积减小,失真。
    3、png 203.2k 255*340 以高质量保存图片或者绘图,用于计算机或网络。

      
    




##02_加载大图片的OOM异常


java.lang.OutOfMemoryError : 


   堆内存空间:给类实例、数组分配内存空间的。   RGB 
   ARGB 32 


   应用程序在启动时系统为它创建一个进程,系统为每个进程创建dalvik虚拟机(模拟器设置的VM Heap),当图片的大小大于虚拟机的堆内存空间时,就内存溢出(内存泄露);


  解决办法:缩放图片加载到内存
  步骤:
   1、获得设备屏幕的分辨率;
   2、得到原图的分辨率;
   3、通过比较得到一个合适的比例值;
   4、按照比例值缩放图片
   5、把图片显示在imageview


  


##03_缩放图片并加载到内存中
  解决办法:


缩放图片加载到内存
步骤:
  1、获得设备屏幕的分辨率;
  2、得到原图的分辨率;
  3、通过比较得到一个合适的比例值;
  4、按照比例值缩放图片
  5、把图片显示在imageview


 代码:


package com.itheima.loadbigpic;

import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.BitmapFactory.Options;
import android.os.Bundle;
import android.os.Environment;
import android.view.Display;
import android.view.WindowManager;
import android.widget.ImageView;

public class MainActivity extends Activity {


private ImageView iv;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        iv = (ImageView) findViewById(R.id.iv);
        
//        1、获得设备屏幕的分辨率;
        //通过服务获得窗口管理器
        WindowManager  wm =  (WindowManager) getSystemService(WINDOW_SERVICE);
        //获得设备分辨率对象
        Display display = wm.getDefaultDisplay();
        
        //api13之前使用这个两个方法,13之后置为过期
        int screenWidth = display.getWidth();
        int screenHeight = display.getHeight();
        
        
//        2、得到原图的分辨率;
       
        Options opts = new Options();
        opts.inJustDecodeBounds = true;
        //opts为null 可以返回一个图片对象,如果不为null ,就会返回null
        BitmapFactory.decodeFile(Environment.getExternalStorageDirectory()+"/lp.jpg", opts);
        //得到原图的宽和高
         int srcWidth = opts.outWidth;
         int srcHeight = opts.outHeight;
         
         
//        3、通过比较得到一个合适的比例值;
         //3000/320 = 9 2262/480 =5
         int sx = srcWidth/screenWidth;
         int sy = srcHeight/screenHeight;
         int scale = 0;
         if(sx >= 1 && sx > sy){
        scale = sx;
         }else if(sy >= 1 && sy > sx){
        scale = sy;
         }
         
//     4、按照比例值缩放图片
           opts.inJustDecodeBounds = false;
           opts.inSampleSize = scale; // 1/scale * 1/scale
           Bitmap bm = BitmapFactory.decodeFile(Environment.getExternalStorageDirectory()+"/lp.jpg", opts);
          
//    5、把图片显示在imageview
           
           iv.setImageBitmap(bm);
    }

}




##04_在内存中创建原图的副本(重点)
 步骤:
  1、得到原图;
  2、创建一个空白的纸张,参考原图;
  3、创建一个画板,参考空白纸张;
  4、创建一个画笔;
  5、在画板上画画;


  代码:


package com.itheima.copypic;


import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.os.Bundle;
import android.widget.ImageView;

public class MainActivity extends Activity {


private ImageView iv;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

iv = (ImageView) findViewById(R.id.iv);


//   1、得到原图;
   Bitmap srcPic = BitmapFactory.decodeResource(getResources(), R.drawable.meinv);
   
   //config 包括位深度
//   2、创建一个空白的纸张,参考原图;
  Bitmap copyPic = Bitmap.createBitmap(srcPic.getWidth(), srcPic.getHeight(), srcPic.getConfig());
//   3、创建一个画板,参考空白纸张;
  Canvas canvas = new Canvas(copyPic);
  
//   4、创建一个画笔;
  Paint paint = new Paint();
  paint.setColor(Color.BLACK);//默认是使用黑色,后面会根据原图的颜色画画
//   5、在画板上画画;
  canvas.drawBitmap(srcPic, new Matrix(), paint);
  
  iv.setImageBitmap(copyPic);
}




}
   


##05_计算机图形处理的API(重点)


    * 旋转
    * 缩放
    * 平移
    * 镜面、倒影
    * 修改颜色
ColorMatrix cm = new ColorMatrix();
cm.set(new float[] {
1, 0, 0, 0, 0,  //red
0, 1, 0, 0, 0,  //green
0, 0, 1, 0, 0,  //blue
0, 0, 0, 1, 0   //透明度
});
paint.setColorFilter(new ColorMatrixColorFilter(cm));




##06_微信画画板  


package com.itheima.painter;


import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.os.Bundle;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.widget.ImageView;


public class MainActivity extends Activity {


private ImageView iv;
private Bitmap srcPic;
private Bitmap copyPic;
private Canvas canvas;
private Paint paint;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);


iv  = (ImageView) findViewById(R.id.iv);



srcPic = BitmapFactory.decodeResource(getResources(), R.drawable.bg);
   
copyPic = Bitmap.createBitmap(srcPic.getWidth(), srcPic.getHeight(), srcPic.getConfig());
canvas = new Canvas(copyPic);
  
paint = new Paint();
  paint.setColor(Color.BLACK);//默认是使用黑色,后面会根据原图的颜色画画
//   5、在画板上画画;
  
  Matrix matrix = new Matrix();
//   
  canvas.drawBitmap(srcPic, matrix, paint);
  iv.setImageBitmap(copyPic);
  
  iv.setOnTouchListener(new OnTouchListener(){
  int startX ;
  int startY;
@Override
public boolean onTouch(View v, MotionEvent event) {
int type = event.getAction();


switch (type) {
case MotionEvent.ACTION_DOWN:

//开始坐标点
startX = (int) event.getX();

startY = (int) event.getY();

break;


case MotionEvent.ACTION_MOVE :

//得到结束点的坐标
int newX = (int) event.getX();
int newY = (int) event.getY();

canvas.drawLine(startX, startY, newX, newY, paint);

iv.setImageBitmap(copyPic);

//得到新的开始坐标点
startX = (int) event.getX();

startY = (int) event.getY();
break;
}

//消费掉当前的监听器
return true;
}
  
  });
  
}





}




##07_视频播放器videoview(重点)



代码:


package com.itheima.videoview;

import android.app.Activity;
import android.os.Bundle;
import android.widget.VideoView;

public class MainActivity extends Activity {

private VideoView vv;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

vv = (VideoView) findViewById(R.id.vv);

vv.setVideoPath("http://192.168.22.136:8080/11.mp4");

vv.start();


}


}




##8_视频播放器surfaceview(重点)


surfaceview表面视图


双缓冲区:使用两个线程协调工作;


surfaceview 重量级空间,当画面可见时,双缓冲器被创建,占用较高的cpu和内存资源。
当界面不可见时,双缓冲器占用释放。
package com.itheima.surfaceview;


import android.app.Activity;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnPreparedListener;
import android.os.Bundle;
import android.view.SurfaceHolder;
import android.view.SurfaceHolder.Callback;
import android.view.SurfaceView;


public class MainActivity extends Activity {


private SurfaceView sv;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

sv = (SurfaceView) findViewById(R.id.sv);

SurfaceHolder holder = sv.getHolder();
//推送缓冲数据,api 13之前的版本上必须执行这行代码,13版本之后,播放器可以自动把
//数据加载到缓冲区
holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);


holder.addCallback(new Callback() {

private MediaPlayer mediaPlay;






@Override
public void surfaceCreated(SurfaceHolder holder) {
try {
mediaPlay = new MediaPlayer();

mediaPlay.setDataSource("http://192.168.22.136:8080/11.mp4");
mediaPlay.setAudioStreamType(AudioManager.STREAM_MUSIC);

mediaPlay.setDisplay(holder);

//使用阻塞式准备方法,等待数据资源准备完成后才开始播放,用于播放本地的音视频文件
// mediaPlay.prepare(); 
//使用异步式准备方法,使用子线程等待数据资源准备完成后才开始播放,用于播放网络上的音视频文件
mediaPlay.prepareAsync();



mediaPlay.setOnPreparedListener(new OnPreparedListener() {

@Override
public void onPrepared(MediaPlayer mp) {

mediaPlay.start();
}
});


} catch (Exception e) {
e.printStackTrace();
}

}

@Override
public void surfaceDestroyed(SurfaceHolder holder) {
if(mediaPlay != null && mediaPlay.isPlaying()){
mediaPlay.stop();

mediaPlay.release();

mediaPlay = null;

// mediaPlay.seekTo(msec);

}

}


@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
// TODO Auto-generated method stub

}
});
}





}




##9_音乐播放器API

package com.itheima.baidumusic;


import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.view.Menu;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.SeekBar;
import android.widget.SeekBar.OnSeekBarChangeListener;


public class MainActivity extends Activity {


private Iservice iservice; // 这个就是我们定义的中间人对象
private MyConn conn;
private static SeekBar sbar;  
public  static Handler handler = new Handler(){
//当 接收到消息该方法执行
public void handleMessage(android.os.Message msg) {
//[1]获取msg 携带的数据 
Bundle data = msg.getData();
//[2]获取当前进度和总进度
int duration = data.getInt("duration");
int currentPosition = data.getInt("currentPosition");

//[3]设置seekbar的最大进度和当前进度 
sbar.setMax(duration);  //设置进度条的最大值
sbar.setProgress(currentPosition);//设置当前进度



};
};




@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);


sbar = (SeekBar) findViewById(R.id.seekBar1);


//[0]先调用startservice 方法开启服务 保证服务在后台长期运行
Intent intent = new Intent(this, MusicService.class);
startService(intent);

// [1]调用bindservice 目的是为了获取我们定义的中间人对象
conn = new MyConn();
// 连接MusicService 服务 获取我们定义的中间人对象
bindService(intent, conn, BIND_AUTO_CREATE);


//[2]给seekbar 设置监听 


sbar.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {
//当停止拖动执行
@Override
public void onStopTrackingTouch(SeekBar seekBar) {

//设置播放的位置 
iservice.callSeekToPosition(seekBar.getProgress());
}
//开始拖动
@Override
public void onStartTrackingTouch(SeekBar seekBar) {

}

@Override
public void onProgressChanged(SeekBar seekBar, int progress,
boolean fromUser) {

}
});

}


// 点击按钮 进行 音乐播放
public void click1(View v) {


// 调用播放音乐的方法
iservice.callPlayMusic();
}


// 暂停音乐
public void click2(View v) {


// 调用暂停音乐的方法
iservice.callPauseMusic();
}


// 继续播放
public void click3(View v) {


// 调用继续播放
iservice.callrePlayMusic();
}


// 当Activity销毁的时候调用
@Override
protected void onDestroy() {
// 在Activity销毁的时候 取消绑定服务
unbindService(conn);


super.onDestroy();
}


private class MyConn implements ServiceConnection {


// 当连接成功时候调用
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
// 获取我们定义的中间人对象
iservice = (Iservice) service;


}


@Override
public void onServiceDisconnected(ComponentName name) {


}


}


}






package com.itheima.baidumusic;


import java.util.Timer;
import java.util.TimerTask;


import android.app.Service;
import android.content.Intent;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnCompletionListener;
import android.os.Binder;
import android.os.Bundle;
import android.os.IBinder;
import android.os.Message;


//音乐播放服务
public class MusicService extends Service {


private MediaPlayer player;


//[2]把我们定义的中间人对象 返回
@Override
public IBinder onBind(Intent intent) {
return new MyBinder();
}
//服务第一次开启的是调用
@Override
public void onCreate() {

//[1]初始化mediaplayer 
player = new MediaPlayer();

super.onCreate();
}


//当服务销毁的时候调用
@Override
public void onDestroy() {
super.onDestroy();
}

//设置播放音乐指定位置的方法
public void seekToPosition(int position){
player.seekTo(position);
}




//专门用来播放音乐的 
public void playMusic(){
System.out.println("音乐播放了");

//[2]设置要播放的资源  path 可以是本地也可是网络路径 
try {
player.reset();

player.setDataSource("/mnt/sdcard/xpg.mp3");

//[3]准备播放 
player.prepare(); 

//[4]开始播放 
player.start();

//[5]更新进度条 
updateSeekBar();

} catch (Exception e) {
e.printStackTrace();
}


}

//更新进度条的方法 
private void updateSeekBar() {
//[1]获取当前歌曲总时长 
final int duration = player.getDuration();
//[2]一秒钟获取一次当前进度  
final Timer timer = new Timer();
final TimerTask task = new TimerTask() {

@Override
public void run() {
//[3]获取当前歌曲的进度 
int currentPosition = player.getCurrentPosition();

//[4]创建message对象  
Message msg = Message.obtain();
//[5]使用msg携带多个数据   
Bundle bundle = new Bundle();
bundle.putInt("duration", duration);
bundle.putInt("currentPosition", currentPosition);
msg.setData(bundle);
//发送消息 MainActivity的handlemessage方法会执行
MainActivity.handler.sendMessage(msg);

}
};
//300毫秒后 每隔1秒钟获取一次当前歌曲的进度
timer.schedule(task, 300, 1000);
//[3]当歌曲播放完成的时候 把timer 和task 取消 
player.setOnCompletionListener(new OnCompletionListener() {

//当歌曲播放完成的回调
@Override
public void onCompletion(MediaPlayer mp) {
System.out.println("歌曲播放完成了 ");

timer.cancel();
task.cancel();

}
});


}
//音乐暂停了
public void pauseMusic(){
System.out.println("音乐暂停了");
//暂停 
player.pause();

}

//音乐继续播放的方法
public void  rePlayMusic(){
System.out.println("音乐继续播放了");

player.start();

}

//[1]定义一个中间人对象(IBinder) 
private class MyBinder extends Binder implements Iservice{


//调用播放音乐的方法
@Override
public void callPlayMusic() {

playMusic();
}


//调用暂停音乐的方法
@Override
public void callPauseMusic() {

pauseMusic();
}


//调用继续播放的方法 
@Override
public void callrePlayMusic() {

rePlayMusic();
}


//调用设置播放指定位置的方法 
@Override
public void callSeekToPosition(int position) {

seekToPosition(position);
}

}



}




package com.itheima.baidumusic;


public interface Iservice {
//把我们想暴露的方法放到接口中
public void callPlayMusic();
public void callPauseMusic();
public void callrePlayMusic();

public void callSeekToPosition(int position);

}






##10_vitamio框架的使用


    1 引入vitamio框架  以library、
    
    2 在布局中定义VideoView
       <io.vov.vitamio.widget.VideoView 
        android:id="@+id/vv"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        />






    3 mainactivity代码
       插件vitamio框架检查是否可用
       if (!LibsChecker.checkVitamioLibs(this)) {
return;
}

final VideoView vv = (VideoView) findViewById(R.id.vv);
vv.setVideoPath("http://192.168.1.2:8080/haha.avi");
vv.setOnPreparedListener(new OnPreparedListener() {

@Override
public void onPrepared(MediaPlayer mp) {
vv.start();

}
});
//设置video的控制器
vv.setMediaController(new MediaController(this));




     4 一定要在清单文件初始化InitActivity
        <activity android:name="io.vov.vitamio.activity.InitActivity"></activity>




##11_照相机拍照
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); 

file = new File(Environment.getExternalStorageDirectory()+"/123.jpg");

intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(file));

startActivityForResult(intent, 0);


##12_录机应用
Intent intent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE); 

file = new File(Environment.getExternalStorageDirectory()+"/123.3gp");

intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(file));

startActivityForResult(intent, 0);
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值