安卓学习第七天

本文详细介绍Android平台上的多媒体应用开发,包括音频和视频的播放、控制流程及注意事项,SoundPool的使用场景及其异步特性,多媒体组件MediaPlayer的生命周期,以及如何处理电话状态变化时的播放控制。此外还涉及Notification的通知展示和交互方式。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

mediaPlayer.reset(); // 重置 播放器的状态
//				mediaPlayer.setDataSource(path);
//				mediaPlayer.prepare(); // c/c++ 播放器引擎的初始化
//				mediaPlayer.start();

多媒体: 
文字->  
图片 声音 视频

native表示这个方法实现是由底层的C、C++实现的这里面只是声明一下。
adb pull /mnt/sdcard/a.jsp  a.jsp
adb push e.mp3 /sdcard/e.mp3(压进去一个)

SoundPool:主要在游戏中处理一些密集的声音,如枪声,爆炸。
并且可以多个同时进行,例如枪声,肯定大家都在放 ,说明了
这个操作肯定是异步的。你放完之后就不管了,进行放另外一个,
而不是等到,这个声音放完,再返回一个我放完的消息,这样才能
执行下一个请求,这是同步。



同步和异步的区别.



同步: 张三叫李四吃饭 如果李四不回答 ,张三就一直的等待.

异步: 张三叫李四吃饭,李四回答不回答张三,张三就接着干自己的事情


问多次调用异步方法 会有什么样的问题?
回调同样的多的方法。


SurfaceView内部维护了一个双缓冲的机制,提高画面的显示速度和质量。(见图片)
其实就是有两个缓冲区。

//视频播放,我的弱点,没有看。做到相关的项目的时间再具体看。

MediaPlayer的生命周期:
有一张图。

android 多媒体框架 可以播放某些类型的视频 
要求视频的格式 必须是渐进式的格式
安卓它支持以下两种格式 ,流格式。
http:// 3gp格式
rtsp的格式 流媒体数据(real time stream protocol)

苹果公司开发的QuickTime支持把视频转化成流媒体。
关键是把视频做成一个支持渐近式的格式 ,它就可以在线播放了。

//Holder是一个内容填充器。

拍照功能:
需求:
1、程序界面必须要横屏显示---这个要注册文件的activity里面android:screenOrientation="landscape"
2、横屏显示 无论用户是否切换屏幕,始终横屏。
3、隐藏标题栏和状态栏。
 super.onCreate(savedInstanceState);
//除去标题栏
requestWindowFeature(Window.FEATURE_NO_TITLE);
//全屏显示 
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, 
		WindowManager.LayoutParams.FLAG_FULLSCREEN);
setContentView(R.layout.main);

在每个组件里面都可以设置
android:layout_weight="100"
这个属性与CSS中z-index效果是一样的。谁的数字小,谁先显示。

多媒体的知识先放一放,到项目时间再回头学习。

Notification:
它也是系统的一个服务,所以你应该明白,它与短信管理,电话管理器等获取方法是一样的。
public void click(View view){
    	//1.Get a reference to the NotificationManager:
    	// 得到一个notification的服务 
    	NotificationManager notificationManager = (NotificationManager) this.getSystemService(Context.NOTIFICATION_SERVICE);
    	// 2.Instantiate the Notification:第二个参数是出现 的提示信息
    	Notification notification = new Notification(R.drawable.ic_launcher,"tickertext",System.currentTimeMillis());
//    	notification.sound= Uri.fromFile(new File("/sdcard/haha.mp3"));
//    	notification.flags = Notification.FLAG_NO_CLEAR; 没有清除的图标 
    	
    	//3.Define the notification's message and PendingIntent(将要发生意图):
    	Intent intent = new Intent(this,NoticationActivity.class);//后面参数表示下拉并且点击之后进入哪个activity
    	PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, 0);
    	//是指下拉之后 显示 的信息
    	notification.setLatestEventInfo(this, "notife 标题", "noti 正文", pendingIntent);
    	//4.Pass the Notification to the NotificationManager:
    	notificationManager.notify(0, notification);
    	
    }
	
常用组件:



public class Mp3Activity extends Activity implements OnClickListener {
	private EditText et_path;
	private Button bt_play, bt_pause, bt_replay, bt_stop;
	private MediaPlayer mediaPlayer;
	private TelephonyManager telephonyManager;
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        
        et_path = (EditText) this.findViewById(R.id.et_path);
		bt_play = (Button) this.findViewById(R.id.play);
		bt_pause = (Button) this.findViewById(R.id.pause);
		bt_replay = (Button) this.findViewById(R.id.replay);
		bt_stop = (Button) this.findViewById(R.id.stop);
		
		//
		mediaPlayer = new MediaPlayer();
		//初始化系统的通话服务,当电话来的时间,应该暂停播放
		telephonyManager = (TelephonyManager) this.getSystemService(TELEPHONY_SERVICE);
		telephonyManager.listen(new MyListener(), PhoneStateListener.LISTEN_CALL_STATE);

		bt_play.setOnClickListener(this);
		bt_pause.setOnClickListener(this);
		bt_replay.setOnClickListener(this);
		bt_stop.setOnClickListener(this);
    }
	@Override
	public void onClick(View v) {
		switch (v.getId()) {
		case R.id.play:
			String path = et_path.getText().toString().trim();
			try {
				play(path);
			} catch (Exception e) {
				e.printStackTrace();
			}
			break;
		case R.id.pause:
			pause();
			break;
		case R.id.replay:
			if (mediaPlayer!=null&&mediaPlayer.isPlaying()) {
				mediaPlayer.seekTo(0);
			}else {
				path = et_path.getText().toString().trim();
				try {
					play(path);
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
			break;
		case R.id.stop:
			if (mediaPlayer!=null && mediaPlayer.isPlaying()) {
				mediaPlayer.stop();
				mediaPlayer = null;
				bt_play.setEnabled(true);
				bt_play.setClickable(true);
			}
			break;
			
			
		}
		
	}
	
	public void play(String path) throws Exception{
		if ("".equals(path)) {
			Toast.makeText(this, "路径不能为空", 0).show();
		}
		File file = new File(path);
		if (mediaPlayer == null) {
			mediaPlayer = new MediaPlayer();
		}
		if (file.exists()) {
			mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
			mediaPlayer.setDataSource(path);
//			mediaPlayer.prepare();这个利用的是同步的方法
			/*为了避免用户界面UI线程的挂起,请启动另一个线程来准备MediaPlayer并在完成后通知主线程。
			不过这就可能要自行编写线程逻辑,这也是使用MediaPlayer时的通常做法,利用其prepareAsync()方法,
			框架提供一种便利的途径来完成此类任务。这个方法在后台进行媒体的准备工作
			,并且立即返回。媒体准备完毕后,将会调用MediaPlayer.OnPreparedListener的onPrepared()方法
			,该Listener通过setOnPreparedListener()指定。*/
			mediaPlayer.prepareAsync();
			//准备完成之后它会通知主线程,也就是说在媒体准备完毕之后会调用下面的方法。因为准备这个方法太耗时了,所以写在另外一个
			//线程里面,不能放在主线程里面,不过谷歌工程师提供了一种更为简单的方法。
			mediaPlayer.setOnPreparedListener(new OnPreparedListener() {
				@Override
				public void onPrepared(MediaPlayer mp) {
					mediaPlayer.start();
					bt_play.setEnabled(false);
					bt_play.setClickable(false);
				}
			});
			
			//注册播放完毕后的监听事件 
			mediaPlayer.setOnCompletionListener(new OnCompletionListener() {
				@Override
				public void onCompletion(MediaPlayer mp) {
					mediaPlayer.release();
					mediaPlayer = null;
					bt_play.setEnabled(true);
					bt_play.setClickable(true);
				}
			});
			
		}else {
			Toast.makeText(this, "文件不存在", 0).show();
			return;
		}
	}
	
	public void pause(){
		// 判断音乐是否在播放
		if (mediaPlayer!=null&&mediaPlayer.isPlaying()) {
			// 暂停音乐播放器
			mediaPlayer.pause();
			bt_pause.setText("续播");
			return;
		}
		if (mediaPlayer!=null&&"续播".equals(bt_pause.getText().toString())) {
			mediaPlayer.start();
			bt_pause.setText("暂停"); 
			return;
		}
		
		if (mediaPlayer!=null && !mediaPlayer.isPlaying()) {
			Toast.makeText(this, "你还没有开始播放", 0).show();
			return;
		}
	}
	
	
	
	private class MyListener extends PhoneStateListener{
		@Override
		public void onCallStateChanged(int state, String incomingNumber) {
			super.onCallStateChanged(state, incomingNumber);
			
			switch (state) {
			case TelephonyManager.CALL_STATE_RINGING:
				pause();
				break;

			case TelephonyManager.CALL_STATE_IDLE://如果是空闲 
				//继续
				pause();
				break;
			}
		}
	}
	
}


public class SoundPoolActivity extends Activity {
	SoundPool soundPool;
	int soundid;
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        soundPool = new SoundPool(5, AudioManager.STREAM_MUSIC, 0);
     // 这语句代码 是一个异步的操作 需要花费一定的时间去把声音装载到内存池中。所以它应该在创建的时间就已经加载了。
        soundid = soundPool.load(this, R.raw.ring, 1);
    }
    
    
    
    public void shoot(View view){
    	//如果你把soundid = soundPool.load(this, R.raw.ring, 1);放在这,肯定要出问题
    	//因为它是异步的,不会阻塞,不会等到加载完以后再去调用下面的方法,所以当调用下面的方法时间,声音还没有加载完,就不会出声音了。
    	//所以异步方法执行过多,会出现的问题是,返回过多。
    	/**
    	 * soundID	a soundID returned by the load() function
			leftVolume	left volume value (range = 0.0 to 1.0)
			rightVolume	right volume value (range = 0.0 to 1.0)
			priority	stream priority (0 = lowest priority)
			loop	loop mode (0 = no loop, -1 = loop forever)
			rate	playback rate (1.0 = normal playback, range 0.5 to 2.0)
    	 */
    	soundPool.play(soundid, 1.0f, 1.0f, 0, 0, 2.0f);
    	//其实TOM猫就是利用最后参数在起作用
    }  
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值