安卓开发之WebView,进度条ProgressBar以及MediaPlayer和SonundPool的使用

      内容比较简单,仅用作笔记,所以就不过多解释,有一些地方代码思路不是很清晰,有点乱,日后会进行修改的。


1、新建一个SoundPool管理器,实现soundpool的创建,加载以及播放音频等功能

package com.example.myexplorer;
import java.util.Random;

import android.annotation.SuppressLint;
import android.content.Context;
import android.media.AudioAttributes;
import android.media.SoundPool;
import android.media.SoundPool.OnLoadCompleteListener;
import android.os.Build;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.util.SparseArray;

public class SoundPoolManager implements OnLoadCompleteListener{
	Context context;
	SoundPool soundPool;
	MyHandler myHandler;
	private final int SOUND_LOAD_OK=1;
	//创建一个SpareseArray对象来存放管理音频资源
	private SparseArray<Object> soundMap=new SparseArray<>(); 
	//实现构造函数,传递context
	public SoundPoolManager(Context context) {
		// TODO Auto-generated constructor stub
		this.context=context;
	}
	
	
/*
 * 创建一个SoundPool池,回调时需要指定创建的池的最大可容纳数量,声音类型以及音频品质
 */
	@SuppressLint("NewApi")
	@SuppressWarnings("deprecation")
	protected void creatSounPool(int maxStreams,int streamType,int srcQuality) {
		if(Build.VERSION.SDK_INT>=21) {                                  //判断为安卓5以上时使用该方法创建,否则5.0以上系统不会播放
			AudioAttributes abs = new AudioAttributes.Builder()
	                .setUsage(AudioAttributes.USAGE_MEDIA)
	                .setContentType(AudioAttributes.CONTENT_TYPE_MUSIC)
	                .build() ;
			soundPool=new SoundPool.Builder()
					.setMaxStreams(5)
					.setAudioAttributes(abs)
					.build();	//创建一个SoundPool对象,该对象可以容纳5个音频流
			}
		else
			soundPool=new SoundPool(maxStreams,streamType,srcQuality);   //安卓5以下的soundpool创建方法
		Log.i("SoundPoolCreat","successfull");
	}
	/*
	 * 加载资源到创建好的SoundPool里面,需要提供音频资源名称以及优先级
	 */
	protected void load(String[] ResourcesName,int priority) {
		for(int i=0;i<ResourcesName.length;i++) {
		soundMap.put(i,soundPool.load(context,context.getResources().
				getIdentifier("com.example.myexplorer:raw/"+ResourcesName[i]
						,null,null) ,priority));
		Log.i("SoundPoolLoad"+i,"successfull");
		}
		soundPool.setOnLoadCompleteListener(this);
		
	}
	/*
	 * 开始播放,要求提供左声道音量leftVolume,右声道音量rightVolume,播放优先级priority,是否循环loop(0为不循环,1为循环)
	 * 播放速率rate
	 */
	protected void play(float leftVolume,
			float rightVolume,int priority,int loop,float rate) {
		int i=0;
	
		//随机播放加载的三个背景音乐
			soundPool.play((int)soundMap.get((int)(new Random().nextInt(3))),  //产生等概率0-2的随机数
					leftVolume, rightVolume, priority, loop, rate);
		Log.i("SoundPoolPlay"+(i++),"successfull");
	}
	/*
	 * 设置加载完成监听,防止未加载完成就播放
	 */
	@SuppressLint("HandlerLeak")
	@Override
	public void onLoadComplete(SoundPool soundPool, int sampleId, int status) {
		
		// TODO Auto-generated method stub
		Log.i("Load","Complete");
		myHandler=new MyHandler();
		Message message=myHandler.obtainMessage();
		message.what=SOUND_LOAD_OK;
		myHandler.sendMessage(message);
	}
	@SuppressLint("HandlerLeak")
	public class MyHandler extends Handler{

		private final int SOUND_LOAD_OK=1;
		@Override
		public void handleMessage(Message msg) {
			switch (msg.what) {
			case SOUND_LOAD_OK:
				//这里添加加载完成后需要做的事
				//play(1, 1, 0, 0, 1);
				break;
			default:
				break;
			}
		}
	}
}

需要注意的是,代码中出现了这么一个判断API的代码段:

if(Build.VERSION.SDK_INT>=21)

      这是因为安卓5以上不再支持直接new一个SoundPool的方法来创建soundpool池,而是提供了利用SoundPool.Builedr以及

AudioAttributes.Builder来创建,如下:

AudioAttributes abs = new AudioAttributes.Builder()
	                .setUsage(AudioAttributes.USAGE_MEDIA)
	                .setContentType(AudioAttributes.CONTENT_TYPE_MUSIC)
	                .build() ;
soundPool=new SoundPool.Builder()
			.setMaxStreams(5)
			.setAudioAttributes(abs)
			.build();	//创建一个SoundPool对象,该对象可以容纳5个音频流

2、MainActivity的代码:


package com.example.myexplorer;

import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

import com.example.myexplorer.R;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Intent;
import android.media.AudioManager;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.view.Window;
import android.webkit.DownloadListener;
import android.webkit.WebChromeClient;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.ProgressBar;
import android.widget.Toast;

@SuppressLint({ "InlinedApi", "ClickableViewAccessibility", "SetJavaScriptEnabled" })
public class MainActivity extends Activity implements OnTouchListener{

	private WebView webView;
	int width,height,keyBack=0;
	View decorView;
	Thread thread;
	
	private ThreadPoolExecutor poolExecutor;
	
	SoundPoolManager soundPoolManager;     //获取音频播放管理器
	String[] musicName= {"music","music1","music3"};//定义一个String数组来存放需要加载的音乐的名称
	float Y;
	private float downX,downY;
    private ProgressBar pg1;  
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		this.requestWindowFeature(Window.FEATURE_NO_TITLE);//隐藏标题
		setContentView(R.layout.activity_main);
		/*
		 * 初始化控件
		*/
		webView=(WebView)findViewById(R.id.webview);  //实例化一个webview浏览组件
		pg1=(ProgressBar) findViewById(R.id.progressbar); 
		soundPoolManager=new SoundPoolManager(this);  //实例化音频管理器
		 // 获得decorView
        decorView = getWindow().getDecorView();
        webView.setOnTouchListener(this);         //为webview添加触摸事件监控
        // 获得手机屏幕的宽度和高度,单位像素
        DisplayMetrics metrics = new DisplayMetrics();
        getWindowManager().getDefaultDisplay().getMetrics(metrics);
        width = metrics.widthPixels;
        height = metrics.heightPixels;
        creatMyWebView(webView);                      //创建currentWebView
		webView.loadUrl("https://w.heiyan.com/");     //传递需要加载的网页	
		//从线程池中拿出一个线程来播放音乐,线程池具体额参数如下
		/*
		 * public ThreadPoolExecutor(  
//核心线程数,除非allowCoreThreadTimeOut被设置为true,否则它闲着也不会死  
int corePoolSize,   
//最大线程数,活动线程数量超过它,后续任务就会排队                     
int maximumPoolSize,   
//超时时长,作用于非核心线程(allowCoreThreadTimeOut被设置为true时也会同时作用于核心线程),闲置超时便被回收             
long keepAliveTime,                            
//枚举类型,设置keepAliveTime的单位,有TimeUnit.MILLISECONDS(ms)、TimeUnit. SECONDS(s)等  
TimeUnit unit,  
//缓冲任务队列,线程池的execute方法会将Runnable对象存储起来  
BlockingQueue<Runnable> workQueue,  
//线程工厂接口,只有一个new Thread(Runnable r)方法,可为线程池创建新线程  
ThreadFactory threadFactory)  
		 */
		poolExecutor = new ThreadPoolExecutor(3, 5,  
                1, TimeUnit.SECONDS, new LinkedBlockingDeque<Runnable>(128));  
		Runnable runnable1=new Runnable() {
				
			@Override
			public void run() {
				// TODO Auto-generated method stub
				//开启音频播放
				Log.i("Thread","start");
				soundPoolManager.creatSounPool(3, AudioManager.STREAM_MUSIC, 0);
				soundPoolManager.load(musicName,1 );
				//soundPoolManager.play(1, 1, 5, 0, 1);
				try {
					Thread.sleep(10000);
					handler2.post(runnable2);
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		};
		poolExecutor.execute(runnable1);    //开启线程
		
		/*
		 * 开启一个新线程,定时置keyBack为0
		 */
		new Thread(new Runnable() {
			
			@Override
			public void run() {
				// TODO Auto-generated method stub
				handler.post(runnable);//启动计时器,每一秒执行一次runnable. 
			}
		}).start();
	}
	/*
	* 创建一个handler对象并重写runnable的run方法,实现,当线程启动时,自动启动消息推送
	*/	
	Handler handler=new Handler();  
	Runnable runnable=new Runnable() {  
	    @Override  
	    public void run() {  
	        // TODO Auto-generated method stub  
			//当线程不没有被中断,重复执行消息推送
			keyBack=0;
	        handler.postDelayed(runnable, 5000);      //自身调用自身,陷入2秒的定时循环
	    }  
	};  	
	
	/*
	* 创建一个handler对象并重写runnable的run方法,实现,当线程启动时,每0-20秒随机播放
	*/	
	Handler handler2=new Handler();  
	Runnable runnable2=new Runnable() {  
	    @Override  
	    public void run() {  
	        // TODO Auto-generated method stub  
			//当线程不没有被中断,重复执行消息推送
			soundPoolManager.play(1, 1, 0, 0, 1);
			Log.i("AtTime","successfull");
	        handler2.postDelayed(runnable2, (int)(Math.random()*20+5)*1000);//自身调用自身,陷入2秒的定时循环
	    }  
	};  
	@SuppressLint("NewApi")
	public void creatMyWebView(WebView w) {
		//加入下载监听器,用于用户第一次支付时下载插件用
        w.setDownloadListener(new MyWebViewDownLoadListener());  
		w.setWebViewClient(new WebViewClient(){  
	        @Override  
	        public boolean shouldOverrideUrlLoading(WebView view, String url) {  
	            if( url.startsWith("http:") || url.startsWith("https:") ) {  
	                return false;  
	            }  
	  
	            // Otherwise allow the OS to handle things like tel, mailto, etc.  
	            Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));  
	            startActivity( intent );  
	            return true;  
	        }  
	    });  
		//支持JS
        WebSettings settings = w.getSettings();
        settings.setJavaScriptEnabled(true);
        w.setWebChromeClient(new WebChromeClient(){  //辅助WebView处理Javascript的对话框,网站图标,网站title,加载进度等 
            @Override  
            public void onProgressChanged(WebView view, int newProgress) {  
                // TODO 自动生成的方法存根  
                  
                if(newProgress==100){  
                    pg1.setVisibility(View.GONE);//加载完网页进度条消失  
                }  
                else{  
                    pg1.setVisibility(View.VISIBLE);//显示进度条  
                    pg1.setProgress(newProgress);//设置进度值  
                }  
                  
            }  
        });  
        
       //设置webview提供的各个属性
        
        w.getSettings().setUseWideViewPort(true);//设置此属性,可任意比例缩放。
        w.getSettings().setSupportZoom(true);    //允许组件具有放大和缩小功能
        w.getSettings().setBuiltInZoomControls(true);
		//不显示webview缩放按钮
        settings.setDisplayZoomControls(false);
	}
	
	/*
	 * 下载监听内部类的定义
	 */
	private class MyWebViewDownLoadListener implements DownloadListener{  
		//添加监听事件即可  
		public void onDownloadStart(String url, String userAgent, String contentDisposition,  
		    String mimetype,long contentLength)          {  
		             Uri uri = Uri.parse(url);  
		             Intent intent = new Intent(Intent.ACTION_VIEW, uri);  
		             startActivity(intent);  
		         }  
		     }
/*
 * 设置触摸监控事件
 */
	@Override
    public boolean onTouch(View v,MotionEvent event) {
        if(event.getAction() == MotionEvent.ACTION_DOWN){// 当按下时
            // 获得按下时的X坐标
            downX = event.getX();
            downY=event.getY();
        }else if(event.getAction() == MotionEvent.ACTION_MOVE){// 当手指滑动时
            // 获得滑过的距离
            float rightmoveDistanceX = event.getX() - downX;
            float leftmoveDistanceX = downX-event.getX()  ;
            Y=Math.abs(event.getY()-downY);
            if(rightmoveDistanceX > width/5 && Y<height/7){// 如果是向右滑动
            	webView.setX(rightmoveDistanceX); // 设置界面的X到滑动到的位置
            	try {
					Thread.sleep(10);
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
            	//webView.setY(0);                   //固定住此时webview的Y
            }
            else if(leftmoveDistanceX > width/5 && Y<height/7) {
            	webView.setX(-leftmoveDistanceX); // 设置界面的X到滑动到的位置
            	//webView.setY(0);                   //固定住此时webview的Y
            	try {
				Thread.sleep(50);
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
            }

        }else if(event.getAction() == MotionEvent.ACTION_UP){// 当抬起手指时
            // 获得滑过的距离
            float moveDistanceX = event.getX() - downX;
            float leftmoveDistanceX= downX-event.getX() ;
            if(moveDistanceX > width*2 / 8 && Y<height/7){
                 // 如果滑动的距离超过了手机屏幕的一半, 结束当前Activity
                if(webView.canGoBack()) {   //如果能够后退则后退操作,如果不行,则提示
            	webView.goBack();
            	webView.setX(0); // 设置界面的X到初始位置
                }
                else {
                	Toast.makeText(MainActivity.this, "没有上一页了",
                			Toast.LENGTH_SHORT).show();
                	webView.setX(0); // 设置界面的X到初始位置
                }
            }else if(leftmoveDistanceX>width*2/8 && Y<height/7) {
            	 if(webView.canGoForward()) {   //如果能够后退则后退操作,如果不行,则提示
                 	webView.goForward();
                 	webView.setX(0); // 设置界面的X到初始位置
                     }
                     else 
                    	 {
                    	 Toast.makeText(MainActivity.this, "没有下一页了",
                    			 Toast.LENGTH_SHORT).show();
                    	 webView.setX(0); // 设置界面的X到初始位置
                    	 }
            }
            else{ // 如果滑动距离没有超过一半
                // 恢复初始状态
            	webView.setX(0);
            }
        }
        return false;
    }

	/*
	 * 进入沉浸模式,即自动隐藏状态栏以及导航栏
	 * @see android.app.Activity#onWindowFocusChanged(boolean)
	 */
	 @Override
	    public void onWindowFocusChanged(boolean hasFocus) {              //进入沉浸模式,即自动隐藏状态栏以及导航栏
	        super.onWindowFocusChanged(hasFocus);
	        //判断是否有焦点
	        if(hasFocus && Build.VERSION.SDK_INT >= 19){
	            View decorView = getWindow().getDecorView();
	            decorView.setSystemUiVisibility(
	                    View.SYSTEM_UI_FLAG_LAYOUT_STABLE
	                    |View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
	                    |View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
	                    |View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
	                    |View.SYSTEM_UI_FLAG_FULLSCREEN
	                    |View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
	            );

	        }
	    }
	 /*
	  * 设置后退键连按两次退出
	  * @see android.app.Activity#onKeyDown(int, android.view.KeyEvent)
	  */
	 @Override
	 public boolean onKeyDown(int keyCode,KeyEvent event) {
		 if(keyCode==KeyEvent.KEYCODE_BACK)
			 {
			 keyBack++;
			 if(keyBack==1) {
			 Toast.makeText(MainActivity.this, "再按一次退出", Toast.LENGTH_SHORT).show();
			 Log.i("keyBack","1");
			 }
			 else if(keyBack==2)
			  finish();
			 }
		 return true;
	 }
	 
	 @Override
		public void onDestroy() {
			//soundPoolManager.soundPool.release();
			super.onDestroy();
		}
}

3、MediaPlayer的代码

package com.example.myexplorer;
import android.content.Context;
import android.media.MediaPlayer;
import android.util.Log;

public class mediaplayer {

	Context context;
	MediaPlayer myMediaPlayer;
	public mediaplayer(Context context) {
		this.context=context;
	}
	protected void creatMediaPlayer() {
		Log.i("Creat","begin");
		//通过mediaPlayer的静态方法creat创建一个MediaPlayer对象
		myMediaPlayer=MediaPlayer.create(context,
				context.getResources().getIdentifier(
						"com.example.myexplorer:raw/background_music", null, null));
		
		//(com.example.myexplorer.R.raw.background_music));
		Log.i("Creat","successfull");
	}
	protected void play() {
		try {
			//myMediaPlayer.prepare();   //准备并加载音频
			myMediaPlayer.start();     //开始播放音频
			Log.i("play","successfull");
		} catch (IllegalStateException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} 
	}
	protected void stop() {
		myMediaPlayer.stop();
	}
	protected void pause() {
		myMediaPlayer.pause();
	}
	protected void release() {
		myMediaPlayer.release();
	}
}

欢迎界面WelcomeActivity的代码:

package com.example.myexplorer;
import android.app.Activity;
import android.content.Intent;
import android.graphics.drawable.AnimationDrawable;
import android.os.Build;
import android.os.Bundle;
import android.view.View;
import android.view.Window;
import android.widget.LinearLayout;

public class welcomeActivity extends Activity {

	private AnimationDrawable ad;
	private LinearLayout ll;
	mediaplayer musicPlayer;
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		this.requestWindowFeature(Window.FEATURE_NO_TITLE);//隐藏标题
		setContentView(R.layout.welcome);
		ll=(LinearLayout)findViewById(R.id.ll);
		ad=(AnimationDrawable)ll.getBackground();
		musicPlayer=new mediaplayer(this);
		musicPlayer.creatMediaPlayer();   //创建一个播放器
		musicPlayer.play();                  //开始播放
		ad.start();
		new Thread(new Runnable() {
			
			@Override
			public void run() {
				// TODO Auto-generated method stub
				try {
					Thread.sleep(3000);
					Intent intent =new Intent(welcomeActivity.this,MainActivity.class);
					startActivity(intent);
					musicPlayer.stop();
				    musicPlayer.release();
					finish();
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				
			}
		}).start();
	}
	/*
	 * 进入沉浸模式,即自动隐藏状态栏以及导航栏
	 * @see android.app.Activity#onWindowFocusChanged(boolean)
	 */
	 @Override
	    public void onWindowFocusChanged(boolean hasFocus) {              //进入沉浸模式,即自动隐藏状态栏以及导航栏
	        super.onWindowFocusChanged(hasFocus);
	        //判断是否有焦点
	        if(hasFocus && Build.VERSION.SDK_INT >= 19){
	            View decorView = getWindow().getDecorView();
	            decorView.setSystemUiVisibility(
	                    View.SYSTEM_UI_FLAG_LAYOUT_STABLE
	                    |View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
	                    |View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
	                    |View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
	                    |View.SYSTEM_UI_FLAG_FULLSCREEN
	                    |View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
	            );

	        }
	    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值