工具:android studio
使用android 播放视频,一开始是使用的 vitamio 的,人家的代码写得特别好,可惜我是在android studio里调用的,哎呀,各种报错,什么R文件不识别啦,Gradle 版本的问题,无奈网上可以找到的资料实在是有限,我还傻傻的配置了NDK 的环境,可以也是没有用。
后来使用优酷的 SDK 代码,参考:http://blog.csdn.net/elsdnwn/article/details/44984011
优酷:http://cloud.youku.com/app
按照介绍一步一步试咯 我下载的是精简版
android studio AIDL文件与java的关联和Eclipse是不一样的,studio需要手动在main\下新建aidl文件夹,将.aidl文件复制过来
Android Studio实现Service AIDL http://www.linuxidc.com/Linux/2015-01/111148.htm
经历了很多次的失败,什么复制文件啦,整体文件复制,包名都一样, 删掉工程重建一个,一个文件一个文件复制,drawable里的文件全部复制,可是还是会报错,
这里要说一下 直接 新建module -> android library 因为youkupalyersdk 是作为类库使用的,不需要生成apk
最后发现一个方法(亲测可行):
首先下载优酷提供的sdk http://cloud.youku.com/down
在Android Studio中新建一个工程名 xxx ,再把 YoukuPlayerOpenSDK 以模块的形式导入到新建的工程当中,接着将YoukuPlayerOpenSDK模块下的build.gradle文件中的compileSdkVersion、buildToolsVersion、minSdkVersion和targetSdkVersion都修改成跟app模块下的build.gradle相应字段一样的数据。
哎,这么简单的方法,在android studio 里直接使用开源的SDK
然后,就可以飞啦
不过优酷的有一个限制就是只可以播放优酷库里的视频,可以根据视频的网络地址,获取网页的数据得到视频的id
于是继续使用vitamio ,由于有了上面的经验,一个浪费了很长时间得到的经验,这个只要不涉及到修改别人的源码,开发就很快
首先是 到Vitamio的Github地址 https://github.com/yixia/VitamioBundle下载SDK
先是做一个读取sd卡里的视频(读取本地文件)的播放器,这个是有参考的
扫描SD卡的文件
private void scanMovieFiles() { fileList = new ArrayList<String>(); fileListPath = new ArrayList<String>(); //要获取SD卡首先要确认SD卡是否装载 if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) { Log.e(TAG, "SD Card not mounted."); } //获取sd卡上所有的文件 final File[] file = Environment.getExternalStorageDirectory().listFiles(); readFile(file); files = fileList.toArray(new String[1]); filesPath = fileListPath.toArray(new String[1]); } /*读取视频文件 会处理 fileList 和 fileListPath */ private void readFile(final File[] file) { for (int i = 0; (file != null) && (i < file.length); i++) { if (file[i].isFile() && (file[i].getName().endsWith("mp4") || file[i].getName().endsWith("mkv") || file[i].getName().endsWith("MP4") || file[i].getName().endsWith("MKV") || file[i].getName().endsWith("avi") || file[i].getName().endsWith("AVI") || file[i].getName().endsWith("rmvb") || file[i].getName().endsWith("RMVB"))) { fileList.add(file[i].getName()); fileListPath.add(file[i].getPath()); } else if (file[i].isDirectory()) { //如果是文件夹,递归读取 final File[] tempFileList = new File(file[i].getAbsolutePath()).listFiles(); readFile(tempFileList); } } }还添加了播放时手势控制,双击暂定/播放,左右滑动开尽快退,上下滑动调音量
private GestureDetector gestureDetector; /*最大声音*/ private int maxVolume; /*当前声音*/ private int currentVolume = -1; /**/ @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); /* * 去屏保 * */ getWindow().setFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON, WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); videoView = (VideoView) this.findViewById(R.id.surface_view); if (!movieUrl.isEmpty()) { if (movieUrl.startsWith("http:")) { videoView.setVideoURI(Uri.parse(movieUrl)); } else { videoView.setVideoPath(movieUrl); } //设置成撑满全屏 videoView.setVideoLayout(VideoView.VIDEO_LAYOUT_STRETCH, 0); videoView.setMediaController(mediaController); videoView.requestFocus(); videoView.setOnPreparedListener(new MediaPlayer.OnPreparedListener() { @Override public void onPrepared(MediaPlayer mp) { mp.setPlaybackSpeed(1.0f); duration = mp.getDuration(); } }); gestureDetector = new GestureDetector(this, new CustomGestureListener()); } @Override public boolean onTouchEvent(MotionEvent event) { if (gestureDetector.onTouchEvent(event)) { return true; } switch (event.getAction() & MotionEvent.ACTION_MASK) { case MotionEvent.ACTION_UP: endGesture(); break; } return super.onTouchEvent(event); } private void endGesture() { currentVolume = -1; mDismissHandler.removeMessages(0); mDismissHandler.sendEmptyMessageDelayed(0, 500); } private class CustomGestureListener extends GestureDetector.SimpleOnGestureListener { /* * 双击操作,开始和暂停 * */ /** * 这个方法不同于onSingleTapUp,他是在GestureDetector确信用户在第一次触摸屏幕后,没有紧跟着第二次触摸屏幕,也就是不是“双击”的时候触发 * */ @Override public boolean onDoubleTap(MotionEvent e) { if (videoView.isPlaying()) { videoView.pause(); } else { videoView.start(); } return super.onDoubleTap(e); } /** * @param e1 The first down motion event that started the scrolling. @param e2 The move motion event that triggered the current onScroll. @param distanceX The distance along the X axis(轴) that has been scrolled since the last call to onScroll. This is NOT the distance between e1 and e2. @param distanceY The distance along the Y axis that has been scrolled since the last call to onScroll. This is NOT the distance between e1 and e2. 无论是用手拖动view,或者是以抛的动作滚动,都会多次触发 ,这个方法在ACTION_MOVE动作发生时就会触发 参看GestureDetector的onTouchEvent方法源码 * */ @Override public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { //上下滑动 if (Math.abs(distanceY) / Math.abs(distanceX) > 3) { float mOldY = e1.getY(); int y = (int) e2.getRawY(); Display disp = getWindowManager().getDefaultDisplay(); int windowHeight = disp.getHeight(); onVolumeSlide((mOldY - y) / windowHeight); } return super.onScroll(e1, e2, distanceX, distanceY); } /* * 滑动操作 * */ /** * @param e1 第1个ACTION_DOWN MotionEvent 并且只有一个 * @param e2 最后一个ACTION_MOVE MotionEvent * @param velocityX X轴上的移动速度,像素/秒 * @param velocityY Y轴上的移动速度,像素/秒 * 这个方法发生在ACTION_UP时才会触发 参看GestureDetector的onTouchEvent方法源码 * * */ @Override public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { currentPosition = videoView.getCurrentPosition(); /*向左滑*/ if (e1.getX() - e2.getX() > 120) { if (currentPosition < 10000) { currentPosition = 0; videoView.seekTo(currentPosition); } else { videoView.seekTo(currentPosition - 10000); } } else if (e2.getX() - e1.getX() > 120) { /*向右滑*/ if (currentPosition + 10000 > duration) { currentPosition = duration; videoView.seekTo(currentPosition); } else { videoView.seekTo(currentPosition + 10000); } } return super.onFling(e1, e2, velocityX, velocityY); } } /* * 定时隐藏 * */ private Handler mDismissHandler = new Handler() { @Override public void handleMessage(Message msg) { mVolumeBrightnessLayout.setVisibility(View.GONE); } }; /** * 滑动改变声音大小 */ private void onVolumeSlide(float percent) { if (currentVolume == -1) { currentVolume = audioManager.getStreamVolume(AudioManager.STREAM_MUSIC); if (currentVolume < 0) currentVolume = 0; // 显示 mOperationBg.setImageResource(R.drawable.video_volumn_bg); mVolumeBrightnessLayout.setVisibility(View.VISIBLE); } int value = currentVolume + (int) (percent * maxVolume); if (value > maxVolume) { value = maxVolume; } else if (value < 0) { value = 0; } // 变更声音 audioManager.setStreamVolume(AudioManager.STREAM_MUSIC, value, 0); // 变更进度条 ViewGroup.LayoutParams lp = mOperationPercent.getLayoutParams(); lp.width = findViewById(R.id.operation_full).getLayoutParams().width * value / maxVolume; mOperationPercent.setLayoutParams(lp); }都是官方提供好的方法,直接使用 它提供的VideoView和MediaController,通过手指滑动来控制音量大小则用的是FrameLayout。
播放界面布局:
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical"> <io.vov.vitamio.widget.VideoView android:id="@+id/surface_view" android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_centerHorizontal="true" android:layout_centerVertical="true" /> <FrameLayout android:id="@+id/operation_volume" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true" android:background="#00000000" android:orientation="horizontal" android:padding="0dip" android:visibility="invisible"> <ImageView android:id="@+id/operation_bg" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:src="@drawable/video_volumn_bg" /> <FrameLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="bottom|center_horizontal" android:paddingBottom="25dip"> <ImageView android:id="@+id/operation_full" android:layout_width="94dip" android:layout_height="wrap_content" android:layout_gravity="left" android:src="@drawable/video_num_bg" /> <ImageView android:id="@+id/operation_percent" android:layout_width="0dip" android:layout_height="wrap_content" android:layout_gravity="left" android:scaleType="matrix" android:src="@drawable/video_num_front" /> </FrameLayout> </FrameLayout> </RelativeLayout>附件:优 酷的源码http://download.csdn.net/detail/i_do_can/9410485
votamino的源码太大了