├── .classpath ├── .gitignore ├── .project ├── AndroidManifest.xml ├── LICENSE ├── README.md ├── assets └── online.xml ├── libs ├── android-support-v13.jar ├── ormlite-android-4.42-SNAPSHOT.jar ├── ormlite-core-4.42-SNAPSHOT.jar └── pinyin4j-2.5.0.jar ├── project.properties ├── res ├── anim │ ├── slide_in_bottom.xml │ ├── slide_in_top.xml │ ├── slide_out_bottom.xml │ └── slide_out_top.xml ├── drawable-hdpi │ ├── arrow_right.png │ ├── blackscreen.png │ ├── contact_list_scroll_normal.png │ ├── contact_list_scroll_pressed.png │ ├── default_thumbnail.png │ ├── fast_scroller_overlay.png │ ├── home_bg_checked.png │ ├── home_bg_normal.png │ ├── ic_line.png │ ├── icon.png │ ├── in_bubble.9.png │ ├── mediacontroller_bg.png │ ├── mediacontroller_pause01.png │ ├── mediacontroller_pause02.png │ ├── mediacontroller_play01.png │ ├── mediacontroller_play02.png │ ├── mediacontroller_seekbar01.png │ ├── mediacontroller_seekbar02.png │ ├── sd_bar_bg.9.png │ ├── toast_frame.9.png │ ├── video_back.png │ ├── video_brightness_bg.png │ ├── video_download.png │ ├── video_download_rate.png │ ├── video_file.png │ ├── video_more.png │ ├── video_num_bg.png │ ├── video_num_front.png │ ├── video_online.png │ └── video_volumn_bg.png ├── drawable-mdpi │ ├── down_btn_0.png │ ├── down_btn_1.png │ ├── down_btn_10.png │ ├── down_btn_2.png │ ├── down_btn_3.png │ ├── down_btn_4.png │ ├── down_btn_5.png │ ├── down_btn_6.png │ ├── down_btn_7.png │ ├── down_btn_8.png │ ├── down_btn_9.png │ ├── icon.png │ ├── logo_56.png │ ├── logo_cntv.png │ ├── logo_iqiyi.png │ ├── logo_letv.png │ ├── logo_pptv.png │ ├── logo_qq.png │ ├── logo_sina.png │ ├── logo_sohu.png │ ├── logo_tudou.png │ └── logo_youku.png ├── drawable-xhdpi │ ├── icon.png │ ├── mediacontroller_lock.png │ ├── mediacontroller_next.png │ ├── mediacontroller_pause.png │ ├── mediacontroller_play.png │ ├── mediacontroller_previous.png │ ├── mediacontroller_screen_fit.png │ ├── mediacontroller_screen_size.png │ ├── mediacontroller_snapshot.png │ ├── mediacontroller_sreen_size_100.png │ ├── mediacontroller_sreen_size_crop.png │ ├── mediacontroller_unlock.png │ ├── scrubber_control_disabled_holo.png │ ├── scrubber_control_focused_holo.png │ ├── scrubber_control_normal_holo.png │ ├── scrubber_control_pressed_holo.png │ ├── scrubber_primary_holo.9.png │ ├── scrubber_secondary_holo.9.png │ └── scrubber_track_holo_dark.9.png ├── drawable │ ├── alphabet_scroller_bg.xml │ ├── home_btn_bg.xml │ ├── icon.png │ ├── mediacontroller_btn_bg.xml │ ├── mediacontroller_pause_button.xml │ ├── mediacontroller_play_button.xml │ ├── mediacontroller_seekbar.xml │ ├── mediacontroller_seekbar_thumb.xml │ ├── scrubber_control_selector_holo.xml │ └── scrubber_progress_horizontal_holo_dark.xml ├── layout │ ├── activity_video.xml │ ├── brightness_volumn.xml │ ├── common_loading.xml │ ├── fragment_file.xml │ ├── fragment_file_item.xml │ ├── fragment_online.xml │ ├── fragment_online_item.xml │ ├── fragment_pager.xml │ ├── mediacontroller.xml │ ├── mediaplayer.xml │ ├── my_media_controller.xml │ └── videoview.xml ├── values-large │ └── dimens.xml ├── values-small │ └── dimens.xml ├── values-sw600dp │ └── dimens.xml ├── values-v11 │ └── styles.xml ├── values-v14 │ └── styles.xml ├── values-xlarge │ └── dimens.xml └── values │ ├── colors.xml │ ├── dimens.xml │ ├── strings.xml │ └── styles.xml └── src └── com └── nmbb └── oplayer ├── OPlayerApplication.java ├── OPreference.java ├── business └── FileBusiness.java ├── database ├── DbHelper.java └── SQLiteHelperOrm.java ├── exception └── Logger.java ├── po ├── OnlineVideo.java ├── PFile.java └── POMedia.java ├── preference └── PreferenceUtils.java ├── receiver └── MediaScannerReceiver.java ├── service ├── FileDownloadService.java └── MediaScannerService.java ├── ui ├── FragmentBase.java ├── FragmentFileOld.java ├── FragmentOnline.java ├── MainActivity.java ├── PlayerActivity.java ├── VideoPlayerActivity.java ├── adapter │ ├── FileAdapter.java │ └── FileDownloadAdapter.java ├── base │ ├── ArrayAdapter.java │ ├── FilterArrayAdapter.java │ └── ThreadPool.java ├── helper │ ├── FileDownloadHelper.java │ ├── VideoHelper.java │ └── XmlReaderHelper.java ├── player │ ├── CommonGestures.java │ ├── MediaController.java │ ├── PlayerService.java │ ├── VP.java │ ├── VideoActivity.java │ └── VideoView.java └── vitamio │ ├── InitActivity.java │ └── LibsChecker.java ├── util ├── ApplicationUtils.java ├── ArrayUtils.java ├── ConvertUtils.java ├── DeviceUtils.java ├── FileUtils.java ├── FractionalTouchDelegate.java ├── ImageUtils.java ├── IntentHelper.java ├── MediaUtils.java ├── PinyinUtils.java ├── StringUtils.java └── ToastUtils.java └── video └── VideoThumbnailUtils.java /.classpath: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # built application files 2 | *.apk 3 | *.ap_ 4 | 5 | # files for the dex VM 6 | *.dex 7 | 8 | # Java class files 9 | *.class 10 | 11 | # generated files 12 | bin/ 13 | gen/ 14 | 15 | # Local configuration file (sdk path, etc) 16 | local.properties 17 | 18 | -------------------------------------------------------------------------------- /.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | OPlayer 4 | 5 | 6 | 7 | 8 | 9 | com.android.ide.eclipse.adt.ResourceManagerBuilder 10 | 11 | 12 | 13 | 14 | com.android.ide.eclipse.adt.PreCompilerBuilder 15 | 16 | 17 | 18 | 19 | org.eclipse.jdt.core.javabuilder 20 | 21 | 22 | 23 | 24 | com.android.ide.eclipse.adt.ApkBuilder 25 | 26 | 27 | 28 | 29 | 30 | com.android.ide.eclipse.adt.AndroidNature 31 | org.eclipse.jdt.core.javanature 32 | 33 | 34 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/over140/OPlayer/315bc745fd96b1ecb9b7481e6705fc8fa192f0a3/LICENSE -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | OPlayer 2 | ======= 3 | 4 | Android平台基于Vitamio的开源播放器 5 | 6 | 支持以下协议的音频和视频播放: 7 | * MMS 8 | * RTSP (RTP, SDP) 9 | * HTTP流式传输(progressive streaming) 10 | * HTTP Live Streaming (M3U8), Android 2.1+ 11 | Vitamio集成了许多音频和视频的解码包,相比Android内置默认的媒体格式,这里列出其中的一些: 12 | * divx/xvid 13 | * wmv 14 | * flv 15 | * ts 16 | * rmvb 17 | * mkv 18 | * mov 19 | * m4v 20 | * avi 21 | * mp4 22 | * 3gp 23 | 24 | == 25 | Vitamio官网: 26 | http://vitamio.org 27 | 28 | == 29 | 我的博客: 30 | http://www.cnblogs.com/over140/ 31 | 32 | == 33 | Vitamio系列文章: 34 | http://www.cnblogs.com/over140/category/409230.html 35 | 36 | == 37 | 依赖Vitamio,下载最新的Vitamio: 38 | https://github.com/yixia/VitamioBundle -------------------------------------------------------------------------------- /libs/android-support-v13.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/over140/OPlayer/315bc745fd96b1ecb9b7481e6705fc8fa192f0a3/libs/android-support-v13.jar -------------------------------------------------------------------------------- /libs/ormlite-android-4.42-SNAPSHOT.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/over140/OPlayer/315bc745fd96b1ecb9b7481e6705fc8fa192f0a3/libs/ormlite-android-4.42-SNAPSHOT.jar -------------------------------------------------------------------------------- /libs/ormlite-core-4.42-SNAPSHOT.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/over140/OPlayer/315bc745fd96b1ecb9b7481e6705fc8fa192f0a3/libs/ormlite-core-4.42-SNAPSHOT.jar -------------------------------------------------------------------------------- /libs/pinyin4j-2.5.0.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/over140/OPlayer/315bc745fd96b1ecb9b7481e6705fc8fa192f0a3/libs/pinyin4j-2.5.0.jar -------------------------------------------------------------------------------- /project.properties: -------------------------------------------------------------------------------- 1 | # This file is automatically generated by Android Tools. 2 | # Do not modify this file -- YOUR CHANGES WILL BE ERASED! 3 | # 4 | # This file must be checked in Version Control Systems. 5 | # 6 | # To customize properties used by the Ant build system use, 7 | # "ant.properties", and override values to adapt the script to your 8 | # project structure. 9 | 10 | # Project target. 11 | target=android-17 12 | android.library.reference.1=../VitamioBundle 13 | -------------------------------------------------------------------------------- /res/anim/slide_in_bottom.xml: -------------------------------------------------------------------------------- 1 | 2 | 13 | 14 | 15 | 16 | 20 | 21 | 25 | 26 | -------------------------------------------------------------------------------- /res/anim/slide_in_top.xml: -------------------------------------------------------------------------------- 1 | 2 | 13 | 14 | 15 | 16 | 20 | 21 | 25 | 26 | -------------------------------------------------------------------------------- /res/anim/slide_out_bottom.xml: -------------------------------------------------------------------------------- 1 | 2 | 13 | 14 | 15 | 16 | 20 | 21 | 25 | 26 | -------------------------------------------------------------------------------- /res/anim/slide_out_top.xml: -------------------------------------------------------------------------------- 1 | 2 | 13 | 14 | 15 | 16 | 20 | 21 | 25 | 26 | -------------------------------------------------------------------------------- /res/drawable-hdpi/arrow_right.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/over140/OPlayer/315bc745fd96b1ecb9b7481e6705fc8fa192f0a3/res/drawable-hdpi/arrow_right.png -------------------------------------------------------------------------------- /res/drawable-hdpi/blackscreen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/over140/OPlayer/315bc745fd96b1ecb9b7481e6705fc8fa192f0a3/res/drawable-hdpi/blackscreen.png -------------------------------------------------------------------------------- /res/drawable-hdpi/contact_list_scroll_normal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/over140/OPlayer/315bc745fd96b1ecb9b7481e6705fc8fa192f0a3/res/drawable-hdpi/contact_list_scroll_normal.png -------------------------------------------------------------------------------- /res/drawable-hdpi/contact_list_scroll_pressed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/over140/OPlayer/315bc745fd96b1ecb9b7481e6705fc8fa192f0a3/res/drawable-hdpi/contact_list_scroll_pressed.png -------------------------------------------------------------------------------- /res/drawable-hdpi/default_thumbnail.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/over140/OPlayer/315bc745fd96b1ecb9b7481e6705fc8fa192f0a3/res/drawable-hdpi/default_thumbnail.png -------------------------------------------------------------------------------- /res/drawable-hdpi/fast_scroller_overlay.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/over140/OPlayer/315bc745fd96b1ecb9b7481e6705fc8fa192f0a3/res/drawable-hdpi/fast_scroller_overlay.png -------------------------------------------------------------------------------- /res/drawable-hdpi/home_bg_checked.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/over140/OPlayer/315bc745fd96b1ecb9b7481e6705fc8fa192f0a3/res/drawable-hdpi/home_bg_checked.png -------------------------------------------------------------------------------- /res/drawable-hdpi/home_bg_normal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/over140/OPlayer/315bc745fd96b1ecb9b7481e6705fc8fa192f0a3/res/drawable-hdpi/home_bg_normal.png -------------------------------------------------------------------------------- /res/drawable-hdpi/ic_line.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/over140/OPlayer/315bc745fd96b1ecb9b7481e6705fc8fa192f0a3/res/drawable-hdpi/ic_line.png -------------------------------------------------------------------------------- /res/drawable-hdpi/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/over140/OPlayer/315bc745fd96b1ecb9b7481e6705fc8fa192f0a3/res/drawable-hdpi/icon.png -------------------------------------------------------------------------------- /res/drawable-hdpi/in_bubble.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/over140/OPlayer/315bc745fd96b1ecb9b7481e6705fc8fa192f0a3/res/drawable-hdpi/in_bubble.9.png -------------------------------------------------------------------------------- /res/drawable-hdpi/mediacontroller_bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/over140/OPlayer/315bc745fd96b1ecb9b7481e6705fc8fa192f0a3/res/drawable-hdpi/mediacontroller_bg.png -------------------------------------------------------------------------------- /res/drawable-hdpi/mediacontroller_pause01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/over140/OPlayer/315bc745fd96b1ecb9b7481e6705fc8fa192f0a3/res/drawable-hdpi/mediacontroller_pause01.png -------------------------------------------------------------------------------- /res/drawable-hdpi/mediacontroller_pause02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/over140/OPlayer/315bc745fd96b1ecb9b7481e6705fc8fa192f0a3/res/drawable-hdpi/mediacontroller_pause02.png -------------------------------------------------------------------------------- /res/drawable-hdpi/mediacontroller_play01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/over140/OPlayer/315bc745fd96b1ecb9b7481e6705fc8fa192f0a3/res/drawable-hdpi/mediacontroller_play01.png -------------------------------------------------------------------------------- /res/drawable-hdpi/mediacontroller_play02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/over140/OPlayer/315bc745fd96b1ecb9b7481e6705fc8fa192f0a3/res/drawable-hdpi/mediacontroller_play02.png -------------------------------------------------------------------------------- /res/drawable-hdpi/mediacontroller_seekbar01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/over140/OPlayer/315bc745fd96b1ecb9b7481e6705fc8fa192f0a3/res/drawable-hdpi/mediacontroller_seekbar01.png -------------------------------------------------------------------------------- /res/drawable-hdpi/mediacontroller_seekbar02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/over140/OPlayer/315bc745fd96b1ecb9b7481e6705fc8fa192f0a3/res/drawable-hdpi/mediacontroller_seekbar02.png -------------------------------------------------------------------------------- /res/drawable-hdpi/sd_bar_bg.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/over140/OPlayer/315bc745fd96b1ecb9b7481e6705fc8fa192f0a3/res/drawable-hdpi/sd_bar_bg.9.png -------------------------------------------------------------------------------- /res/drawable-hdpi/toast_frame.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/over140/OPlayer/315bc745fd96b1ecb9b7481e6705fc8fa192f0a3/res/drawable-hdpi/toast_frame.9.png -------------------------------------------------------------------------------- /res/drawable-hdpi/video_back.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/over140/OPlayer/315bc745fd96b1ecb9b7481e6705fc8fa192f0a3/res/drawable-hdpi/video_back.png -------------------------------------------------------------------------------- /res/drawable-hdpi/video_brightness_bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/over140/OPlayer/315bc745fd96b1ecb9b7481e6705fc8fa192f0a3/res/drawable-hdpi/video_brightness_bg.png -------------------------------------------------------------------------------- /res/drawable-hdpi/video_download.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/over140/OPlayer/315bc745fd96b1ecb9b7481e6705fc8fa192f0a3/res/drawable-hdpi/video_download.png -------------------------------------------------------------------------------- /res/drawable-hdpi/video_download_rate.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/over140/OPlayer/315bc745fd96b1ecb9b7481e6705fc8fa192f0a3/res/drawable-hdpi/video_download_rate.png -------------------------------------------------------------------------------- /res/drawable-hdpi/video_file.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/over140/OPlayer/315bc745fd96b1ecb9b7481e6705fc8fa192f0a3/res/drawable-hdpi/video_file.png -------------------------------------------------------------------------------- /res/drawable-hdpi/video_more.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/over140/OPlayer/315bc745fd96b1ecb9b7481e6705fc8fa192f0a3/res/drawable-hdpi/video_more.png -------------------------------------------------------------------------------- /res/drawable-hdpi/video_num_bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/over140/OPlayer/315bc745fd96b1ecb9b7481e6705fc8fa192f0a3/res/drawable-hdpi/video_num_bg.png -------------------------------------------------------------------------------- /res/drawable-hdpi/video_num_front.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/over140/OPlayer/315bc745fd96b1ecb9b7481e6705fc8fa192f0a3/res/drawable-hdpi/video_num_front.png -------------------------------------------------------------------------------- /res/drawable-hdpi/video_online.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/over140/OPlayer/315bc745fd96b1ecb9b7481e6705fc8fa192f0a3/res/drawable-hdpi/video_online.png -------------------------------------------------------------------------------- /res/drawable-hdpi/video_volumn_bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/over140/OPlayer/315bc745fd96b1ecb9b7481e6705fc8fa192f0a3/res/drawable-hdpi/video_volumn_bg.png -------------------------------------------------------------------------------- /res/drawable-mdpi/down_btn_0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/over140/OPlayer/315bc745fd96b1ecb9b7481e6705fc8fa192f0a3/res/drawable-mdpi/down_btn_0.png -------------------------------------------------------------------------------- /res/drawable-mdpi/down_btn_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/over140/OPlayer/315bc745fd96b1ecb9b7481e6705fc8fa192f0a3/res/drawable-mdpi/down_btn_1.png -------------------------------------------------------------------------------- /res/drawable-mdpi/down_btn_10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/over140/OPlayer/315bc745fd96b1ecb9b7481e6705fc8fa192f0a3/res/drawable-mdpi/down_btn_10.png -------------------------------------------------------------------------------- /res/drawable-mdpi/down_btn_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/over140/OPlayer/315bc745fd96b1ecb9b7481e6705fc8fa192f0a3/res/drawable-mdpi/down_btn_2.png -------------------------------------------------------------------------------- /res/drawable-mdpi/down_btn_3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/over140/OPlayer/315bc745fd96b1ecb9b7481e6705fc8fa192f0a3/res/drawable-mdpi/down_btn_3.png -------------------------------------------------------------------------------- /res/drawable-mdpi/down_btn_4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/over140/OPlayer/315bc745fd96b1ecb9b7481e6705fc8fa192f0a3/res/drawable-mdpi/down_btn_4.png -------------------------------------------------------------------------------- /res/drawable-mdpi/down_btn_5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/over140/OPlayer/315bc745fd96b1ecb9b7481e6705fc8fa192f0a3/res/drawable-mdpi/down_btn_5.png -------------------------------------------------------------------------------- /res/drawable-mdpi/down_btn_6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/over140/OPlayer/315bc745fd96b1ecb9b7481e6705fc8fa192f0a3/res/drawable-mdpi/down_btn_6.png -------------------------------------------------------------------------------- /res/drawable-mdpi/down_btn_7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/over140/OPlayer/315bc745fd96b1ecb9b7481e6705fc8fa192f0a3/res/drawable-mdpi/down_btn_7.png -------------------------------------------------------------------------------- /res/drawable-mdpi/down_btn_8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/over140/OPlayer/315bc745fd96b1ecb9b7481e6705fc8fa192f0a3/res/drawable-mdpi/down_btn_8.png -------------------------------------------------------------------------------- /res/drawable-mdpi/down_btn_9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/over140/OPlayer/315bc745fd96b1ecb9b7481e6705fc8fa192f0a3/res/drawable-mdpi/down_btn_9.png -------------------------------------------------------------------------------- /res/drawable-mdpi/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/over140/OPlayer/315bc745fd96b1ecb9b7481e6705fc8fa192f0a3/res/drawable-mdpi/icon.png -------------------------------------------------------------------------------- /res/drawable-mdpi/logo_56.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/over140/OPlayer/315bc745fd96b1ecb9b7481e6705fc8fa192f0a3/res/drawable-mdpi/logo_56.png -------------------------------------------------------------------------------- /res/drawable-mdpi/logo_cntv.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/over140/OPlayer/315bc745fd96b1ecb9b7481e6705fc8fa192f0a3/res/drawable-mdpi/logo_cntv.png -------------------------------------------------------------------------------- /res/drawable-mdpi/logo_iqiyi.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/over140/OPlayer/315bc745fd96b1ecb9b7481e6705fc8fa192f0a3/res/drawable-mdpi/logo_iqiyi.png -------------------------------------------------------------------------------- /res/drawable-mdpi/logo_letv.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/over140/OPlayer/315bc745fd96b1ecb9b7481e6705fc8fa192f0a3/res/drawable-mdpi/logo_letv.png -------------------------------------------------------------------------------- /res/drawable-mdpi/logo_pptv.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/over140/OPlayer/315bc745fd96b1ecb9b7481e6705fc8fa192f0a3/res/drawable-mdpi/logo_pptv.png -------------------------------------------------------------------------------- /res/drawable-mdpi/logo_qq.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/over140/OPlayer/315bc745fd96b1ecb9b7481e6705fc8fa192f0a3/res/drawable-mdpi/logo_qq.png -------------------------------------------------------------------------------- /res/drawable-mdpi/logo_sina.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/over140/OPlayer/315bc745fd96b1ecb9b7481e6705fc8fa192f0a3/res/drawable-mdpi/logo_sina.png -------------------------------------------------------------------------------- /res/drawable-mdpi/logo_sohu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/over140/OPlayer/315bc745fd96b1ecb9b7481e6705fc8fa192f0a3/res/drawable-mdpi/logo_sohu.png -------------------------------------------------------------------------------- /res/drawable-mdpi/logo_tudou.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/over140/OPlayer/315bc745fd96b1ecb9b7481e6705fc8fa192f0a3/res/drawable-mdpi/logo_tudou.png -------------------------------------------------------------------------------- /res/drawable-mdpi/logo_youku.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/over140/OPlayer/315bc745fd96b1ecb9b7481e6705fc8fa192f0a3/res/drawable-mdpi/logo_youku.png -------------------------------------------------------------------------------- /res/drawable-xhdpi/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/over140/OPlayer/315bc745fd96b1ecb9b7481e6705fc8fa192f0a3/res/drawable-xhdpi/icon.png -------------------------------------------------------------------------------- /res/drawable-xhdpi/mediacontroller_lock.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/over140/OPlayer/315bc745fd96b1ecb9b7481e6705fc8fa192f0a3/res/drawable-xhdpi/mediacontroller_lock.png -------------------------------------------------------------------------------- /res/drawable-xhdpi/mediacontroller_next.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/over140/OPlayer/315bc745fd96b1ecb9b7481e6705fc8fa192f0a3/res/drawable-xhdpi/mediacontroller_next.png -------------------------------------------------------------------------------- /res/drawable-xhdpi/mediacontroller_pause.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/over140/OPlayer/315bc745fd96b1ecb9b7481e6705fc8fa192f0a3/res/drawable-xhdpi/mediacontroller_pause.png -------------------------------------------------------------------------------- /res/drawable-xhdpi/mediacontroller_play.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/over140/OPlayer/315bc745fd96b1ecb9b7481e6705fc8fa192f0a3/res/drawable-xhdpi/mediacontroller_play.png -------------------------------------------------------------------------------- /res/drawable-xhdpi/mediacontroller_previous.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/over140/OPlayer/315bc745fd96b1ecb9b7481e6705fc8fa192f0a3/res/drawable-xhdpi/mediacontroller_previous.png -------------------------------------------------------------------------------- /res/drawable-xhdpi/mediacontroller_screen_fit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/over140/OPlayer/315bc745fd96b1ecb9b7481e6705fc8fa192f0a3/res/drawable-xhdpi/mediacontroller_screen_fit.png -------------------------------------------------------------------------------- /res/drawable-xhdpi/mediacontroller_screen_size.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/over140/OPlayer/315bc745fd96b1ecb9b7481e6705fc8fa192f0a3/res/drawable-xhdpi/mediacontroller_screen_size.png -------------------------------------------------------------------------------- /res/drawable-xhdpi/mediacontroller_snapshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/over140/OPlayer/315bc745fd96b1ecb9b7481e6705fc8fa192f0a3/res/drawable-xhdpi/mediacontroller_snapshot.png -------------------------------------------------------------------------------- /res/drawable-xhdpi/mediacontroller_sreen_size_100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/over140/OPlayer/315bc745fd96b1ecb9b7481e6705fc8fa192f0a3/res/drawable-xhdpi/mediacontroller_sreen_size_100.png -------------------------------------------------------------------------------- /res/drawable-xhdpi/mediacontroller_sreen_size_crop.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/over140/OPlayer/315bc745fd96b1ecb9b7481e6705fc8fa192f0a3/res/drawable-xhdpi/mediacontroller_sreen_size_crop.png -------------------------------------------------------------------------------- /res/drawable-xhdpi/mediacontroller_unlock.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/over140/OPlayer/315bc745fd96b1ecb9b7481e6705fc8fa192f0a3/res/drawable-xhdpi/mediacontroller_unlock.png -------------------------------------------------------------------------------- /res/drawable-xhdpi/scrubber_control_disabled_holo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/over140/OPlayer/315bc745fd96b1ecb9b7481e6705fc8fa192f0a3/res/drawable-xhdpi/scrubber_control_disabled_holo.png -------------------------------------------------------------------------------- /res/drawable-xhdpi/scrubber_control_focused_holo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/over140/OPlayer/315bc745fd96b1ecb9b7481e6705fc8fa192f0a3/res/drawable-xhdpi/scrubber_control_focused_holo.png -------------------------------------------------------------------------------- /res/drawable-xhdpi/scrubber_control_normal_holo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/over140/OPlayer/315bc745fd96b1ecb9b7481e6705fc8fa192f0a3/res/drawable-xhdpi/scrubber_control_normal_holo.png -------------------------------------------------------------------------------- /res/drawable-xhdpi/scrubber_control_pressed_holo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/over140/OPlayer/315bc745fd96b1ecb9b7481e6705fc8fa192f0a3/res/drawable-xhdpi/scrubber_control_pressed_holo.png -------------------------------------------------------------------------------- /res/drawable-xhdpi/scrubber_primary_holo.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/over140/OPlayer/315bc745fd96b1ecb9b7481e6705fc8fa192f0a3/res/drawable-xhdpi/scrubber_primary_holo.9.png -------------------------------------------------------------------------------- /res/drawable-xhdpi/scrubber_secondary_holo.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/over140/OPlayer/315bc745fd96b1ecb9b7481e6705fc8fa192f0a3/res/drawable-xhdpi/scrubber_secondary_holo.9.png -------------------------------------------------------------------------------- /res/drawable-xhdpi/scrubber_track_holo_dark.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/over140/OPlayer/315bc745fd96b1ecb9b7481e6705fc8fa192f0a3/res/drawable-xhdpi/scrubber_track_holo_dark.9.png -------------------------------------------------------------------------------- /res/drawable/alphabet_scroller_bg.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /res/drawable/home_btn_bg.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /res/drawable/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/over140/OPlayer/315bc745fd96b1ecb9b7481e6705fc8fa192f0a3/res/drawable/icon.png -------------------------------------------------------------------------------- /res/drawable/mediacontroller_btn_bg.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /res/drawable/mediacontroller_pause_button.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /res/drawable/mediacontroller_play_button.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /res/drawable/mediacontroller_seekbar.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 22 | 26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /res/drawable/mediacontroller_seekbar_thumb.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /res/drawable/scrubber_control_selector_holo.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 11 | 13 | 15 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /res/drawable/scrubber_progress_horizontal_holo_dark.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /res/layout/activity_video.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 15 | 16 | 20 | 21 | 27 | 28 | 35 | 41 | 42 | 52 | 53 | 54 | 60 | 61 | 74 | 75 | 83 | 84 | 85 | 86 | -------------------------------------------------------------------------------- /res/layout/brightness_volumn.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 15 | 16 | 21 | 22 | 28 | 29 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /res/layout/common_loading.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 13 | 14 | 18 | 19 | 24 | 25 | -------------------------------------------------------------------------------- /res/layout/fragment_file.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 18 | 19 | 24 | 25 | 30 | 31 | 41 | 42 | 55 | 56 | 57 | 58 | 59 | 67 | 68 | 69 | 73 | 74 | 83 | 84 | 92 | 93 | 94 | -------------------------------------------------------------------------------- /res/layout/fragment_file_item.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 12 | 13 | 22 | 23 | 38 | 39 | 50 | 51 | 60 | 61 | -------------------------------------------------------------------------------- /res/layout/fragment_online.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 16 | 17 | 22 | 23 | 24 | 25 | 26 | 35 | 36 | -------------------------------------------------------------------------------- /res/layout/fragment_online_item.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 14 | 15 | 22 | 23 | 36 | 37 | -------------------------------------------------------------------------------- /res/layout/fragment_pager.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 11 | 14 | 15 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /res/layout/mediaplayer.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | -------------------------------------------------------------------------------- /res/layout/my_media_controller.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 12 | 16 | 18 | 21 | 25 | 26 | 27 | 31 | 32 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /res/layout/videoview.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 13 | 14 | 20 | 21 | 24 | 25 | 32 | 33 | 34 | 43 | 44 | 50 | 51 | 56 | 57 | 63 | 64 | 71 | 72 | 73 | 74 | -------------------------------------------------------------------------------- /res/values-large/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 48.0dip 4 | -------------------------------------------------------------------------------- /res/values-small/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 32.0dip 4 | -------------------------------------------------------------------------------- /res/values-sw600dp/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 56dp 5 | 8dp 6 | 2dp 7 | 8 | -------------------------------------------------------------------------------- /res/values-v11/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /res/values-v14/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | 11 | 12 | -------------------------------------------------------------------------------- /res/values-xlarge/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 64.0dip 5 | 56dp 6 | 7 | -------------------------------------------------------------------------------- /res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #ffffffff 4 | #ff000000 5 | #ff0000ff 6 | #ff00ff00 7 | #ffff0000 8 | #ff0078f0 9 | #ff7d7d7d 10 | #ffc3ddea 11 | #ffffcc00 12 | #ff274462 13 | #808080ff 14 | #00000000 15 | #ff53c1bd 16 | #99000000 17 | #f4f4f4 18 | 19 | -------------------------------------------------------------------------------- /res/values/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 16.0dip 5 | 15.0dip 6 | 18.0dip 7 | 14.0dip 8 | 13.0dip 9 | 30.0dip 10 | 49.0dip 11 | 40.0dip 12 | 48dp 13 | 32dp 14 | 2dp 15 | 0dp 16 | 17 | -------------------------------------------------------------------------------- /res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 开播视频 5 | 1.0 6 | 本地视频 7 | 在线视频 8 | 初始化播放器... 9 | 载入中,请稍后... 10 | 文件操作 11 | 重命名 12 | 重命名失败 13 | 文件已存在 14 | 删除 15 | 确定删除 (%s) ? 16 | 正在缓冲... 17 | VPlayer codec 18 | Cannot play video 19 | Sorry, this video is not valid for streaming to 20 | this device. 21 | 对不起,这个视频不能播放。 22 | OK 23 | Play/Pause 24 | 25 | 锁定 26 | 100% 27 | 全屏 28 | 拉伸 29 | 裁剪 30 | 屏幕已锁定 31 | 屏幕锁定已解除 32 | 缓冲: %.2f%% 33 | 对不起,这个视频不能播放。 34 | SD卡无法读取 35 | 截图存放在 %s. 36 | 截图失败 37 | 正在退出… 38 | 39 | 40 | -------------------------------------------------------------------------------- /res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 8 | 15 | 16 | 17 | 22 | 23 | 33 | 34 | 49 | 50 | 56 | 57 | 62 | 63 | 66 | 67 | 74 | 75 | 78 | 79 | 84 | 85 | -------------------------------------------------------------------------------- /src/com/nmbb/oplayer/OPlayerApplication.java: -------------------------------------------------------------------------------- 1 | package com.nmbb.oplayer; 2 | 3 | import android.app.Application; 4 | import android.content.Context; 5 | import android.os.Environment; 6 | 7 | import com.nmbb.oplayer.util.FileUtils; 8 | 9 | public class OPlayerApplication extends Application { 10 | 11 | private static OPlayerApplication mApplication; 12 | 13 | /** OPlayer SD卡缓存路径 */ 14 | public static final String OPLAYER_CACHE_BASE = Environment.getExternalStorageDirectory() + "/oplayer"; 15 | /** 视频截图缓冲路径 */ 16 | public static final String OPLAYER_VIDEO_THUMB = OPLAYER_CACHE_BASE + "/thumb/"; 17 | /** 首次扫描 */ 18 | public static final String PREF_KEY_FIRST = "application_first"; 19 | 20 | @Override 21 | public void onCreate() { 22 | super.onCreate(); 23 | mApplication = this; 24 | 25 | init(); 26 | } 27 | 28 | private void init() { 29 | //创建缓存目录 30 | FileUtils.createIfNoExists(OPLAYER_CACHE_BASE); 31 | FileUtils.createIfNoExists(OPLAYER_VIDEO_THUMB); 32 | } 33 | 34 | public static OPlayerApplication getApplication() { 35 | return mApplication; 36 | } 37 | 38 | public static Context getContext() { 39 | return mApplication; 40 | } 41 | 42 | /** 销毁 */ 43 | public void destory() { 44 | mApplication = null; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/com/nmbb/oplayer/OPreference.java: -------------------------------------------------------------------------------- 1 | package com.nmbb.oplayer; 2 | 3 | import java.util.Map.Entry; 4 | 5 | import android.content.ContentValues; 6 | import android.content.Context; 7 | import android.content.SharedPreferences; 8 | 9 | /** 存储系统设置 */ 10 | public class OPreference { 11 | 12 | private static final String PREFERENCE_NAME = "preference.db"; 13 | 14 | private SharedPreferences mPreference; 15 | 16 | public OPreference(Context ctx) { 17 | mPreference = ctx.getApplicationContext().getSharedPreferences(PREFERENCE_NAME, Context.MODE_PRIVATE); 18 | } 19 | 20 | public boolean putStringAndCommit(String key, String value) { 21 | return mPreference.edit().putString(key, value).commit(); 22 | } 23 | 24 | public boolean putIntAndCommit(String key, int value) { 25 | return mPreference.edit().putInt(key, value).commit(); 26 | } 27 | 28 | public boolean putBooleanAndCommit(String key, boolean value) { 29 | return mPreference.edit().putBoolean(key, value).commit(); 30 | } 31 | 32 | public boolean putIntAndCommit(ContentValues values) { 33 | SharedPreferences.Editor editor = mPreference.edit(); 34 | for (Entry value : values.valueSet()) { 35 | editor.putString(value.getKey(), value.getValue().toString()); 36 | } 37 | return editor.commit(); 38 | } 39 | 40 | public String getString(String key) { 41 | return getString(key, ""); 42 | } 43 | 44 | public String getString(String key, String defValue) { 45 | return mPreference.getString(key, defValue); 46 | } 47 | 48 | public int getInt(String key) { 49 | return getInt(key, -1); 50 | } 51 | 52 | public int getInt(String key, int defValue) { 53 | return mPreference.getInt(key, defValue); 54 | } 55 | 56 | public boolean getBoolean(String key) { 57 | return getBoolean(key, false); 58 | } 59 | 60 | public boolean getBoolean(String key, boolean defValue) { 61 | return mPreference.getBoolean(key, defValue); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/com/nmbb/oplayer/business/FileBusiness.java: -------------------------------------------------------------------------------- 1 | package com.nmbb.oplayer.business; 2 | 3 | import java.sql.SQLException; 4 | import java.util.ArrayList; 5 | import java.util.List; 6 | 7 | import com.j256.ormlite.dao.Dao; 8 | import com.j256.ormlite.stmt.QueryBuilder; 9 | import com.nmbb.oplayer.database.SQLiteHelperOrm; 10 | import com.nmbb.oplayer.exception.Logger; 11 | import com.nmbb.oplayer.po.POMedia; 12 | 13 | public final class FileBusiness { 14 | 15 | private static final String TABLE_NAME = "files"; 16 | private static final String TAG = "FileBusiness"; 17 | 18 | public static List getAllSortFiles() { 19 | SQLiteHelperOrm db = new SQLiteHelperOrm(); 20 | try { 21 | Dao dao = db.getDao(POMedia.class); 22 | QueryBuilder query = dao.queryBuilder(); 23 | query.orderBy("title_key", true); 24 | return dao.query(query.prepare()); 25 | } catch (SQLException e) { 26 | Logger.e(e); 27 | } finally { 28 | if (db != null) 29 | db.close(); 30 | } 31 | return new ArrayList(); 32 | // new DbHelper().queryForAll(POMedia.class); 33 | } 34 | 35 | // /** 获取所有已经排好序的列表 */ 36 | // public static ArrayList getAllSortFiles(final Context ctx) { 37 | // ArrayList result = new ArrayList(); 38 | // SQLiteHelper sqlite = new SQLiteHelper(ctx); 39 | // SQLiteDatabase db = sqlite.getReadableDatabase(); 40 | // Cursor c = null; 41 | // try { 42 | // c = db.rawQuery("SELECT " + FilesColumns.COL_ID + "," + FilesColumns.COL_TITLE + "," + FilesColumns.COL_TITLE_PINYIN + "," + FilesColumns.COL_PATH + "," + FilesColumns.COL_DURATION + "," + FilesColumns.COL_POSITION + "," + FilesColumns.COL_LAST_ACCESS_TIME + "," + FilesColumns.COL_THUMB + "," + FilesColumns.COL_FILE_SIZE + " FROM files", null); 43 | // while (c.moveToNext()) { 44 | // PFile po = new PFile(); 45 | // int index = 0; 46 | // po._id = c.getLong(index++); 47 | // po.title = c.getString(index++); 48 | // po.title_pinyin = c.getString(index++); 49 | // po.path = c.getString(index++); 50 | // po.duration = c.getInt(index++); 51 | // po.position = c.getInt(index++); 52 | // po.last_access_time = c.getLong(index++); 53 | // po.thumb = c.getString(index++); 54 | // po.file_size = c.getLong(index++); 55 | // result.add(po); 56 | // } 57 | // } finally { 58 | // if (c != null) 59 | // c.close(); 60 | // } 61 | // db.close(); 62 | // 63 | // Collections.sort(result, new Comparator() { 64 | // 65 | // @Override 66 | // public int compare(PFile f1, PFile f2) { 67 | // char c1 = f1.title_pinyin.length() == 0 ? ' ' : f1.title_pinyin.charAt(0); 68 | // char c2 = f2.title_pinyin.length() == 0 ? ' ' : f2.title_pinyin.charAt(0); 69 | // return c1 == c2 ? 0 : (c1 > c2 ? 1 : -1); 70 | // }//相等返回0,-1 f2 > f2,-1 71 | // 72 | // }); 73 | // return result; 74 | // } 75 | // 76 | // /** 重命名文件 */ 77 | // public static void renameFile(final Context ctx, final PFile p) { 78 | // SQLiteHelper sqlite = new SQLiteHelper(ctx); 79 | // SQLiteDatabase db = sqlite.getWritableDatabase(); 80 | // try { 81 | // ContentValues values = new ContentValues(); 82 | // values.put(FilesColumns.COL_TITLE, p.title); 83 | // values.put(FilesColumns.COL_TITLE_PINYIN, PinyinUtils.chineneToSpell(p.title.charAt(0) + "")); 84 | // values.put(FilesColumns.COL_PATH, p.path); 85 | // db.update(TABLE_NAME, values, FilesColumns.COL_ID + " = ?", new String[] { p._id + "" }); 86 | // } catch (Exception e) { 87 | // e.printStackTrace(); 88 | // } finally { 89 | // try { 90 | // db.close(); 91 | // } catch (Exception e) { 92 | // } 93 | // } 94 | // } 95 | // 96 | // /** 删除文件 */ 97 | // public static int deleteFile(final Context ctx, final PFile p) { 98 | // SQLiteHelper sqlite = new SQLiteHelper(ctx); 99 | // SQLiteDatabase db = sqlite.getWritableDatabase(); 100 | // int result = -1; 101 | // try { 102 | // result = db.delete(TABLE_NAME, FilesColumns.COL_ID + " = ?", new String[] { p._id + "" }); 103 | // } catch (Exception e) { 104 | // e.printStackTrace(); 105 | // } finally { 106 | // try { 107 | // db.close(); 108 | // } catch (Exception e) { 109 | // } 110 | // } 111 | // return result; 112 | // } 113 | // 114 | // public static void insertFile(final Context ctx, final PFile p) { 115 | // SQLiteHelper sqlite = new SQLiteHelper(ctx); 116 | // SQLiteDatabase db = sqlite.getWritableDatabase(); 117 | // try { 118 | // ContentValues values = new ContentValues(); 119 | // values.put(FilesColumns.COL_TITLE, p.title); 120 | // values.put(FilesColumns.COL_TITLE_PINYIN, PinyinUtils.chineneToSpell(p.title.charAt(0) + "")); 121 | // values.put(FilesColumns.COL_PATH, p.path); 122 | // values.put(FilesColumns.COL_LAST_ACCESS_TIME, System.currentTimeMillis()); 123 | // values.put(FilesColumns.COL_FILE_SIZE, p.file_size); 124 | // db.insert(TABLE_NAME, "", values); 125 | // } catch (Exception e) { 126 | // e.printStackTrace(); 127 | // } finally { 128 | // try { 129 | // db.close(); 130 | // } catch (Exception e) { 131 | // } 132 | // } 133 | // } 134 | // 135 | // /** 批量提取视频的缩略图已经视频的宽高 */ 136 | // public static ArrayList batchBuildThumbnail(final Context ctx, final ArrayList files) { 137 | // ArrayList result = new ArrayList(); 138 | // 139 | // for (File f : files) { 140 | // PFile pf = new PFile(); 141 | // try { 142 | // if (f.exists() && f.canRead()) { 143 | // //取出视频的一帧图像 144 | //// Bitmap bitmap = ThumbnailUtils.createVideoThumbnail(ctx, f.getAbsolutePath(), Video.Thumbnails.MINI_KIND); 145 | //// if (bitmap == null) { 146 | //// //缩略图创建失败 147 | //// bitmap = Bitmap.createBitmap(ThumbnailUtils.TARGET_SIZE_MINI_THUMBNAIL_WIDTH, ThumbnailUtils.TARGET_SIZE_MINI_THUMBNAIL_HEIGHT, Bitmap.Config.RGB_565); 148 | //// Log.e(TAG, "batchBuildThumbnail createBitmap faild : " + f.getAbsolutePath()); 149 | //// } 150 | //// 151 | //// pf.width = bitmap.getWidth(); 152 | //// pf.height = bitmap.getHeight(); 153 | //// 154 | //// //缩略图 155 | //// bitmap = ThumbnailUtils.extractThumbnail(bitmap, ThumbnailUtils.dipToPX(ctx, ThumbnailUtils.TARGET_SIZE_MICRO_THUMBNAIL_WIDTH), ThumbnailUtils.dipToPX(ctx, ThumbnailUtils.TARGET_SIZE_MICRO_THUMBNAIL_HEIGHT), ThumbnailUtils.OPTIONS_RECYCLE_INPUT); 156 | //// if (bitmap != null) { 157 | //// File thum = new File(f.getParent(), f.getName() + ".jpg"); 158 | //// pf.thumb = thum.getAbsolutePath(); 159 | //// //thum.createNewFile(); 160 | //// FileOutputStream iStream = new FileOutputStream(thum); 161 | //// bitmap.compress(Bitmap.CompressFormat.JPEG, 85, iStream); 162 | //// iStream.close(); 163 | //// } 164 | //// 165 | //// if (bitmap != null) 166 | //// bitmap.recycle(); 167 | // 168 | // } 169 | // } catch (Exception e) { 170 | // Log.e(TAG, e); 171 | // continue; 172 | // } finally { 173 | // result.add(pf); 174 | // } 175 | // } 176 | // 177 | // return result; 178 | // } 179 | // 180 | // /** 批量插入数据 */ 181 | // public static void batchInsertFiles(final Context ctx, final ArrayList files) { 182 | // SQLiteHelper sqlite = new SQLiteHelper(ctx); 183 | // SQLiteDatabase db = sqlite.getWritableDatabase(); 184 | // try { 185 | // db.beginTransaction(); 186 | // 187 | // SQLiteStatement stat = db.compileStatement("INSERT INTO files(" + FilesColumns.COL_TITLE + "," + FilesColumns.COL_TITLE_PINYIN + "," + FilesColumns.COL_PATH + "," + FilesColumns.COL_LAST_ACCESS_TIME + "," + FilesColumns.COL_FILE_SIZE + ") VALUES(?,?,?,?,?)"); 188 | // for (File f : files) { 189 | // String name = f.getName(); 190 | // int index = 1; 191 | // stat.bindString(index++, name);// title 192 | // stat.bindString(index++, PinyinUtils.chineneToSpell(name.charAt(0) + ""));// title_pinyin 193 | // stat.bindString(index++, f.getPath());// path 194 | // stat.bindLong(index++, System.currentTimeMillis());// last_access_time 195 | // stat.bindLong(index++, f.length()); 196 | // stat.execute(); 197 | // } 198 | // db.setTransactionSuccessful(); 199 | // } catch (BadHanyuPinyinOutputFormatCombination e) { 200 | // e.printStackTrace(); 201 | // } catch (Exception e) { 202 | // e.printStackTrace(); 203 | // } finally { 204 | // db.endTransaction(); 205 | // try { 206 | // db.close(); 207 | // } catch (Exception e) { 208 | // } 209 | // } 210 | // } 211 | } 212 | -------------------------------------------------------------------------------- /src/com/nmbb/oplayer/database/DbHelper.java: -------------------------------------------------------------------------------- 1 | package com.nmbb.oplayer.database; 2 | 3 | import java.sql.SQLException; 4 | import java.util.ArrayList; 5 | import java.util.List; 6 | import java.util.Map; 7 | 8 | import android.content.ContentValues; 9 | 10 | import com.j256.ormlite.dao.Dao; 11 | import com.j256.ormlite.stmt.UpdateBuilder; 12 | import com.nmbb.oplayer.exception.Logger; 13 | 14 | @SuppressWarnings({ "unchecked", "rawtypes" }) 15 | public class DbHelper { 16 | 17 | /** 新增一条记录 */ 18 | public int create(T po) { 19 | SQLiteHelperOrm db = new SQLiteHelperOrm(); 20 | try { 21 | Dao dao = db.getDao(po.getClass()); 22 | return dao.create(po); 23 | } catch (SQLException e) { 24 | Logger.e(e); 25 | } finally { 26 | if (db != null) 27 | db.close(); 28 | } 29 | return -1; 30 | } 31 | 32 | public boolean exists(T po, Map where) { 33 | SQLiteHelperOrm db = new SQLiteHelperOrm(); 34 | try { 35 | Dao dao = db.getDao(po.getClass()); 36 | if (dao.queryForFieldValues(where).size() > 0) { 37 | return true; 38 | } 39 | } catch (SQLException e) { 40 | Logger.e(e); 41 | } finally { 42 | if (db != null) 43 | db.close(); 44 | } 45 | return false; 46 | } 47 | 48 | public int createIfNotExists(T po, Map where) { 49 | SQLiteHelperOrm db = new SQLiteHelperOrm(); 50 | try { 51 | Dao dao = db.getDao(po.getClass()); 52 | if (dao.queryForFieldValues(where).size() < 1) { 53 | return dao.create(po); 54 | } 55 | } catch (SQLException e) { 56 | Logger.e(e); 57 | } finally { 58 | if (db != null) 59 | db.close(); 60 | } 61 | return -1; 62 | } 63 | 64 | /** 查询一条记录 */ 65 | public List queryForEq(Class c, String fieldName, Object value) { 66 | SQLiteHelperOrm db = new SQLiteHelperOrm(); 67 | try { 68 | Dao dao = db.getDao(c); 69 | return dao.queryForEq(fieldName, value); 70 | } catch (SQLException e) { 71 | Logger.e(e); 72 | } finally { 73 | if (db != null) 74 | db.close(); 75 | } 76 | return new ArrayList(); 77 | } 78 | 79 | /** 删除一条记录 */ 80 | public int remove(T po) { 81 | SQLiteHelperOrm db = new SQLiteHelperOrm(); 82 | try { 83 | Dao dao = db.getDao(po.getClass()); 84 | return dao.delete(po); 85 | } catch (SQLException e) { 86 | Logger.e(e); 87 | } finally { 88 | if (db != null) 89 | db.close(); 90 | } 91 | return -1; 92 | } 93 | 94 | /** 95 | * 根据特定条件更新特定字段 96 | * 97 | * @param c 98 | * @param values 99 | * @param columnName where字段 100 | * @param value where值 101 | * @return 102 | */ 103 | public int update(Class c, ContentValues values, String columnName, Object value) { 104 | SQLiteHelperOrm db = new SQLiteHelperOrm(); 105 | try { 106 | Dao dao = db.getDao(c); 107 | UpdateBuilder updateBuilder = dao.updateBuilder(); 108 | updateBuilder.where().eq(columnName, value); 109 | for (String key : values.keySet()) { 110 | updateBuilder.updateColumnValue(key, values.get(key)); 111 | } 112 | return updateBuilder.update(); 113 | } catch (SQLException e) { 114 | Logger.e(e); 115 | } finally { 116 | if (db != null) 117 | db.close(); 118 | } 119 | return -1; 120 | } 121 | 122 | /** 更新一条记录 */ 123 | public int update(T po) { 124 | SQLiteHelperOrm db = new SQLiteHelperOrm(); 125 | try { 126 | 127 | Dao dao = db.getDao(po.getClass()); 128 | return dao.update(po); 129 | } catch (SQLException e) { 130 | Logger.e(e); 131 | } finally { 132 | if (db != null) 133 | db.close(); 134 | } 135 | return -1; 136 | } 137 | 138 | /** 查询所有记录 */ 139 | public List queryForAll(Class c) { 140 | SQLiteHelperOrm db = new SQLiteHelperOrm(); 141 | try { 142 | Dao dao = db.getDao(c); 143 | return dao.queryForAll(); 144 | } catch (SQLException e) { 145 | Logger.e(e); 146 | } finally { 147 | if (db != null) 148 | db.close(); 149 | } 150 | return new ArrayList(); 151 | } 152 | } 153 | -------------------------------------------------------------------------------- /src/com/nmbb/oplayer/database/SQLiteHelperOrm.java: -------------------------------------------------------------------------------- 1 | package com.nmbb.oplayer.database; 2 | 3 | import java.sql.SQLException; 4 | 5 | import android.content.Context; 6 | import android.database.sqlite.SQLiteDatabase; 7 | 8 | import com.j256.ormlite.android.apptools.OrmLiteSqliteOpenHelper; 9 | import com.j256.ormlite.support.ConnectionSource; 10 | import com.j256.ormlite.table.TableUtils; 11 | import com.nmbb.oplayer.OPlayerApplication; 12 | import com.nmbb.oplayer.exception.Logger; 13 | import com.nmbb.oplayer.po.POMedia; 14 | 15 | public class SQLiteHelperOrm extends OrmLiteSqliteOpenHelper { 16 | private static final String DATABASE_NAME = "oplayer.db"; 17 | private static final int DATABASE_VERSION = 1; 18 | 19 | public SQLiteHelperOrm(Context context) { 20 | super(context, DATABASE_NAME, null, DATABASE_VERSION); 21 | } 22 | 23 | public SQLiteHelperOrm() { 24 | super(OPlayerApplication.getContext(), DATABASE_NAME, null, DATABASE_VERSION); 25 | } 26 | 27 | @Override 28 | public void onCreate(SQLiteDatabase db, ConnectionSource connectionSource) { 29 | try { 30 | TableUtils.createTable(connectionSource, POMedia.class); 31 | } catch (SQLException e) { 32 | Logger.e(e); 33 | } 34 | } 35 | 36 | @Override 37 | public void onUpgrade(SQLiteDatabase db, ConnectionSource connectionSource, int arg2, int arg3) { 38 | try { 39 | TableUtils.dropTable(connectionSource, POMedia.class, true); 40 | onCreate(db, connectionSource); 41 | } catch (SQLException e) { 42 | Logger.e(e); 43 | } 44 | } 45 | } -------------------------------------------------------------------------------- /src/com/nmbb/oplayer/exception/Logger.java: -------------------------------------------------------------------------------- 1 | package com.nmbb.oplayer.exception; 2 | 3 | import android.util.Log; 4 | 5 | public class Logger { 6 | 7 | private static boolean isLog = true; 8 | private static final String TAG = "OPlayer"; 9 | 10 | public static void setLog(boolean isLog) { 11 | Logger.isLog = isLog; 12 | } 13 | 14 | public static boolean getIsLog() { 15 | return isLog; 16 | } 17 | 18 | public static void d(String tag, String msg) { 19 | if (isLog) { 20 | Log.d(tag, msg); 21 | } 22 | } 23 | 24 | public static void d(String msg) { 25 | Log.d(TAG, msg); 26 | } 27 | 28 | /** 29 | * Send a {@link #DEBUG} log message and log the exception. 30 | * 31 | * @param tag Used to identify the source of a log message. It usually 32 | * identifies the class or activity where the log call occurs. 33 | * @param msg The message you would like logged. 34 | * @param tr An exception to log 35 | */ 36 | public static void d(String tag, String msg, Throwable tr) { 37 | if (isLog) { 38 | Log.d(tag, msg, tr); 39 | } 40 | } 41 | 42 | public static void e(Throwable tr) { 43 | if (isLog) { 44 | Log.e(TAG, "", tr); 45 | } 46 | } 47 | 48 | public static void i(String msg) { 49 | if (isLog) { 50 | Log.i(TAG, msg); 51 | } 52 | } 53 | 54 | public static void i(String tag, String msg) { 55 | if (isLog) { 56 | Log.i(tag, msg); 57 | } 58 | } 59 | 60 | /** 61 | * Send a {@link #INFO} log message and log the exception. 62 | * 63 | * @param tag Used to identify the source of a log message. It usually 64 | * identifies the class or activity where the log call occurs. 65 | * @param msg The message you would like logged. 66 | * @param tr An exception to log 67 | */ 68 | public static void i(String tag, String msg, Throwable tr) { 69 | if (isLog) { 70 | Log.i(tag, msg, tr); 71 | } 72 | 73 | } 74 | 75 | /** 76 | * Send an {@link #ERROR} log message. 77 | * 78 | * @param tag Used to identify the source of a log message. It usually 79 | * identifies the class or activity where the log call occurs. 80 | * @param msg The message you would like logged. 81 | */ 82 | public static void e(String tag, String msg) { 83 | if (isLog) { 84 | Log.e(tag, msg); 85 | } 86 | } 87 | 88 | public static void e(String msg) { 89 | if (isLog) { 90 | Log.e(TAG, msg); 91 | } 92 | } 93 | 94 | /** 95 | * Send a {@link #ERROR} log message and log the exception. 96 | * 97 | * @param tag Used to identify the source of a log message. It usually 98 | * identifies the class or activity where the log call occurs. 99 | * @param msg The message you would like logged. 100 | * @param tr An exception to log 101 | */ 102 | public static void e(String tag, String msg, Throwable tr) { 103 | if (isLog) { 104 | Log.e(tag, msg, tr); 105 | } 106 | } 107 | 108 | public static void e(String msg, Throwable tr) { 109 | if (isLog) { 110 | Log.e(TAG, msg, tr); 111 | } 112 | } 113 | 114 | public static void systemErr(String msg) { 115 | // if (true) { 116 | if (isLog) { 117 | if (msg != null) { 118 | Log.e(TAG, msg); 119 | } 120 | 121 | } 122 | } 123 | 124 | } 125 | -------------------------------------------------------------------------------- /src/com/nmbb/oplayer/po/OnlineVideo.java: -------------------------------------------------------------------------------- 1 | package com.nmbb.oplayer.po; 2 | 3 | import java.util.ArrayList; 4 | 5 | public class OnlineVideo { 6 | public String id; 7 | /** 标题 */ 8 | public String title; 9 | public String desc; 10 | /** LOGO */ 11 | public int iconId = 0; 12 | public String icon_url; 13 | /** 播放地址 */ 14 | public String url; 15 | /** 备用链接 */ 16 | public ArrayList backup_url; 17 | /** 是否目录 */ 18 | public boolean is_category = false; 19 | /** 0视频 1电视 */ 20 | public int category; 21 | /** */ 22 | public int level = 1; 23 | 24 | public OnlineVideo() { 25 | 26 | } 27 | 28 | public OnlineVideo(String title, int iconId, int category) { 29 | this.title = title; 30 | this.iconId = iconId; 31 | this.category = category; 32 | } 33 | 34 | public OnlineVideo(String title, int iconId, int category, String url) { 35 | this.title = title; 36 | this.iconId = iconId; 37 | this.category = category; 38 | this.url = url; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/com/nmbb/oplayer/po/PFile.java: -------------------------------------------------------------------------------- 1 | package com.nmbb.oplayer.po; 2 | 3 | import android.content.Context; 4 | import android.database.Cursor; 5 | import android.graphics.Bitmap; 6 | 7 | public final class PFile { 8 | 9 | public long _id; 10 | /** 视频标题 */ 11 | public String title; 12 | /** 视频标题拼音 */ 13 | public String title_pinyin; 14 | /** 视频路径 */ 15 | public String path; 16 | /** 最后一次访问时间 */ 17 | public long last_access_time; 18 | /** 视频时长 */ 19 | public int duration; 20 | /** 视频播放进度 */ 21 | public int position; 22 | /** 视频缩略图 */ 23 | public String thumb; 24 | /** 文件大小 */ 25 | public long file_size; 26 | /** 文件状态0 - 10 分别代表 下载 0-100% */ 27 | public int status = -1; 28 | /** 文件临时大小 用于下载 */ 29 | public long temp_file_size = -1L; 30 | /** 视频宽度 */ 31 | public int width; 32 | /** 视频高度 */ 33 | public int height; 34 | 35 | public PFile() { 36 | 37 | } 38 | 39 | public PFile(Cursor c) { 40 | //Video.Media._ID, Video.Media.TITLE, Video.Media.TITLE_KEY, Video.Media.SIZE, Video.Media.DURATION, Video.Media.DATA, Video.Media.WIDTH, Video.Media.HEIGHT 41 | _id = c.getLong(0); 42 | title = c.getString(1); 43 | title_pinyin = c.getString(2); 44 | file_size = c.getLong(3); 45 | duration = c.getInt(4); 46 | path = c.getString(5); 47 | width = c.getInt(6); 48 | height = c.getInt(7); 49 | } 50 | 51 | /** 获取缩略图 */ 52 | public Bitmap getThumb(Context ctx) { 53 | return null; 54 | // return Video.Thumbnails.getThumbnail(ctx.getApplicationContext(), ctx.getContentResolver(), _id, Video.Thumbnails.MICRO_KIND, null); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/com/nmbb/oplayer/po/POMedia.java: -------------------------------------------------------------------------------- 1 | package com.nmbb.oplayer.po; 2 | 3 | import java.io.File; 4 | 5 | import com.j256.ormlite.field.DatabaseField; 6 | import com.j256.ormlite.table.DatabaseTable; 7 | 8 | /** 9 | * 视频PO类 10 | * 11 | * @author 农民伯伯 12 | * @see http://www.cnblogs.com/over140 13 | * 14 | */ 15 | @DatabaseTable(tableName = "media") 16 | public class POMedia { 17 | @DatabaseField(generatedId = true) 18 | public long _id; 19 | /** 视频标题 */ 20 | @DatabaseField 21 | public String title; 22 | /** 视频标题拼音 */ 23 | @DatabaseField 24 | public String title_key; 25 | /** 视频路径 */ 26 | @DatabaseField 27 | public String path; 28 | /** 最后一次访问时间 */ 29 | @DatabaseField 30 | public long last_access_time; 31 | /** 最后一次修改时间 */ 32 | @DatabaseField 33 | public long last_modify_time; 34 | /** 视频时长 */ 35 | @DatabaseField 36 | public int duration; 37 | /** 视频播放进度 */ 38 | @DatabaseField 39 | public int position; 40 | /** 视频缩略图路径 */ 41 | @DatabaseField 42 | public String thumb_path; 43 | /** 文件大小 */ 44 | @DatabaseField 45 | public long file_size; 46 | /** 视频宽度 */ 47 | @DatabaseField 48 | public int width; 49 | /** 视频高度 */ 50 | @DatabaseField 51 | public int height; 52 | /** MIME类型 */ 53 | public String mime_type; 54 | /** 0 本地视频 1 网络视频 */ 55 | public int type = 0; 56 | 57 | /** 文件状态0 - 10 分别代表 下载 0-100% */ 58 | public int status = -1; 59 | /** 文件临时大小 用于下载 */ 60 | public long temp_file_size = -1L; 61 | 62 | public POMedia() { 63 | 64 | } 65 | 66 | public POMedia(File f) { 67 | title = f.getName(); 68 | path = f.getAbsolutePath(); 69 | last_modify_time = f.lastModified(); 70 | file_size = f.length(); 71 | } 72 | 73 | public POMedia(String path, String mimeType) { 74 | this(new File(path)); 75 | this.mime_type = mimeType; 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /src/com/nmbb/oplayer/preference/PreferenceUtils.java: -------------------------------------------------------------------------------- 1 | package com.nmbb.oplayer.preference; 2 | 3 | import android.content.Context; 4 | import android.content.SharedPreferences; 5 | import android.content.SharedPreferences.Editor; 6 | import android.preference.PreferenceManager; 7 | 8 | import com.nmbb.oplayer.OPlayerApplication; 9 | 10 | public final class PreferenceUtils { 11 | 12 | /** 清空数据 */ 13 | public static void reset(final Context ctx) { 14 | SharedPreferences.Editor edit = PreferenceManager.getDefaultSharedPreferences(ctx).edit(); 15 | edit.clear(); 16 | edit.commit(); 17 | } 18 | 19 | public static String getString(String key, String defValue) { 20 | return PreferenceManager.getDefaultSharedPreferences(OPlayerApplication.getContext()).getString(key, defValue); 21 | } 22 | 23 | public static long getLong(String key, long defValue) { 24 | return PreferenceManager.getDefaultSharedPreferences(OPlayerApplication.getContext()).getLong(key, defValue); 25 | } 26 | 27 | public static float getFloat(String key, float defValue) { 28 | return PreferenceManager.getDefaultSharedPreferences(OPlayerApplication.getContext()).getFloat(key, defValue); 29 | } 30 | 31 | public static void put(String key, String value) { 32 | putString(key, value); 33 | } 34 | 35 | public static void put(String key, int value) { 36 | putInt(key, value); 37 | } 38 | 39 | public static void put(String key, float value) { 40 | putFloat(key, value); 41 | } 42 | 43 | public static void put(String key, boolean value) { 44 | putBoolean(key, value); 45 | } 46 | 47 | public static void putFloat(String key, float value) { 48 | SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(OPlayerApplication.getContext()); 49 | Editor editor = sharedPreferences.edit(); 50 | editor.putFloat(key, value); 51 | editor.commit(); 52 | } 53 | 54 | public static SharedPreferences getPreferences() { 55 | return PreferenceManager.getDefaultSharedPreferences(OPlayerApplication.getContext()); 56 | } 57 | 58 | public static int getInt(String key, int defValue) { 59 | return PreferenceManager.getDefaultSharedPreferences(OPlayerApplication.getContext()).getInt(key, defValue); 60 | } 61 | 62 | public static boolean getBoolean(String key, boolean defValue) { 63 | return PreferenceManager.getDefaultSharedPreferences(OPlayerApplication.getContext()).getBoolean(key, defValue); 64 | } 65 | 66 | public static void putStringProcess(String key, String value) { 67 | SharedPreferences sharedPreferences = OPlayerApplication.getContext().getSharedPreferences("preference_mu", Context.MODE_MULTI_PROCESS); 68 | Editor editor = sharedPreferences.edit(); 69 | editor.putString(key, value); 70 | editor.commit(); 71 | } 72 | 73 | public static String getStringProcess(String key, String defValue) { 74 | SharedPreferences sharedPreferences = OPlayerApplication.getContext().getSharedPreferences("preference_mu", Context.MODE_MULTI_PROCESS); 75 | return sharedPreferences.getString(key, defValue); 76 | } 77 | 78 | public static boolean hasString(String key) { 79 | SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(OPlayerApplication.getContext()); 80 | return sharedPreferences.contains(key); 81 | } 82 | 83 | public static void putString(String key, String value) { 84 | SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(OPlayerApplication.getContext()); 85 | Editor editor = sharedPreferences.edit(); 86 | editor.putString(key, value); 87 | editor.commit(); 88 | } 89 | 90 | public static void putLong(String key, long value) { 91 | SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(OPlayerApplication.getContext()); 92 | Editor editor = sharedPreferences.edit(); 93 | editor.putLong(key, value); 94 | editor.commit(); 95 | } 96 | 97 | public static void putBoolean(String key, boolean value) { 98 | SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(OPlayerApplication.getContext()); 99 | Editor editor = sharedPreferences.edit(); 100 | editor.putBoolean(key, value); 101 | editor.commit(); 102 | } 103 | 104 | public static void putInt(String key, int value) { 105 | SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(OPlayerApplication.getContext()); 106 | Editor editor = sharedPreferences.edit(); 107 | editor.putInt(key, value); 108 | editor.commit(); 109 | } 110 | 111 | public static void remove(String... keys) { 112 | if (keys != null) { 113 | SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(OPlayerApplication.getContext()); 114 | Editor editor = sharedPreferences.edit(); 115 | for (String key : keys) { 116 | editor.remove(key); 117 | } 118 | editor.commit(); 119 | } 120 | } 121 | } 122 | -------------------------------------------------------------------------------- /src/com/nmbb/oplayer/receiver/MediaScannerReceiver.java: -------------------------------------------------------------------------------- 1 | package com.nmbb.oplayer.receiver; 2 | 3 | import android.content.BroadcastReceiver; 4 | import android.content.Context; 5 | import android.content.Intent; 6 | import android.net.Uri; 7 | import android.os.Bundle; 8 | import android.os.Environment; 9 | 10 | import com.nmbb.oplayer.service.MediaScannerService; 11 | 12 | /** 文件扫描 */ 13 | public class MediaScannerReceiver extends BroadcastReceiver { 14 | 15 | public static final String ACTION_MEDIA_SCANNER_SCAN_FILE = ""; 16 | public static final String ACTION_MEDIA_SCANNER_SCAN_DIRECTORY = ""; 17 | 18 | @Override 19 | public void onReceive(Context context, Intent intent) { 20 | String action = intent.getAction(); 21 | Uri uri = intent.getData(); 22 | 23 | if (action.equals(Intent.ACTION_BOOT_COMPLETED)) { 24 | //扫描整个SD卡目录 25 | //FIXME 处理多个SD卡的问题 26 | // Environment.getExternalStorageDirectory().getParentFile(); 27 | scanDirectory(context, Environment.getExternalStorageDirectory().getAbsolutePath()); 28 | } else if (uri.getScheme().equals("file")) { 29 | String path = uri.getPath(); 30 | if (action.equals(Intent.ACTION_MEDIA_MOUNTED)) { 31 | scanDirectory(context, path); 32 | } else if (action.equals(ACTION_MEDIA_SCANNER_SCAN_FILE) && path != null) { 33 | scanFile(context, path); 34 | } else if (action.equals(ACTION_MEDIA_SCANNER_SCAN_DIRECTORY) && path != null) { 35 | scanDirectory(context, path); 36 | } 37 | } 38 | } 39 | 40 | /** 扫描文件夹 */ 41 | private void scanDirectory(Context context, String volume) { 42 | Bundle args = new Bundle(); 43 | args.putString(MediaScannerService.EXTRA_DIRECTORY, volume); 44 | context.startService(new Intent(context, MediaScannerService.class).putExtras(args)); 45 | } 46 | 47 | private void scanFile(Context context, String path) { 48 | Bundle args = new Bundle(); 49 | args.putString(MediaScannerService.EXTRA_FILE_PATH, path); 50 | context.startService(new Intent(context, MediaScannerService.class).putExtras(args)); 51 | } 52 | // private static boolean isScanning = false; 53 | // // private boolean isScanningStarted = false; 54 | // private IReceiverNotify mNotify; 55 | // 56 | // public MediaScannerReceiver() { 57 | // } 58 | // 59 | // public MediaScannerReceiver(IReceiverNotify notify) { 60 | // mNotify = notify; 61 | // } 62 | // 63 | // public static boolean isScanning(Context ctx) { 64 | // return isServiceRunning(ctx, "io.vov.vitamio.MediaScannerService"); 65 | // } 66 | // 67 | // @Override 68 | // public void onReceive(Context context, Intent intent) { 69 | // final String action = intent.getAction(); 70 | // Log.i("MediaScannerReceiver", action); 71 | // } 72 | // 73 | // /** 服务是否正在运行 */ 74 | // public static boolean isServiceRunning(Context ctx, String name) { 75 | // ActivityManager manager = (ActivityManager) ctx.getSystemService(Context.ACTIVITY_SERVICE); 76 | // for (RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) { 77 | // if (name.equals(service.service.getClassName())) 78 | // return true; 79 | // } 80 | // return false; 81 | // } 82 | } 83 | -------------------------------------------------------------------------------- /src/com/nmbb/oplayer/service/FileDownloadService.java: -------------------------------------------------------------------------------- 1 | package com.nmbb.oplayer.service; 2 | 3 | import android.app.Service; 4 | import android.content.Intent; 5 | import android.os.IBinder; 6 | 7 | public class FileDownloadService extends Service { 8 | 9 | @Override 10 | public IBinder onBind(Intent intent) { 11 | return null; 12 | } 13 | 14 | 15 | } 16 | -------------------------------------------------------------------------------- /src/com/nmbb/oplayer/service/MediaScannerService.java: -------------------------------------------------------------------------------- 1 | package com.nmbb.oplayer.service; 2 | 3 | import java.io.File; 4 | import java.io.FileNotFoundException; 5 | import java.util.ArrayList; 6 | import java.util.HashMap; 7 | import java.util.Map; 8 | import java.util.concurrent.ConcurrentHashMap; 9 | 10 | import android.app.ActivityManager; 11 | import android.app.ActivityManager.RunningServiceInfo; 12 | import android.app.Service; 13 | import android.content.Context; 14 | import android.content.Intent; 15 | import android.os.Binder; 16 | import android.os.Bundle; 17 | import android.os.Handler; 18 | import android.os.IBinder; 19 | import android.os.Message; 20 | import com.nmbb.oplayer.OPlayerApplication; 21 | import com.nmbb.oplayer.OPreference; 22 | import com.nmbb.oplayer.database.DbHelper; 23 | import com.nmbb.oplayer.exception.Logger; 24 | import com.nmbb.oplayer.po.POMedia; 25 | import com.nmbb.oplayer.util.FileUtils; 26 | import com.nmbb.oplayer.util.PinyinUtils; 27 | import com.nmbb.oplayer.util.StringUtils; 28 | 29 | /** 媒体扫描 */ 30 | public class MediaScannerService extends Service implements Runnable { 31 | 32 | private static final String SERVICE_NAME = "com.nmbb.oplayer.service.MediaScannerService"; 33 | /** 扫描文件夹 */ 34 | public static final String EXTRA_DIRECTORY = "scan_directory"; 35 | /** 扫描文件 */ 36 | public static final String EXTRA_FILE_PATH = "scan_file"; 37 | public static final String EXTRA_MIME_TYPE = "mimetype"; 38 | 39 | public static final int SCAN_STATUS_NORMAL = -1; 40 | /** 开始扫描 */ 41 | public static final int SCAN_STATUS_START = 0; 42 | /** 正在扫描 扫描到一个视频文件 */ 43 | public static final int SCAN_STATUS_RUNNING = 1; 44 | /** 扫描完成 */ 45 | public static final int SCAN_STATUS_END = 2; 46 | /** */ 47 | private ArrayList observers = new ArrayList(); 48 | private ConcurrentHashMap mScanMap = new ConcurrentHashMap(); 49 | 50 | /** 当前状态 */ 51 | private volatile int mServiceStatus = SCAN_STATUS_NORMAL; 52 | private DbHelper mDbHelper; 53 | private Map mDbWhere = new HashMap(2); 54 | 55 | @Override 56 | public void onCreate() { 57 | super.onCreate(); 58 | 59 | mDbHelper = new DbHelper(); 60 | } 61 | 62 | /** 是否正在运行 */ 63 | public static boolean isRunning() { 64 | ActivityManager manager = (ActivityManager) OPlayerApplication.getContext().getSystemService(Context.ACTIVITY_SERVICE); 65 | for (RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) { 66 | if (SERVICE_NAME.equals(service.service.getClassName())) 67 | return true; 68 | } 69 | return false; 70 | } 71 | 72 | @Override 73 | public int onStartCommand(Intent intent, int flags, int startId) { 74 | if (intent != null) 75 | parseIntent(intent); 76 | 77 | return super.onStartCommand(intent, flags, startId); 78 | } 79 | 80 | /** 解析Intent */ 81 | private void parseIntent(final Intent intent) { 82 | final Bundle arguments = intent.getExtras(); 83 | if (arguments != null) { 84 | if (arguments.containsKey(EXTRA_DIRECTORY)) { 85 | String directory = arguments.getString(EXTRA_DIRECTORY); 86 | Logger.i("onStartCommand:" + directory); 87 | //扫描文件夹 88 | if (!mScanMap.containsKey(directory)) 89 | mScanMap.put(directory, ""); 90 | } else if (arguments.containsKey(EXTRA_FILE_PATH)) { 91 | //单文件 92 | String filePath = arguments.getString(EXTRA_FILE_PATH); 93 | Logger.i("onStartCommand:" + filePath); 94 | if (!StringUtils.isEmpty(filePath)) { 95 | if (!mScanMap.containsKey(filePath)) 96 | mScanMap.put(filePath, arguments.getString(EXTRA_MIME_TYPE)); 97 | // scanFile(filePath, arguments.getString(EXTRA_MIME_TYPE)); 98 | } 99 | } 100 | } 101 | 102 | if (mServiceStatus == SCAN_STATUS_NORMAL || mServiceStatus == SCAN_STATUS_END) { 103 | new Thread(this).start(); 104 | //scan(); 105 | } 106 | } 107 | 108 | @Override 109 | public void run() { 110 | scan(); 111 | } 112 | 113 | /** 扫描 */ 114 | private void scan() { 115 | //开始扫描 116 | notifyObservers(SCAN_STATUS_START, null); 117 | 118 | while (mScanMap.keySet().size() > 0) { 119 | 120 | String path = ""; 121 | for (String key : mScanMap.keySet()) { 122 | path = key; 123 | break; 124 | } 125 | if (mScanMap.containsKey(path)) { 126 | String mimeType = mScanMap.get(path); 127 | if ("".equals(mimeType)) { 128 | scanDirectory(path); 129 | } else { 130 | scanFile(path, mimeType); 131 | } 132 | 133 | //扫描完成一个 134 | mScanMap.remove(path); 135 | } 136 | 137 | //任务之间歇息一秒 138 | try { 139 | Thread.sleep(1000); 140 | } catch (InterruptedException e) { 141 | Logger.e(e); 142 | } 143 | } 144 | 145 | //全部扫描完成 146 | notifyObservers(SCAN_STATUS_END, null); 147 | 148 | //第一次扫描 149 | OPreference pref = new OPreference(this); 150 | if (pref.getBoolean(OPlayerApplication.PREF_KEY_FIRST, true)) 151 | pref.putBooleanAndCommit(OPlayerApplication.PREF_KEY_FIRST, false); 152 | 153 | //停止服务 154 | stopSelf(); 155 | } 156 | 157 | private Handler mHandler = new Handler() { 158 | @Override 159 | public void handleMessage(Message msg) { 160 | super.handleMessage(msg); 161 | for (IMediaScannerObserver s : observers) { 162 | if (s != null) { 163 | s.update(msg.what, (POMedia) msg.obj); 164 | } 165 | } 166 | } 167 | }; 168 | 169 | /** 扫描文件 */ 170 | private void scanFile(String path, String mimeType) { 171 | save(new POMedia(path, mimeType)); 172 | } 173 | 174 | /** 扫描文件夹 */ 175 | private void scanDirectory(String path) { 176 | eachAllMedias(new File(path)); 177 | } 178 | 179 | /** 递归查找视频 */ 180 | private void eachAllMedias(File f) { 181 | if (f != null && f.exists() && f.isDirectory()) { 182 | File[] files = f.listFiles(); 183 | if (files != null) { 184 | for (File file : f.listFiles()) { 185 | // Logger.i(f.getAbsolutePath()); 186 | if (file.isDirectory()) { 187 | //忽略.开头的文件夹 188 | if (!file.getAbsolutePath().startsWith(".")) 189 | eachAllMedias(file); 190 | } else if (file.exists() && file.canRead() && FileUtils.isVideo(file)) { 191 | save(new POMedia(file)); 192 | } 193 | } 194 | } 195 | } 196 | } 197 | 198 | /** 199 | * 保存入库 200 | * 201 | * @throws FileNotFoundException 202 | */ 203 | private void save(POMedia media) { 204 | mDbWhere.put("path", media.path); 205 | mDbWhere.put("last_modify_time", media.last_modify_time); 206 | //检测 207 | if (!mDbHelper.exists(media, mDbWhere)) { 208 | try { 209 | if (media.title != null && media.title.length() > 0) 210 | media.title_key = PinyinUtils.chineneToSpell(media.title.charAt(0) + ""); 211 | } catch (Exception ex) { 212 | Logger.e(ex); 213 | } 214 | media.last_access_time = System.currentTimeMillis(); 215 | 216 | //提取缩略图 217 | // extractThumbnail(media); 218 | media.mime_type = FileUtils.getMimeType(media.path); 219 | 220 | //入库 221 | mDbHelper.create(media); 222 | 223 | //扫描到一个 224 | notifyObservers(SCAN_STATUS_RUNNING, media); 225 | } 226 | } 227 | 228 | /** 提取生成缩略图 */ 229 | private void extractThumbnail(POMedia media) { 230 | // final Context ctx = OPlayerApplication.getContext(); 231 | // // ThumbnailUtils. 232 | // Bitmap bitmap = ThumbnailUtils.createVideoThumbnail(media.path, Images.Thumbnails.MINI_KIND); 233 | // try { 234 | // if (bitmap == null) { 235 | // //缩略图创建失败 236 | // bitmap = Bitmap.createBitmap(ThumbnailUtils.TARGET_SIZE_MINI_THUMBNAIL_WIDTH, ThumbnailUtils.TARGET_SIZE_MINI_THUMBNAIL_HEIGHT, Bitmap.Config.RGB_565); 237 | // } 238 | // 239 | // media.width = bitmap.getWidth(); 240 | // media.height = bitmap.getHeight(); 241 | // 242 | // //缩略图 243 | // bitmap = ThumbnailUtils.extractThumbnail(bitmap, ConvertUtils.dipToPX(ctx, ThumbnailUtils.TARGET_SIZE_MICRO_THUMBNAIL_WIDTH), ConvertUtils.dipToPX(ctx, ThumbnailUtils.TARGET_SIZE_MICRO_THUMBNAIL_HEIGHT), ThumbnailUtils.OPTIONS_RECYCLE_INPUT); 244 | // if (bitmap != null) { 245 | // //将缩略图存到视频当前路径 246 | // File thum = new File(OPlayerApplication.OPLAYER_VIDEO_THUMB, UUID.randomUUID().toString()); 247 | // media.thumb_path = thum.getAbsolutePath(); 248 | // //thum.createNewFile(); 249 | // FileOutputStream iStream = new FileOutputStream(thum); 250 | // bitmap.compress(Bitmap.CompressFormat.JPEG, 85, iStream); 251 | // iStream.close(); 252 | // } 253 | // 254 | // //入库 255 | // 256 | // } catch (Exception ex) { 257 | // Logger.e(ex); 258 | // } finally { 259 | // if (bitmap != null) 260 | // bitmap.recycle(); 261 | // 262 | // } 263 | } 264 | 265 | // ~~~ 状态改变 266 | 267 | /** 通知状态改变 */ 268 | private void notifyObservers(int flag, POMedia media) { 269 | mHandler.sendMessage(mHandler.obtainMessage(flag, media)); 270 | } 271 | 272 | /** 增加观察者 */ 273 | public void addObserver(IMediaScannerObserver s) { 274 | synchronized (this) { 275 | if (!observers.contains(s)) { 276 | observers.add(s); 277 | } 278 | } 279 | } 280 | 281 | /** 删除观察者 */ 282 | public synchronized void deleteObserver(IMediaScannerObserver s) { 283 | observers.remove(s); 284 | } 285 | 286 | /** 删除所有观察者 */ 287 | public synchronized void deleteObservers() { 288 | observers.clear(); 289 | } 290 | 291 | public interface IMediaScannerObserver { 292 | /** 293 | * 294 | * @param flag 0 开始扫描 1 正在扫描 2 扫描完成 295 | * @param file 扫描到的视频文件 296 | */ 297 | public void update(int flag, POMedia media); 298 | } 299 | 300 | // ~~~ Binder 301 | 302 | private final MediaScannerServiceBinder mBinder = new MediaScannerServiceBinder(); 303 | 304 | public class MediaScannerServiceBinder extends Binder { 305 | public MediaScannerService getService() { 306 | return MediaScannerService.this; 307 | } 308 | } 309 | 310 | @Override 311 | public IBinder onBind(Intent intent) { 312 | return mBinder; 313 | } 314 | 315 | } 316 | -------------------------------------------------------------------------------- /src/com/nmbb/oplayer/ui/FragmentBase.java: -------------------------------------------------------------------------------- 1 | package com.nmbb.oplayer.ui; 2 | 3 | import com.nmbb.oplayer.R; 4 | 5 | import android.content.BroadcastReceiver; 6 | import android.content.IntentFilter; 7 | import android.database.ContentObserver; 8 | import android.net.Uri; 9 | import android.os.Bundle; 10 | import android.support.v4.app.Fragment; 11 | import android.view.LayoutInflater; 12 | import android.view.View; 13 | import android.view.ViewGroup; 14 | import android.widget.ListView; 15 | 16 | public class FragmentBase extends Fragment { 17 | 18 | protected ListView mListView; 19 | protected View mLoadingLayout; 20 | protected MainActivity mParent; 21 | 22 | @Override 23 | public void onCreate(Bundle savedInstanceState) { 24 | super.onCreate(savedInstanceState); 25 | mParent = (MainActivity) getActivity(); 26 | } 27 | 28 | @Override 29 | public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 30 | View v = inflater.inflate(R.layout.fragment_file, container, false); 31 | mListView = (ListView) v.findViewById(android.R.id.list); 32 | mLoadingLayout = v.findViewById(R.id.loading); 33 | return v; 34 | } 35 | 36 | public boolean onBackPressed() { 37 | return false; 38 | } 39 | 40 | public void registerReceiver(BroadcastReceiver receiver, IntentFilter filter) { 41 | if (mParent != null) 42 | mParent.registerReceiver(receiver, filter); 43 | } 44 | 45 | public void unregisterReceiver(BroadcastReceiver receiver) { 46 | if (mParent != null) 47 | mParent.unregisterReceiver(receiver); 48 | } 49 | 50 | public void registerContentObserver(Uri uri, boolean notifyForDescendents, ContentObserver observer) { 51 | if (mParent != null) 52 | mParent.getContentResolver().registerContentObserver(uri, notifyForDescendents, observer); 53 | } 54 | 55 | public void unregisterContentObserver(ContentObserver observer) { 56 | if (mParent != null) 57 | mParent.getContentResolver().unregisterContentObserver(observer); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/com/nmbb/oplayer/ui/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.nmbb.oplayer.ui; 2 | 3 | 4 | import android.content.Intent; 5 | import android.os.Bundle; 6 | import android.os.Environment; 7 | import android.support.v4.app.Fragment; 8 | import android.support.v4.app.FragmentActivity; 9 | import android.support.v4.app.FragmentPagerAdapter; 10 | import android.support.v4.view.ViewPager; 11 | import android.view.View; 12 | import android.view.View.OnClickListener; 13 | import android.widget.RadioButton; 14 | 15 | import com.nmbb.oplayer.OPlayerApplication; 16 | import com.nmbb.oplayer.OPreference; 17 | import com.nmbb.oplayer.R; 18 | import com.nmbb.oplayer.service.MediaScannerService; 19 | import com.nmbb.oplayer.ui.helper.FileDownloadHelper; 20 | import com.nmbb.oplayer.ui.vitamio.LibsChecker; 21 | 22 | public class MainActivity extends FragmentActivity implements OnClickListener { 23 | 24 | 25 | private ViewPager mPager; 26 | private RadioButton mRadioFile; 27 | private RadioButton mRadioOnline; 28 | public FileDownloadHelper mFileDownload; 29 | 30 | @Override 31 | protected void onCreate(Bundle savedInstanceState) { 32 | super.onCreate(savedInstanceState); 33 | 34 | if (!LibsChecker.checkVitamioLibs(this, R.string.init_decoders)) 35 | return; 36 | 37 | OPreference pref = new OPreference(this); 38 | // 首次运行,扫描SD卡 39 | if (pref.getBoolean(OPlayerApplication.PREF_KEY_FIRST, true)) { 40 | getApplicationContext().startService(new Intent(getApplicationContext(), MediaScannerService.class).putExtra(MediaScannerService.EXTRA_DIRECTORY, Environment.getExternalStorageDirectory().getAbsolutePath())); 41 | } 42 | 43 | setContentView(R.layout.fragment_pager); 44 | 45 | // ~~~~~~ 绑定控件 46 | mPager = (ViewPager) findViewById(R.id.pager); 47 | mRadioFile = (RadioButton) findViewById(R.id.radio_file); 48 | mRadioOnline = (RadioButton) findViewById(R.id.radio_online); 49 | 50 | // ~~~~~~ 绑定事件 51 | mRadioFile.setOnClickListener(this); 52 | mRadioOnline.setOnClickListener(this); 53 | mPager.setOnPageChangeListener(mPagerListener); 54 | 55 | // ~~~~~~ 绑定数据 56 | mPager.setAdapter(mAdapter); 57 | } 58 | 59 | @Override 60 | public void onBackPressed() { 61 | if (getFragmentByPosition(mPager.getCurrentItem()).onBackPressed()) 62 | return; 63 | else 64 | super.onBackPressed(); 65 | } 66 | 67 | @Override 68 | protected void onDestroy() { 69 | super.onDestroy(); 70 | if (mFileDownload != null) 71 | mFileDownload.stopALl(); 72 | } 73 | 74 | /** 查找Fragment */ 75 | private FragmentBase getFragmentByPosition(int position) { 76 | return (FragmentBase) getSupportFragmentManager().findFragmentByTag("android:switcher:" + mPager.getId() + ":" + position); 77 | } 78 | 79 | private FragmentPagerAdapter mAdapter = new FragmentPagerAdapter(getSupportFragmentManager()) { 80 | 81 | /** 仅执行一次 */ 82 | @Override 83 | public Fragment getItem(int position) { 84 | Fragment result = null; 85 | switch (position) { 86 | case 1: 87 | result = new FragmentOnline();// 在线视频 88 | break; 89 | case 0: 90 | default: 91 | result = new FragmentFileOld();// 本地视频 92 | mFileDownload = new FileDownloadHelper(((FragmentFileOld) result).mDownloadHandler); 93 | break; 94 | } 95 | return result; 96 | } 97 | 98 | @Override 99 | public int getCount() { 100 | return 2; 101 | } 102 | }; 103 | 104 | private ViewPager.SimpleOnPageChangeListener mPagerListener = new ViewPager.SimpleOnPageChangeListener() { 105 | @Override 106 | public void onPageSelected(int position) { 107 | switch (position) { 108 | case 0:// 本地视频 109 | mRadioFile.setChecked(true); 110 | break; 111 | case 1:// 在线视频 112 | mRadioOnline.setChecked(true); 113 | break; 114 | } 115 | } 116 | }; 117 | 118 | @Override 119 | public void onClick(View v) { 120 | switch (v.getId()) { 121 | case R.id.radio_file: 122 | mPager.setCurrentItem(0); 123 | break; 124 | case R.id.radio_online: 125 | mPager.setCurrentItem(1); 126 | break; 127 | } 128 | } 129 | } 130 | -------------------------------------------------------------------------------- /src/com/nmbb/oplayer/ui/PlayerActivity.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2011 VOV IO (http://vov.io/) 3 | */ 4 | 5 | package com.nmbb.oplayer.ui; 6 | 7 | import com.nmbb.oplayer.R; 8 | 9 | import io.vov.vitamio.MediaPlayer; 10 | import io.vov.vitamio.MediaPlayer.OnBufferingUpdateListener; 11 | import io.vov.vitamio.MediaPlayer.OnCompletionListener; 12 | import io.vov.vitamio.MediaPlayer.OnPreparedListener; 13 | import io.vov.vitamio.MediaPlayer.OnVideoSizeChangedListener; 14 | import android.app.Activity; 15 | import android.os.Bundle; 16 | import android.os.Environment; 17 | import android.util.Log; 18 | import android.view.SurfaceHolder; 19 | import android.view.SurfaceView; 20 | 21 | public class PlayerActivity extends Activity implements OnBufferingUpdateListener, OnCompletionListener, OnPreparedListener, OnVideoSizeChangedListener, SurfaceHolder.Callback { 22 | 23 | private static final String TAG = "MediaPlayerDemo"; 24 | private int mVideoWidth; 25 | private int mVideoHeight; 26 | private MediaPlayer mMediaPlayer; 27 | private SurfaceView mPreview; 28 | private SurfaceHolder holder; 29 | private String path = Environment.getExternalStorageDirectory() + "/Moon.mp4"; 30 | 31 | private boolean mIsVideoSizeKnown = false; 32 | private boolean mIsVideoReadyToBePlayed = false; 33 | 34 | @Override 35 | public void onCreate(Bundle icicle) { 36 | super.onCreate(icicle); 37 | setContentView(R.layout.mediaplayer); 38 | mPreview = (SurfaceView) findViewById(R.id.surface); 39 | holder = mPreview.getHolder(); 40 | holder.addCallback(this); 41 | } 42 | 43 | private void playVideo() { 44 | doCleanUp(); 45 | try { 46 | mMediaPlayer = new MediaPlayer(this); 47 | mMediaPlayer.setDataSource(path); 48 | mMediaPlayer.setDisplay(holder); 49 | mMediaPlayer.prepareAsync(); 50 | mMediaPlayer.setScreenOnWhilePlaying(true); 51 | mMediaPlayer.setOnBufferingUpdateListener(this); 52 | mMediaPlayer.setOnCompletionListener(this); 53 | mMediaPlayer.setOnPreparedListener(this); 54 | mMediaPlayer.setOnVideoSizeChangedListener(this); 55 | } catch (Exception e) { 56 | Log.e(TAG, "error: " + e.getMessage(), e); 57 | } 58 | } 59 | 60 | @Override 61 | public void onBufferingUpdate(MediaPlayer arg0, int percent) { 62 | Log.d(TAG, "onBufferingUpdate percent:" + percent); 63 | 64 | } 65 | 66 | @Override 67 | public void onCompletion(MediaPlayer arg0) { 68 | Log.d(TAG, "onCompletion called"); 69 | mMediaPlayer.release(); 70 | } 71 | 72 | @Override 73 | public void onVideoSizeChanged(MediaPlayer mp, int width, int height) { 74 | Log.v(TAG, "onVideoSizeChanged called"); 75 | if (width == 0 || height == 0) { 76 | Log.e(TAG, "invalid video width(" + width + ") or height(" + height + ")"); 77 | return; 78 | } 79 | mIsVideoSizeKnown = true; 80 | mVideoWidth = width; 81 | mVideoHeight = height; 82 | if (mIsVideoReadyToBePlayed && mIsVideoSizeKnown) { 83 | startVideoPlayback(); 84 | } 85 | } 86 | 87 | @Override 88 | public void onPrepared(MediaPlayer mediaplayer) { 89 | Log.d(TAG, "onPrepared called"); 90 | mIsVideoReadyToBePlayed = true; 91 | if (mIsVideoReadyToBePlayed && mIsVideoSizeKnown) { 92 | startVideoPlayback(); 93 | } 94 | } 95 | 96 | @Override 97 | public void surfaceChanged(SurfaceHolder surfaceholder, int i, int j, int k) { 98 | Log.d(TAG, "surfaceChanged called" + i + " " + j + " " + k); 99 | } 100 | 101 | @Override 102 | public void surfaceDestroyed(SurfaceHolder surfaceholder) { 103 | Log.d(TAG, "surfaceDestroyed called"); 104 | } 105 | 106 | @Override 107 | public void surfaceCreated(SurfaceHolder holder) { 108 | Log.d(TAG, "surfaceCreated called"); 109 | playVideo(); 110 | } 111 | 112 | @Override 113 | protected void onPause() { 114 | super.onPause(); 115 | releaseMediaPlayer(); 116 | doCleanUp(); 117 | } 118 | 119 | @Override 120 | protected void onDestroy() { 121 | super.onDestroy(); 122 | releaseMediaPlayer(); 123 | doCleanUp(); 124 | } 125 | 126 | private void releaseMediaPlayer() { 127 | if (mMediaPlayer != null) { 128 | mMediaPlayer.release(); 129 | mMediaPlayer = null; 130 | } 131 | } 132 | 133 | private void doCleanUp() { 134 | mVideoWidth = 0; 135 | mVideoHeight = 0; 136 | mIsVideoReadyToBePlayed = false; 137 | mIsVideoSizeKnown = false; 138 | } 139 | 140 | private void startVideoPlayback() { 141 | Log.v(TAG, "startVideoPlayback"); 142 | holder.setFixedSize(mVideoWidth, mVideoHeight); 143 | mMediaPlayer.start(); 144 | } 145 | } 146 | -------------------------------------------------------------------------------- /src/com/nmbb/oplayer/ui/VideoPlayerActivity.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2011 VOV IO (http://vov.io/) 3 | */ 4 | 5 | package com.nmbb.oplayer.ui; 6 | 7 | import com.nmbb.oplayer.R; 8 | import com.nmbb.oplayer.exception.Logger; 9 | import com.nmbb.oplayer.ui.vitamio.LibsChecker; 10 | 11 | import io.vov.vitamio.MediaPlayer; 12 | import io.vov.vitamio.MediaPlayer.OnCompletionListener; 13 | import io.vov.vitamio.MediaPlayer.OnInfoListener; 14 | import io.vov.vitamio.widget.MediaController; 15 | import io.vov.vitamio.widget.VideoView; 16 | import android.app.Activity; 17 | import android.content.Context; 18 | import android.content.Intent; 19 | import android.content.pm.ActivityInfo; 20 | import android.content.res.Configuration; 21 | import android.media.AudioManager; 22 | import android.net.Uri; 23 | import android.os.Bundle; 24 | import android.os.Environment; 25 | import android.os.Handler; 26 | import android.os.Message; 27 | import android.text.TextUtils; 28 | import android.view.Display; 29 | import android.view.GestureDetector.SimpleOnGestureListener; 30 | import android.view.GestureDetector; 31 | import android.view.MotionEvent; 32 | import android.view.View; 33 | import android.view.ViewGroup; 34 | import android.view.WindowManager; 35 | import android.widget.ImageView; 36 | 37 | public class VideoPlayerActivity extends Activity implements OnCompletionListener, OnInfoListener { 38 | 39 | private String mPath; 40 | private String mTitle; 41 | private VideoView mVideoView; 42 | private View mVolumeBrightnessLayout; 43 | private ImageView mOperationBg; 44 | private ImageView mOperationPercent; 45 | private AudioManager mAudioManager; 46 | /** 最大声音 */ 47 | private int mMaxVolume; 48 | /** 当前声音 */ 49 | private int mVolume = -1; 50 | /** 当前亮度 */ 51 | private float mBrightness = -1f; 52 | /** 当前缩放模式 */ 53 | private int mLayout = VideoView.VIDEO_LAYOUT_ZOOM; 54 | private GestureDetector mGestureDetector; 55 | private MediaController mMediaController; 56 | private View mLoadingView; 57 | 58 | @Override 59 | public void onCreate(Bundle bundle) { 60 | super.onCreate(bundle); 61 | 62 | // ~~~ 检测Vitamio是否解压解码包 63 | if (!LibsChecker.checkVitamioLibs(this, R.string.init_decoders)) 64 | return; 65 | 66 | // ~~~ 获取播放地址和标题 67 | Intent intent = getIntent(); 68 | mPath = intent.getStringExtra("path"); 69 | mTitle = intent.getStringExtra("title"); 70 | if (TextUtils.isEmpty(mPath)) { 71 | mPath = Environment.getExternalStorageDirectory() + "/video/你太猖狂.flv"; 72 | 73 | } else if (intent.getData() != null) 74 | mPath = intent.getData().toString(); 75 | 76 | // ~~~ 绑定控件 77 | setContentView(R.layout.videoview); 78 | mVideoView = (VideoView) findViewById(R.id.surface_view); 79 | mVolumeBrightnessLayout = findViewById(R.id.operation_volume_brightness); 80 | mOperationBg = (ImageView) findViewById(R.id.operation_bg); 81 | mOperationPercent = (ImageView) findViewById(R.id.operation_percent); 82 | mLoadingView = findViewById(R.id.video_loading); 83 | 84 | // ~~~ 绑定事件 85 | mVideoView.setOnCompletionListener(this); 86 | mVideoView.setOnInfoListener(this); 87 | 88 | // ~~~ 绑定数据 89 | mAudioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE); 90 | mMaxVolume = mAudioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC); 91 | if (mPath.startsWith("http:")) 92 | mVideoView.setVideoURI(Uri.parse(mPath)); 93 | else 94 | mVideoView.setVideoPath(mPath); 95 | 96 | //设置显示名称 97 | mMediaController = new MediaController(this); 98 | mMediaController.setFileName(mTitle); 99 | mVideoView.setMediaController(mMediaController); 100 | mVideoView.requestFocus(); 101 | 102 | mGestureDetector = new GestureDetector(this, new MyGestureListener()); 103 | setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); 104 | } 105 | 106 | @Override 107 | protected void onPause() { 108 | super.onPause(); 109 | if (mVideoView != null) 110 | mVideoView.pause(); 111 | } 112 | 113 | @Override 114 | protected void onResume() { 115 | super.onResume(); 116 | if (mVideoView != null) 117 | mVideoView.resume(); 118 | } 119 | 120 | @Override 121 | protected void onDestroy() { 122 | super.onDestroy(); 123 | if (mVideoView != null) 124 | mVideoView.stopPlayback(); 125 | } 126 | 127 | @Override 128 | public boolean onTouchEvent(MotionEvent event) { 129 | if (mGestureDetector.onTouchEvent(event)) 130 | return true; 131 | 132 | // 处理手势结束 133 | switch (event.getAction() & MotionEvent.ACTION_MASK) { 134 | case MotionEvent.ACTION_UP: 135 | endGesture(); 136 | break; 137 | } 138 | 139 | return super.onTouchEvent(event); 140 | } 141 | 142 | /** 手势结束 */ 143 | private void endGesture() { 144 | mVolume = -1; 145 | mBrightness = -1f; 146 | 147 | // 隐藏 148 | mDismissHandler.removeMessages(0); 149 | mDismissHandler.sendEmptyMessageDelayed(0, 500); 150 | } 151 | 152 | private class MyGestureListener extends SimpleOnGestureListener { 153 | 154 | /** 双击 */ 155 | @Override 156 | public boolean onDoubleTap(MotionEvent e) { 157 | if (mLayout == VideoView.VIDEO_LAYOUT_ZOOM) 158 | mLayout = VideoView.VIDEO_LAYOUT_ORIGIN; 159 | else 160 | mLayout++; 161 | if (mVideoView != null) 162 | mVideoView.setVideoLayout(mLayout, 0); 163 | return true; 164 | } 165 | 166 | /** 滑动 */ 167 | @Override 168 | public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { 169 | float mOldX = e1.getX(), mOldY = e1.getY(); 170 | int y = (int) e2.getRawY(); 171 | Display disp = getWindowManager().getDefaultDisplay(); 172 | int windowWidth = disp.getWidth(); 173 | int windowHeight = disp.getHeight(); 174 | 175 | if (mOldX > windowWidth * 4.0 / 5)// 右边滑动 176 | onVolumeSlide((mOldY - y) / windowHeight); 177 | else if (mOldX < windowWidth / 5.0)// 左边滑动 178 | onBrightnessSlide((mOldY - y) / windowHeight); 179 | 180 | return super.onScroll(e1, e2, distanceX, distanceY); 181 | } 182 | } 183 | 184 | /** 定时隐藏 */ 185 | private Handler mDismissHandler = new Handler() { 186 | @Override 187 | public void handleMessage(Message msg) { 188 | mVolumeBrightnessLayout.setVisibility(View.GONE); 189 | } 190 | }; 191 | 192 | /** 193 | * 滑动改变声音大小 194 | * 195 | * @param percent 196 | */ 197 | private void onVolumeSlide(float percent) { 198 | if (mVolume == -1) { 199 | mVolume = mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC); 200 | if (mVolume < 0) 201 | mVolume = 0; 202 | 203 | // 显示 204 | mOperationBg.setImageResource(R.drawable.video_volumn_bg); 205 | mVolumeBrightnessLayout.setVisibility(View.VISIBLE); 206 | } 207 | 208 | int index = (int) (percent * mMaxVolume) + mVolume; 209 | if (index > mMaxVolume) 210 | index = mMaxVolume; 211 | else if (index < 0) 212 | index = 0; 213 | 214 | // 变更声音 215 | mAudioManager.setStreamVolume(AudioManager.STREAM_MUSIC, index, 0); 216 | 217 | // 变更进度条 218 | ViewGroup.LayoutParams lp = mOperationPercent.getLayoutParams(); 219 | lp.width = findViewById(R.id.operation_full).getLayoutParams().width * index / mMaxVolume; 220 | mOperationPercent.setLayoutParams(lp); 221 | } 222 | 223 | /** 224 | * 滑动改变亮度 225 | * 226 | * @param percent 227 | */ 228 | private void onBrightnessSlide(float percent) { 229 | if (mBrightness < 0) { 230 | mBrightness = getWindow().getAttributes().screenBrightness; 231 | if (mBrightness <= 0.00f) 232 | mBrightness = 0.50f; 233 | if (mBrightness < 0.01f) 234 | mBrightness = 0.01f; 235 | 236 | // 显示 237 | mOperationBg.setImageResource(R.drawable.video_brightness_bg); 238 | mVolumeBrightnessLayout.setVisibility(View.VISIBLE); 239 | } 240 | WindowManager.LayoutParams lpa = getWindow().getAttributes(); 241 | lpa.screenBrightness = mBrightness + percent; 242 | if (lpa.screenBrightness > 1.0f) 243 | lpa.screenBrightness = 1.0f; 244 | else if (lpa.screenBrightness < 0.01f) 245 | lpa.screenBrightness = 0.01f; 246 | getWindow().setAttributes(lpa); 247 | 248 | ViewGroup.LayoutParams lp = mOperationPercent.getLayoutParams(); 249 | lp.width = (int) (findViewById(R.id.operation_full).getLayoutParams().width * lpa.screenBrightness); 250 | mOperationPercent.setLayoutParams(lp); 251 | } 252 | 253 | @Override 254 | public void onConfigurationChanged(Configuration newConfig) { 255 | if (mVideoView != null) 256 | mVideoView.setVideoLayout(mLayout, 0); 257 | super.onConfigurationChanged(newConfig); 258 | } 259 | 260 | @Override 261 | public void onCompletion(MediaPlayer player) { 262 | finish(); 263 | } 264 | 265 | private void stopPlayer() { 266 | if (mVideoView != null) 267 | mVideoView.pause(); 268 | } 269 | 270 | private void startPlayer() { 271 | if (mVideoView != null) 272 | mVideoView.start(); 273 | } 274 | 275 | private boolean isPlaying() { 276 | return mVideoView != null && mVideoView.isPlaying(); 277 | } 278 | 279 | /** 是否需要自动恢复播放,用于自动暂停,恢复播放 */ 280 | private boolean needResume; 281 | 282 | @Override 283 | public boolean onInfo(MediaPlayer arg0, int arg1, int arg2) { 284 | switch (arg1) { 285 | case MediaPlayer.MEDIA_INFO_BUFFERING_START: 286 | //开始缓存,暂停播放 287 | if (isPlaying()) { 288 | stopPlayer(); 289 | needResume = true; 290 | } 291 | mLoadingView.setVisibility(View.VISIBLE); 292 | break; 293 | case MediaPlayer.MEDIA_INFO_BUFFERING_END: 294 | //缓存完成,继续播放 295 | if (needResume) 296 | startPlayer(); 297 | mLoadingView.setVisibility(View.GONE); 298 | break; 299 | case MediaPlayer.MEDIA_INFO_DOWNLOAD_RATE_CHANGED: 300 | //显示 下载速度 301 | Logger.e("download rate:" + arg2); 302 | //mListener.onDownloadRateChanged(arg2); 303 | break; 304 | } 305 | return true; 306 | } 307 | } 308 | -------------------------------------------------------------------------------- /src/com/nmbb/oplayer/ui/adapter/FileAdapter.java: -------------------------------------------------------------------------------- 1 | package com.nmbb.oplayer.ui.adapter; 2 | 3 | import java.util.ArrayList; 4 | 5 | import com.nmbb.oplayer.R; 6 | import com.nmbb.oplayer.po.PFile; 7 | import com.nmbb.oplayer.util.FileUtils; 8 | 9 | import android.content.Context; 10 | import android.database.Cursor; 11 | import android.view.LayoutInflater; 12 | import android.view.View; 13 | import android.view.ViewGroup; 14 | import android.widget.CursorAdapter; 15 | import android.widget.ImageView; 16 | import android.widget.TextView; 17 | 18 | public class FileAdapter extends CursorAdapter { 19 | 20 | private LayoutInflater mInflater; 21 | private ArrayList mKey = new ArrayList(); 22 | 23 | public FileAdapter(Context context, Cursor c) { 24 | super(context, c, false); 25 | mInflater = LayoutInflater.from(context); 26 | } 27 | 28 | @Override 29 | public View newView(Context context, Cursor cursor, ViewGroup parent) { 30 | return mInflater.inflate(R.layout.fragment_file_item, null); 31 | } 32 | 33 | @Override 34 | public void changeCursor(Cursor cursor) { 35 | initKeys(cursor); 36 | super.changeCursor(cursor); 37 | } 38 | 39 | private void initKeys(Cursor c) { 40 | if (c != null && !c.isClosed()) { 41 | mKey.clear(); 42 | while (c.moveToNext()) { 43 | String title_key = c.getString(2); 44 | mKey.add(title_key.charAt(0)); 45 | } 46 | } 47 | } 48 | 49 | /** 根据拼音名称获取位置 */ 50 | public int getPositionByName(char key) { 51 | return mKey.indexOf(key); 52 | } 53 | 54 | @Override 55 | public PFile getItem(int position) { 56 | if (getCursor().moveToPosition(position)) 57 | return new PFile(getCursor()); 58 | else 59 | return null; 60 | } 61 | 62 | @Override 63 | public void bindView(View convertView, Context context, Cursor cursor) { 64 | final PFile f = new PFile(cursor); 65 | //显示名称 66 | ((TextView) convertView.findViewById(R.id.title)).setText(f.title); 67 | 68 | //显示文件大小 69 | String file_size; 70 | if (f.temp_file_size > 0) { 71 | file_size = FileUtils.showFileSize(f.temp_file_size) + " / " + FileUtils.showFileSize(f.file_size); 72 | } else { 73 | file_size = FileUtils.showFileSize(f.file_size); 74 | } 75 | ((TextView) convertView.findViewById(R.id.file_size)).setText(file_size); 76 | 77 | //显示缩略图 78 | ((ImageView) convertView.findViewById(R.id.thumbnail)).setImageBitmap(f.getThumb(context)); 79 | } 80 | 81 | } 82 | -------------------------------------------------------------------------------- /src/com/nmbb/oplayer/ui/adapter/FileDownloadAdapter.java: -------------------------------------------------------------------------------- 1 | package com.nmbb.oplayer.ui.adapter; 2 | 3 | import java.util.ArrayList; 4 | import java.util.HashMap; 5 | 6 | import android.content.Context; 7 | import android.view.LayoutInflater; 8 | import android.view.View; 9 | import android.view.ViewGroup; 10 | import android.widget.ImageView; 11 | import android.widget.TextView; 12 | 13 | import com.nmbb.oplayer.R; 14 | import com.nmbb.oplayer.po.PFile; 15 | import com.nmbb.oplayer.ui.base.ArrayAdapter; 16 | import com.nmbb.oplayer.util.FileUtils; 17 | 18 | public class FileDownloadAdapter extends ArrayAdapter { 19 | private HashMap maps = new HashMap(); 20 | 21 | private LayoutInflater mInflater; 22 | 23 | public FileDownloadAdapter(Context ctx, ArrayList l) { 24 | super(ctx, l); 25 | mInflater = LayoutInflater.from(ctx); 26 | maps.clear(); 27 | } 28 | 29 | @Override 30 | public View getView(int position, View convertView, ViewGroup parent) { 31 | final PFile f = getItem(position); 32 | if (convertView == null) { 33 | convertView = mInflater.inflate(R.layout.fragment_file_item, null); 34 | } 35 | ((TextView) convertView.findViewById(R.id.title)).setText(f.title); 36 | 37 | //显示文件大小 38 | String file_size; 39 | if (f.temp_file_size > 0) { 40 | file_size = FileUtils.showFileSize(f.temp_file_size) + " / " + FileUtils.showFileSize(f.file_size); 41 | } else { 42 | file_size = FileUtils.showFileSize(f.file_size); 43 | } 44 | ((TextView) convertView.findViewById(R.id.file_size)).setText(file_size); 45 | 46 | //显示进度表 47 | final ImageView status = (ImageView) convertView.findViewById(R.id.status); 48 | if (f.status > -1) { 49 | int resStauts = getStatusImage(f.status); 50 | if (resStauts > 0) { 51 | if (status.getVisibility() != View.VISIBLE) 52 | status.setVisibility(View.VISIBLE); 53 | status.setImageResource(resStauts); 54 | } 55 | } else { 56 | if (status.getVisibility() != View.GONE) 57 | status.setVisibility(View.GONE); 58 | } 59 | return convertView; 60 | } 61 | 62 | private int getStatusImage(int status) { 63 | int resStauts = -1; 64 | switch (status) { 65 | case 0: 66 | resStauts = R.drawable.down_btn_0; 67 | break; 68 | case 1: 69 | resStauts = R.drawable.down_btn_1; 70 | break; 71 | case 2: 72 | resStauts = R.drawable.down_btn_2; 73 | break; 74 | case 3: 75 | resStauts = R.drawable.down_btn_3; 76 | break; 77 | case 4: 78 | resStauts = R.drawable.down_btn_4; 79 | break; 80 | case 5: 81 | resStauts = R.drawable.down_btn_5; 82 | break; 83 | case 6: 84 | resStauts = R.drawable.down_btn_6; 85 | break; 86 | case 7: 87 | resStauts = R.drawable.down_btn_7; 88 | break; 89 | case 8: 90 | resStauts = R.drawable.down_btn_8; 91 | break; 92 | case 9: 93 | resStauts = R.drawable.down_btn_9; 94 | break; 95 | case 10: 96 | resStauts = R.drawable.down_btn_10; 97 | break; 98 | } 99 | return resStauts; 100 | } 101 | 102 | public void add(PFile item, String url) { 103 | super.add(item); 104 | if (!maps.containsKey(url)) 105 | maps.put(url, item); 106 | } 107 | 108 | public void delete(int position) { 109 | synchronized (mLock) { 110 | mObjects.remove(position); 111 | } 112 | notifyDataSetChanged(); 113 | } 114 | 115 | public PFile getItem(String url) { 116 | return maps.get(url); 117 | } 118 | } 119 | -------------------------------------------------------------------------------- /src/com/nmbb/oplayer/ui/base/ArrayAdapter.java: -------------------------------------------------------------------------------- 1 | package com.nmbb.oplayer.ui.base; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Arrays; 5 | import java.util.Collection; 6 | import java.util.List; 7 | 8 | import android.content.Context; 9 | import android.view.LayoutInflater; 10 | import android.widget.BaseAdapter; 11 | 12 | public abstract class ArrayAdapter extends BaseAdapter { 13 | 14 | // 数据 15 | protected ArrayList mObjects; 16 | protected LayoutInflater mInflater; 17 | protected final Object mLock = new Object(); 18 | 19 | public ArrayAdapter(final Context ctx, final ArrayList l) { 20 | mObjects = l == null ? new ArrayList() : l; 21 | mInflater = (LayoutInflater) ctx.getSystemService(Context.LAYOUT_INFLATER_SERVICE); 22 | } 23 | 24 | public ArrayAdapter(final Context ctx, final T... l) { 25 | mObjects = new ArrayList(); 26 | mObjects.addAll(Arrays.asList(l)); 27 | mInflater = (LayoutInflater) ctx.getSystemService(Context.LAYOUT_INFLATER_SERVICE); 28 | } 29 | 30 | public ArrayAdapter(final Context ctx, final List l) { 31 | mObjects = new ArrayList(); 32 | if (l != null) 33 | mObjects.addAll(l); 34 | mInflater = (LayoutInflater) ctx.getSystemService(Context.LAYOUT_INFLATER_SERVICE); 35 | } 36 | 37 | public ArrayAdapter(final Context ctx, final Collection l) { 38 | mObjects = new ArrayList(); 39 | if (l != null) 40 | mObjects.addAll(l); 41 | mInflater = (LayoutInflater) ctx.getSystemService(Context.LAYOUT_INFLATER_SERVICE); 42 | } 43 | 44 | @Override 45 | public int getCount() { 46 | return mObjects.size(); 47 | } 48 | 49 | @Override 50 | public T getItem(int position) { 51 | return mObjects.get(position); 52 | } 53 | 54 | @Override 55 | public long getItemId(int position) { 56 | return 0; 57 | } 58 | 59 | public void add(T item) { 60 | this.mObjects.add(item); 61 | } 62 | 63 | public void replace(ArrayList newObjects) { 64 | if (newObjects == null) 65 | newObjects = new ArrayList(); 66 | this.mObjects = newObjects; 67 | } 68 | 69 | /** 70 | * Adds the specified items at the end of the array. 71 | * 72 | * @param items The items to add at the end of the array. 73 | */ 74 | public void addAll(T... items) { 75 | ArrayList values = this.mObjects; 76 | for (T item : items) { 77 | values.add(item); 78 | } 79 | this.mObjects = values; 80 | } 81 | 82 | /** 83 | * 84 | * @param collection 85 | */ 86 | public void addAll(Collection collection) { 87 | mObjects.addAll(collection); 88 | } 89 | 90 | /** 91 | * Remove all elements from the list. 92 | */ 93 | public void clear() { 94 | mObjects.clear(); 95 | } 96 | 97 | /** 98 | * 获取所有数据 99 | * 100 | * @return 101 | */ 102 | public final ArrayList getAll() { 103 | return mObjects; 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /src/com/nmbb/oplayer/ui/base/FilterArrayAdapter.java: -------------------------------------------------------------------------------- 1 | package com.nmbb.oplayer.ui.base; 2 | 3 | import java.util.ArrayList; 4 | 5 | import android.content.Context; 6 | import android.graphics.Color; 7 | import android.text.SpannableStringBuilder; 8 | import android.text.Spanned; 9 | import android.text.TextUtils; 10 | import android.text.style.ForegroundColorSpan; 11 | import android.widget.Filter; 12 | 13 | public abstract class FilterArrayAdapter extends ArrayAdapter { 14 | 15 | private String mFilterString; 16 | private Object mLock = new Object(); 17 | private ListFilter mFilter; 18 | private ArrayList mOriginalValues; 19 | protected final ForegroundColorSpan redSpan = new ForegroundColorSpan( 20 | Color.RED); 21 | 22 | 23 | public FilterArrayAdapter(Context ctx, ArrayList l) { 24 | super(ctx, l); 25 | } 26 | 27 | public Filter getFilter() { 28 | if (mFilter == null) { 29 | mFilter = new ListFilter(); 30 | } 31 | return mFilter; 32 | } 33 | 34 | /** 35 | * 获取搜索字符串 36 | * 37 | * @return 38 | */ 39 | public String getFilterString() { 40 | return mFilterString; 41 | } 42 | 43 | /** 44 | * 高亮文本 45 | * 46 | * @param text 47 | * 文本 48 | * @return 49 | */ 50 | public CharSequence highlightText(String text) { 51 | CharSequence result; 52 | final String key = mFilterString; 53 | int index = TextUtils.isEmpty(key) ? -1 : text.toLowerCase().indexOf(key.toLowerCase()); 54 | if (index > -1) { 55 | SpannableStringBuilder nameStyle = new SpannableStringBuilder(text); 56 | nameStyle.setSpan(redSpan, index, index + key.length(), 57 | Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); 58 | result = nameStyle; 59 | } else 60 | result = text; 61 | return result; 62 | } 63 | 64 | /** 65 | * 过滤 66 | * 67 | * @param values 68 | * @param prefixString 69 | * @return 70 | */ 71 | public abstract ArrayList filter(final ArrayList values, CharSequence prefixString); 72 | 73 | /** 74 | *

75 | * An array filter constrains the content of the array adapter with a prefix. 76 | * Each item that does not start with the supplied prefix is removed from the 77 | * list. 78 | *

79 | */ 80 | private class ListFilter extends Filter { 81 | @Override 82 | protected FilterResults performFiltering(CharSequence prefix) { 83 | FilterResults results = new FilterResults(); 84 | 85 | if (mOriginalValues == null) { 86 | synchronized (mLock) { 87 | mOriginalValues = new ArrayList(mObjects); 88 | } 89 | } 90 | 91 | if (prefix == null || prefix.length() == 0) { 92 | mFilterString = ""; 93 | synchronized (mLock) { 94 | ArrayList list = new ArrayList(mOriginalValues); 95 | results.values = list; 96 | results.count = list.size(); 97 | } 98 | } else { 99 | mFilterString = prefix.toString(); 100 | final ArrayList newValues = FilterArrayAdapter.this.filter(mOriginalValues, prefix); 101 | results.values = newValues; 102 | results.count = newValues.size(); 103 | } 104 | 105 | return results; 106 | } 107 | 108 | @SuppressWarnings("unchecked") 109 | @Override 110 | protected void publishResults(CharSequence constraint, FilterResults results) { 111 | mObjects = (ArrayList) results.values; 112 | 113 | //filterComplate(); 114 | 115 | if (results.count > 0) { 116 | notifyDataSetChanged(); 117 | } else { 118 | notifyDataSetInvalidated(); 119 | } 120 | } 121 | } 122 | 123 | } 124 | -------------------------------------------------------------------------------- /src/com/nmbb/oplayer/ui/base/ThreadPool.java: -------------------------------------------------------------------------------- 1 | package com.nmbb.oplayer.ui.base; 2 | 3 | import java.util.concurrent.LinkedBlockingQueue; 4 | import java.util.concurrent.ThreadFactory; 5 | import java.util.concurrent.ThreadPoolExecutor; 6 | import java.util.concurrent.TimeUnit; 7 | import java.util.concurrent.atomic.AtomicBoolean; 8 | import java.util.concurrent.atomic.AtomicInteger; 9 | 10 | import android.os.Build; 11 | 12 | public class ThreadPool { 13 | private AtomicBoolean mStopped = new AtomicBoolean(Boolean.FALSE); 14 | private ThreadPoolExecutor mQueue; 15 | 16 | public ThreadPool() { 17 | if (Build.VERSION.SDK_INT > 8) { 18 | mQueue = new ThreadPoolExecutor(10, 10, 60, TimeUnit.SECONDS, new LinkedBlockingQueue(), sThreadFactory); 19 | mQueue.allowCoreThreadTimeOut(true); 20 | } else { 21 | mQueue = new ThreadPoolExecutor(2, 10, 60, TimeUnit.SECONDS, new LinkedBlockingQueue(), sThreadFactory); 22 | } 23 | } 24 | 25 | public void start(Runnable run) { 26 | mQueue.execute(run); 27 | } 28 | 29 | public void stop() { 30 | if (!mStopped.get()) { 31 | mQueue.shutdownNow(); 32 | mStopped.set(Boolean.TRUE); 33 | } 34 | } 35 | 36 | private static final ThreadFactory sThreadFactory = new ThreadFactory() { 37 | private final AtomicInteger mCount = new AtomicInteger(1); 38 | 39 | @Override 40 | public Thread newThread(Runnable r) { 41 | return new Thread(r, "ThreadPool #" + mCount.getAndIncrement()); 42 | } 43 | }; 44 | } 45 | -------------------------------------------------------------------------------- /src/com/nmbb/oplayer/ui/helper/FileDownloadHelper.java: -------------------------------------------------------------------------------- 1 | package com.nmbb.oplayer.ui.helper; 2 | 3 | import java.io.File; 4 | import java.io.FileInputStream; 5 | import java.io.FileOutputStream; 6 | import java.io.IOException; 7 | import java.io.InputStream; 8 | import java.util.HashMap; 9 | import java.util.Timer; 10 | import java.util.TimerTask; 11 | 12 | import org.apache.http.HttpEntity; 13 | import org.apache.http.HttpResponse; 14 | import org.apache.http.client.HttpClient; 15 | import org.apache.http.client.methods.HttpGet; 16 | import org.apache.http.impl.client.DefaultHttpClient; 17 | 18 | import android.os.Handler; 19 | import android.util.Log; 20 | 21 | import com.nmbb.oplayer.ui.base.ThreadPool; 22 | 23 | public class FileDownloadHelper { 24 | private static final String TAG = "FileDownloadHelper"; 25 | /** 线程池 */ 26 | private ThreadPool mPool = new ThreadPool(); 27 | /** 开始下载 */ 28 | public static final int MESSAGE_START = 0; 29 | /** 更新进度 */ 30 | public static final int MESSAGE_PROGRESS = 1; 31 | /** 下载结束 */ 32 | public static final int MESSAGE_STOP = 2; 33 | /** 下载出错 */ 34 | public static final int MESSAGE_ERROR = 3; 35 | /** 中途终止 */ 36 | private volatile boolean mIsStop = false; 37 | private Handler mHandler; 38 | public volatile HashMap mDownloadUrls = new HashMap(); 39 | 40 | public FileDownloadHelper(Handler handler) { 41 | if (handler == null) 42 | throw new IllegalArgumentException("handler不能为空!"); 43 | 44 | this.mHandler = handler; 45 | } 46 | 47 | public void stopALl() { 48 | mIsStop = true; 49 | mPool.stop(); 50 | } 51 | 52 | /** 53 | * 下载一个新的文件 54 | * 55 | * @param url 56 | * @param savePath 57 | */ 58 | public void newDownloadFile(final String url, final String savePath) { 59 | if (mDownloadUrls.containsKey(url)) 60 | return; 61 | else 62 | mDownloadUrls.put(url, savePath); 63 | mPool.start(new Runnable() { 64 | 65 | @Override 66 | public void run() { 67 | mHandler.sendMessage(mHandler.obtainMessage(MESSAGE_START, url)); 68 | HttpClient client = new DefaultHttpClient(); 69 | HttpGet get = new HttpGet(url); 70 | InputStream inputStream = null; 71 | FileOutputStream outputStream = null; 72 | try { 73 | HttpResponse response = client.execute(get); 74 | HttpEntity entity = response.getEntity(); 75 | final int size = (int) entity.getContentLength(); 76 | inputStream = entity.getContent(); 77 | if (size > 0 && inputStream != null) { 78 | outputStream = new FileOutputStream(savePath); 79 | int ch = -1; 80 | byte[] buf = new byte[1024]; 81 | //每秒更新一次进度 82 | new Timer().schedule(new TimerTask() { 83 | 84 | @Override 85 | public void run() { 86 | try { 87 | FileInputStream fis = new FileInputStream(new File(savePath)); 88 | int downloadedSize = fis.available(); 89 | if (downloadedSize >= size) 90 | cancel(); 91 | mHandler.sendMessage(mHandler.obtainMessage(MESSAGE_PROGRESS, downloadedSize, size, url)); 92 | } catch (Exception e) { 93 | 94 | } 95 | } 96 | }, 50, 1000); 97 | 98 | while ((ch = inputStream.read(buf)) != -1 && !mIsStop) { 99 | outputStream.write(buf, 0, ch); 100 | } 101 | outputStream.flush(); 102 | } 103 | } catch (Exception e) { 104 | Log.e(TAG, e.getMessage(), e); 105 | mHandler.sendMessage(mHandler.obtainMessage(MESSAGE_ERROR, url + ":" + e.getMessage())); 106 | } finally { 107 | try { 108 | if (outputStream != null) 109 | outputStream.close(); 110 | } catch (IOException ex) { 111 | } 112 | try { 113 | if (inputStream != null) 114 | inputStream.close(); 115 | } catch (IOException ex) { 116 | } 117 | } 118 | mDownloadUrls.remove(url); 119 | mHandler.sendMessage(mHandler.obtainMessage(MESSAGE_STOP, url)); 120 | } 121 | }); 122 | } 123 | } 124 | -------------------------------------------------------------------------------- /src/com/nmbb/oplayer/ui/helper/VideoHelper.java: -------------------------------------------------------------------------------- 1 | package com.nmbb.oplayer.ui.helper; 2 | 3 | import java.io.ByteArrayOutputStream; 4 | import java.io.IOException; 5 | import java.io.InputStream; 6 | import java.net.HttpURLConnection; 7 | import java.net.MalformedURLException; 8 | import java.net.URL; 9 | 10 | import com.nmbb.oplayer.util.StringUtils; 11 | 12 | import android.os.Build; 13 | import android.text.Html; 14 | 15 | public class VideoHelper { 16 | 17 | /** 在线视频对象 */ 18 | public static class OnlineVideo { 19 | public String url; 20 | public String title; 21 | 22 | public OnlineVideo() { 23 | } 24 | 25 | public OnlineVideo(String url) { 26 | this.url = url; 27 | } 28 | } 29 | 30 | /** 获取优酷视频m3u8地址 */ 31 | public static OnlineVideo getYoukuVideo(String url) { 32 | OnlineVideo result = null; 33 | String vid = ""; 34 | //提取vid 35 | vid = substring(url, "vid=", "&"); 36 | 37 | if (!StringUtils.isEmpty(vid)) { 38 | String title = ""; 39 | String html = connect(url); 40 | if (!StringUtils.isEmpty(html)) { 41 | //获取title 42 | title = substring(html, "", ""); 43 | title = substring(title, "", "-优酷3G", title); 44 | title = Html.fromHtml(title).toString(); 45 | } 46 | 47 | result = new OnlineVideo(); 48 | result.url = "http://v.youku.com/player/getRealM3U8/vid/" + vid + "/type//video.m3u8"; 49 | result.title = title; 50 | } 51 | return result; 52 | } 53 | 54 | public static String substring(String search, String start, String end, String defaultValue) { 55 | int s_len = start.length(); 56 | int s_pos = StringUtils.isEmpty(start) ? 0 : search.indexOf(start); 57 | if (s_pos > -1) { 58 | int end_pos = StringUtils.isEmpty(end) ? -1 : search.indexOf(end, s_pos + s_len); 59 | if (end_pos > -1) 60 | return search.substring(s_pos + start.length(), end_pos); 61 | else 62 | return search.substring(s_pos + start.length()); 63 | } 64 | return defaultValue; 65 | } 66 | 67 | public static String substring(String search, String start, String end) { 68 | return substring(search, start, end, ""); 69 | } 70 | 71 | private static String connect(String uri) { 72 | return connect(uri, "UTF8"); 73 | } 74 | 75 | private static String connect(String uri, String charsetName) { 76 | String result = ""; 77 | try { 78 | URL url = new URL(uri); 79 | HttpURLConnection conn = (HttpURLConnection) url.openConnection(); 80 | conn.setConnectTimeout(5 * 1000); 81 | if (Integer.parseInt(Build.VERSION.SDK) < 8) { 82 | System.setProperty("http.keepAlive", "false"); 83 | } 84 | if (conn.getResponseCode() == 200) { 85 | InputStream is = conn.getInputStream(); 86 | result = readData(is, charsetName); 87 | } 88 | conn.disconnect(); 89 | } catch (MalformedURLException e) { 90 | } catch (IOException e) { 91 | } catch (Exception e) { 92 | } 93 | return result; 94 | } 95 | 96 | public static String readData(InputStream inSream, String charsetName) throws Exception { 97 | ByteArrayOutputStream outStream = new ByteArrayOutputStream(); 98 | byte[] buffer = new byte[1024]; 99 | int len = -1; 100 | while ((len = inSream.read(buffer)) != -1) { 101 | outStream.write(buffer, 0, len); 102 | } 103 | byte[] data = outStream.toByteArray(); 104 | outStream.close(); 105 | inSream.close(); 106 | return new String(data, charsetName); 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /src/com/nmbb/oplayer/ui/helper/XmlReaderHelper.java: -------------------------------------------------------------------------------- 1 | package com.nmbb.oplayer.ui.helper; 2 | 3 | import java.io.IOException; 4 | import java.util.ArrayList; 5 | 6 | import javax.xml.parsers.DocumentBuilder; 7 | import javax.xml.parsers.DocumentBuilderFactory; 8 | import javax.xml.parsers.ParserConfigurationException; 9 | 10 | import org.w3c.dom.Document; 11 | import org.w3c.dom.Element; 12 | import org.w3c.dom.NamedNodeMap; 13 | import org.w3c.dom.Node; 14 | import org.w3c.dom.NodeList; 15 | import org.xml.sax.SAXException; 16 | 17 | import android.content.Context; 18 | 19 | import com.nmbb.oplayer.po.OnlineVideo; 20 | 21 | /** 从XML读取电视台节目 */ 22 | public class XmlReaderHelper { 23 | 24 | /** 获取所有电视分类 */ 25 | public static ArrayList getAllCategory(final Context context) { 26 | ArrayList result = new ArrayList(); 27 | DocumentBuilderFactory docBuilderFactory = null; 28 | DocumentBuilder docBuilder = null; 29 | Document doc = null; 30 | try { 31 | docBuilderFactory = DocumentBuilderFactory.newInstance(); 32 | docBuilder = docBuilderFactory.newDocumentBuilder(); 33 | // xml file 放到 assets目录中的 34 | doc = docBuilder.parse(context.getResources().getAssets() 35 | .open("online.xml")); 36 | // root element 37 | Element root = doc.getDocumentElement(); 38 | NodeList nodeList = root.getElementsByTagName("category"); 39 | for (int i = 0; i < nodeList.getLength(); i++) { 40 | Node node = nodeList.item(i);// category 41 | OnlineVideo ov = new OnlineVideo(); 42 | NamedNodeMap attr = node.getAttributes(); 43 | ov.title = attr.getNamedItem("name").getNodeValue(); 44 | ov.id = attr.getNamedItem("id").getNodeValue(); 45 | ov.category = 1; 46 | ov.level = 2; 47 | ov.is_category = true; 48 | result.add(ov); 49 | // Read Node 50 | } 51 | } catch (IOException e) { 52 | } catch (SAXException e) { 53 | } catch (ParserConfigurationException e) { 54 | } finally { 55 | doc = null; 56 | docBuilder = null; 57 | docBuilderFactory = null; 58 | } 59 | return result; 60 | } 61 | 62 | /** 读取分类下所有电视地址 */ 63 | public static ArrayList getVideos(final Context context, 64 | String categoryId) { 65 | ArrayList result = new ArrayList(); 66 | DocumentBuilderFactory docBuilderFactory = null; 67 | DocumentBuilder docBuilder = null; 68 | Document doc = null; 69 | try { 70 | docBuilderFactory = DocumentBuilderFactory.newInstance(); 71 | docBuilder = docBuilderFactory.newDocumentBuilder(); 72 | // xml file 放到 assets目录中的 73 | doc = docBuilder.parse(context.getResources().getAssets() 74 | .open("online.xml")); 75 | // root element 76 | Element root = doc.getElementById(categoryId); 77 | if (root != null) { 78 | NodeList nodeList = root.getChildNodes(); 79 | for (int i = 0, j = nodeList.getLength(); i < j; i++) { 80 | Node baseNode = nodeList.item(i); 81 | 82 | if (!"item".equals(baseNode.getNodeName())) 83 | continue; 84 | String id = baseNode.getFirstChild().getNodeValue(); 85 | if (id == null) 86 | continue; 87 | OnlineVideo ov = new OnlineVideo(); 88 | ov.id = id; 89 | 90 | Element el = doc.getElementById(ov.id); 91 | if (el != null) { 92 | ov.title = el.getAttribute("title"); 93 | ov.icon_url = el.getAttribute("image"); 94 | ov.level = 3; 95 | ov.category = 1; 96 | NodeList nodes = el.getChildNodes(); 97 | for (int m = 0, n = nodes.getLength(); m < n; m++) { 98 | Node node = nodes.item(m); 99 | if (!"ref".equals(node.getNodeName())) 100 | continue; 101 | String href = node.getAttributes() 102 | .getNamedItem("href").getNodeValue(); 103 | if (ov.url == null) { 104 | ov.url = href; 105 | } else { 106 | if (ov.backup_url == null) 107 | ov.backup_url = new ArrayList(); 108 | ov.backup_url.add(href); 109 | } 110 | } 111 | if (ov.url != null) 112 | result.add(ov); 113 | } 114 | } 115 | } 116 | } catch (IOException e) { 117 | e.printStackTrace(); 118 | } catch (SAXException e) { 119 | e.printStackTrace(); 120 | } catch (ParserConfigurationException e) { 121 | e.printStackTrace(); 122 | } finally { 123 | doc = null; 124 | docBuilder = null; 125 | docBuilderFactory = null; 126 | } 127 | return result; 128 | } 129 | } 130 | -------------------------------------------------------------------------------- /src/com/nmbb/oplayer/ui/player/CommonGestures.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2012 YIXIA.COM 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.nmbb.oplayer.ui.player; 18 | 19 | import android.annotation.SuppressLint; 20 | import android.app.Activity; 21 | import android.support.v4.view.GestureDetectorCompat; 22 | import android.view.GestureDetector.SimpleOnGestureListener; 23 | import android.view.MotionEvent; 24 | import android.view.ScaleGestureDetector; 25 | 26 | import com.nmbb.oplayer.util.DeviceUtils; 27 | 28 | public class CommonGestures { 29 | public static final int SCALE_STATE_BEGIN = 0; 30 | public static final int SCALE_STATE_SCALEING = 1; 31 | public static final int SCALE_STATE_END = 2; 32 | 33 | private boolean mGestureEnabled; 34 | 35 | private GestureDetectorCompat mDoubleTapGestureDetector; 36 | private GestureDetectorCompat mTapGestureDetector; 37 | private ScaleGestureDetector mScaleDetector; 38 | 39 | private Activity mContext; 40 | 41 | public CommonGestures(Activity ctx) { 42 | mContext = ctx; 43 | mDoubleTapGestureDetector = new GestureDetectorCompat(mContext, new DoubleTapGestureListener()); 44 | mTapGestureDetector = new GestureDetectorCompat(mContext, new TapGestureListener()); 45 | mScaleDetector = new ScaleGestureDetector(mContext, new ScaleDetectorListener()); 46 | } 47 | 48 | public boolean onTouchEvent(MotionEvent event) { 49 | if (mListener == null) 50 | return false; 51 | 52 | if (mTapGestureDetector.onTouchEvent(event)) 53 | return true; 54 | 55 | if (event.getPointerCount() > 1) { 56 | try { 57 | if (mScaleDetector != null && mScaleDetector.onTouchEvent(event)) 58 | return true; 59 | } catch (Exception e) { 60 | e.printStackTrace(); 61 | } 62 | } 63 | 64 | if (mDoubleTapGestureDetector.onTouchEvent(event)) 65 | return true; 66 | 67 | switch (event.getAction() & MotionEvent.ACTION_MASK) { 68 | case MotionEvent.ACTION_UP: 69 | mListener.onGestureEnd(); 70 | break; 71 | } 72 | 73 | return false; 74 | } 75 | 76 | private class TapGestureListener extends SimpleOnGestureListener { 77 | @Override 78 | public boolean onSingleTapConfirmed(MotionEvent event) { 79 | if (mListener != null) 80 | mListener.onSingleTap(); 81 | return true; 82 | } 83 | 84 | @Override 85 | public void onLongPress(MotionEvent e) { 86 | if (mListener != null && mGestureEnabled) 87 | mListener.onLongPress(); 88 | } 89 | } 90 | 91 | @SuppressLint("NewApi") 92 | private class ScaleDetectorListener implements ScaleGestureDetector.OnScaleGestureListener { 93 | @Override 94 | public boolean onScale(ScaleGestureDetector detector) { 95 | if (mListener != null && mGestureEnabled) 96 | mListener.onScale(detector.getScaleFactor(), SCALE_STATE_SCALEING); 97 | return true; 98 | } 99 | 100 | @Override 101 | public void onScaleEnd(ScaleGestureDetector detector) { 102 | if (mListener != null && mGestureEnabled) 103 | mListener.onScale(0F, SCALE_STATE_END); 104 | } 105 | 106 | @Override 107 | public boolean onScaleBegin(ScaleGestureDetector detector) { 108 | if (mListener != null && mGestureEnabled) 109 | mListener.onScale(0F, SCALE_STATE_BEGIN); 110 | return true; 111 | } 112 | } 113 | 114 | private class DoubleTapGestureListener extends SimpleOnGestureListener { 115 | private boolean mDown = false; 116 | 117 | @Override 118 | public boolean onDown(MotionEvent event) { 119 | mDown = true; 120 | return super.onDown(event); 121 | } 122 | 123 | @Override 124 | public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { 125 | if (mListener != null && mGestureEnabled && e1 != null && e2 != null) { 126 | if (mDown) { 127 | mListener.onGestureBegin(); 128 | mDown = false; 129 | } 130 | float mOldX = e1.getX(), mOldY = e1.getY(); 131 | int windowWidth = DeviceUtils.getScreenWidth(mContext); 132 | int windowHeight = DeviceUtils.getScreenHeight(mContext); 133 | if (Math.abs(e2.getY(0) - mOldY) * 2 > Math.abs(e2.getX(0) - mOldX)) { 134 | if (mOldX > windowWidth * 4.0 / 5) { 135 | mListener.onRightSlide((mOldY - e2.getY(0)) / windowHeight); 136 | } else if (mOldX < windowWidth / 5.0) { 137 | mListener.onLeftSlide((mOldY - e2.getY(0)) / windowHeight); 138 | } 139 | } 140 | } 141 | return super.onScroll(e1, e2, distanceX, distanceY); 142 | } 143 | 144 | @Override 145 | public boolean onDoubleTap(MotionEvent event) { 146 | if (mListener != null && mGestureEnabled) 147 | mListener.onDoubleTap(); 148 | return super.onDoubleTap(event); 149 | } 150 | } 151 | 152 | public void setTouchListener(TouchListener l, boolean enable) { 153 | mListener = l; 154 | mGestureEnabled = enable; 155 | } 156 | 157 | private TouchListener mListener; 158 | 159 | public interface TouchListener { 160 | public void onGestureBegin(); 161 | 162 | public void onGestureEnd(); 163 | 164 | public void onLeftSlide(float percent); 165 | 166 | public void onRightSlide(float percent); 167 | 168 | public void onSingleTap(); 169 | 170 | public void onDoubleTap(); 171 | 172 | public void onScale(float scaleFactor, int state); 173 | 174 | public void onLongPress(); 175 | } 176 | } 177 | -------------------------------------------------------------------------------- /src/com/nmbb/oplayer/ui/player/VP.java: -------------------------------------------------------------------------------- 1 | package com.nmbb.oplayer.ui.player; 2 | 3 | import io.vov.vitamio.MediaPlayer; 4 | import android.graphics.Typeface; 5 | 6 | public class VP { 7 | 8 | public static final String SNAP_SHOT_PATH = "/Player"; 9 | public static final String SESSION_LAST_POSITION_SUFIX = ".last"; 10 | 11 | // key 12 | public static final String SUB_SHADOW_COLOR = "vplayer_sub_shadow_color"; 13 | public static final String SUB_POSITION = "vplayer_sub_position"; 14 | public static final String SUB_SIZE = "vplayer_sub_size"; 15 | public static final String SUB_SHADOW_RADIUS = "vplayer_sub_shadow_radius"; 16 | public static final String SUB_ENABLED = "vplayer_sub_enabled"; 17 | public static final String SUB_SHADOW_ENABLED = "vplayer_sub_shadow_enabled"; 18 | public static final String SUB_TEXT_KEY = "sub_text"; 19 | public static final String SUB_PIXELS_KEY = "sub_pixels"; 20 | public static final String SUB_WIDTH_KEY = "sub_width"; 21 | public static final String SUB_HEIGHT_KEY = "sub_height"; 22 | 23 | // default value 1024 24 | public static final int DEFAULT_BUF_SIZE = 512 * 1024; 25 | public static final int DEFAULT_VIDEO_QUALITY = MediaPlayer.VIDEOQUALITY_MEDIUM; 26 | public static final boolean DEFAULT_DEINTERLACE = false; 27 | public static final float DEFAULT_ASPECT_RATIO = 0f; 28 | public static final float DEFAULT_STEREO_VOLUME = 1.0f; 29 | public static final String DEFAULT_META_ENCODING = "auto"; 30 | public static final String DEFAULT_SUB_ENCODING = "auto"; 31 | public static final int DEFAULT_SUB_STYLE = Typeface.BOLD; 32 | public static final int DEFAULT_SUB_COLOR = 0xffffffff; 33 | public static final int DEFAULT_SUB_SHADOWCOLOR = 0xff000000; 34 | public static final float DEFAULT_SUB_SHADOWRADIUS = 2.0f; 35 | public static final float DEFAULT_SUB_SIZE = 18.0f; 36 | public static final float DEFAULT_SUB_POS = 10.0f; 37 | public static final int DEFAULT_TYPEFACE_INT = 0; 38 | public static final boolean DEFAULT_SUB_SHOWN = true; 39 | public static final boolean DEFAULT_SUB_SHADOW = true; 40 | public static final Typeface DEFAULT_TYPEFACE = Typeface.DEFAULT; 41 | 42 | 43 | public static Typeface getTypeface(int type) { 44 | switch (type) { 45 | case 0: 46 | return Typeface.DEFAULT; 47 | case 1: 48 | return Typeface.SANS_SERIF; 49 | case 2: 50 | return Typeface.SERIF; 51 | case 3: 52 | return Typeface.MONOSPACE; 53 | default: 54 | return DEFAULT_TYPEFACE; 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/com/nmbb/oplayer/ui/player/VideoView.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2012 YIXIA.COM 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.nmbb.oplayer.ui.player; 18 | 19 | import android.app.Activity; 20 | import android.content.Context; 21 | import android.graphics.PixelFormat; 22 | import android.util.AttributeSet; 23 | import android.view.SurfaceHolder; 24 | import android.view.SurfaceView; 25 | import android.view.ViewGroup.LayoutParams; 26 | 27 | import com.nmbb.oplayer.util.DeviceUtils; 28 | 29 | public class VideoView extends SurfaceView { 30 | private Activity mActivity; 31 | private SurfaceHolder mSurfaceHolder; 32 | private int mSurfaceWidth, mSurfaceHeight; 33 | private int mVideoMode = VIDEO_LAYOUT_SCALE; 34 | public static final int VIDEO_LAYOUT_ORIGIN = 0; 35 | public static final int VIDEO_LAYOUT_SCALE = 1; 36 | public static final int VIDEO_LAYOUT_STRETCH = 2; 37 | public static final int VIDEO_LAYOUT_ZOOM = 3; 38 | public static final int VIDEO_LAYOUT_SCALE_ZOOM = 4; 39 | public int mVideoHeight; 40 | 41 | public VideoView(Context context, AttributeSet attrs) { 42 | super(context, attrs); 43 | getHolder().addCallback(mCallback); 44 | getHolder().setFormat(PixelFormat.RGBA_8888); 45 | } 46 | 47 | @SuppressWarnings("deprecation") 48 | public void initialize(Activity activity, SurfaceCallback l, boolean push) { 49 | mActivity = activity; 50 | mListener = l; 51 | if (mSurfaceHolder == null) 52 | mSurfaceHolder = getHolder(); 53 | 54 | // These methods is set to hw decoder or sw decoder, <= 2.3 55 | if (push) 56 | getHolder().setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); 57 | else 58 | getHolder().setType(SurfaceHolder.SURFACE_TYPE_NORMAL); 59 | } 60 | 61 | private void setSurfaceLayout(float userRatio, int videoWidth, int videoHeight, float videoAspectRatio) { 62 | LayoutParams lp = getLayoutParams(); 63 | int windowWidth = DeviceUtils.getScreenWidth(mActivity); 64 | int windowHeight = DeviceUtils.getScreenHeight(mActivity); 65 | float windowRatio = windowWidth / (float) windowHeight; 66 | float videoRatio = userRatio <= 0.01f ? videoAspectRatio : userRatio; 67 | mSurfaceHeight = videoHeight; 68 | mSurfaceWidth = videoWidth; 69 | if (VIDEO_LAYOUT_ORIGIN == mVideoMode && mSurfaceWidth < windowWidth && mSurfaceHeight < windowHeight) { 70 | lp.width = (int) (mSurfaceHeight * videoRatio); 71 | lp.height = mSurfaceHeight; 72 | } else if (mVideoMode == VIDEO_LAYOUT_ZOOM) { 73 | lp.width = windowRatio > videoRatio ? windowWidth : (int) (videoRatio * windowHeight); 74 | lp.height = windowRatio < videoRatio ? windowHeight : (int) (windowWidth / videoRatio); 75 | } else if (mVideoMode == VIDEO_LAYOUT_SCALE_ZOOM && mVideoHeight > 0) { 76 | lp.width = (int) (mVideoHeight * videoRatio); 77 | lp.height = mVideoHeight; 78 | } else { 79 | boolean full = mVideoMode == VIDEO_LAYOUT_STRETCH; 80 | lp.width = (full || windowRatio < videoRatio) ? windowWidth : (int) (videoRatio * windowHeight); 81 | lp.height = (full || windowRatio > videoRatio) ? windowHeight : (int) (windowWidth / videoRatio); 82 | } 83 | mVideoHeight = lp.height; 84 | setLayoutParams(lp); 85 | getHolder().setFixedSize(mSurfaceWidth, mSurfaceHeight); 86 | //Log.d("VIDEO: %dx%dx%f, Surface: %dx%d, LP: %dx%d, Window: %dx%dx%f", videoWidth, videoHeight, videoAspectRatio, mSurfaceWidth, mSurfaceHeight, lp.width, lp.height, windowWidth, windowHeight, windowRatio); 87 | } 88 | 89 | public void setVideoLayout(int layout, float userRatio, int videoWidth, int videoHeight, float videoRatio) { 90 | mVideoMode = layout; 91 | setSurfaceLayout(userRatio, videoWidth, videoHeight, videoRatio); 92 | } 93 | 94 | private SurfaceHolder.Callback mCallback = new SurfaceHolder.Callback() { 95 | @Override 96 | public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { 97 | holder.setKeepScreenOn(true); 98 | if (mListener != null) 99 | mListener.onSurfaceChanged(holder, format, width, height); 100 | } 101 | 102 | @Override 103 | public void surfaceCreated(SurfaceHolder holder) { 104 | mSurfaceHolder = holder; 105 | if (mListener != null) 106 | mListener.onSurfaceCreated(holder); 107 | } 108 | 109 | @Override 110 | public void surfaceDestroyed(SurfaceHolder holder) { 111 | if (mListener != null) 112 | mListener.onSurfaceDestroyed(holder); 113 | } 114 | }; 115 | 116 | private SurfaceCallback mListener; 117 | 118 | public interface SurfaceCallback { 119 | public void onSurfaceCreated(SurfaceHolder holder); 120 | 121 | public void onSurfaceChanged(SurfaceHolder holder, int format, int width, int height); 122 | 123 | public void onSurfaceDestroyed(SurfaceHolder holder); 124 | } 125 | } 126 | -------------------------------------------------------------------------------- /src/com/nmbb/oplayer/ui/vitamio/InitActivity.java: -------------------------------------------------------------------------------- 1 | package com.nmbb.oplayer.ui.vitamio; 2 | 3 | import io.vov.vitamio.Vitamio; 4 | import android.app.Activity; 5 | import android.app.ProgressDialog; 6 | import android.content.Intent; 7 | import android.os.AsyncTask; 8 | import android.os.Bundle; 9 | import android.os.Handler; 10 | import android.os.Message; 11 | import android.view.WindowManager; 12 | 13 | import com.nmbb.oplayer.R; 14 | 15 | public class InitActivity extends Activity { 16 | public static final String FROM_ME = "fromVitamioInitActivity"; 17 | public static final String EXTRA_MSG = "EXTRA_MSG"; 18 | public static final String EXTRA_FILE = "EXTRA_FILE"; 19 | private ProgressDialog mPD; 20 | 21 | @Override 22 | protected void onCreate(Bundle savedInstanceState) { 23 | super.onCreate(savedInstanceState); 24 | getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); 25 | 26 | new AsyncTask() { 27 | @Override 28 | protected void onPreExecute() { 29 | mPD = new ProgressDialog(InitActivity.this); 30 | mPD.setCancelable(false); 31 | mPD.setMessage(getText(R.string.init_decoders)); 32 | mPD.show(); 33 | } 34 | 35 | @Override 36 | protected Object doInBackground(Object... params) { 37 | 38 | Vitamio.initialize(getApplicationContext()); 39 | // if (Vitamio.isInitialized(getApplicationContext())) 40 | // return null; 41 | // 42 | // //反射解压 43 | // try { 44 | // Class c = Class.forName("io.vov.vitamio.Vitamio"); 45 | // Method extractLibs = c.getDeclaredMethod("extractLibs", new Class[] { android.content.Context.class, int.class }); 46 | // extractLibs.setAccessible(true); 47 | // extractLibs.invoke(c, new Object[] { getApplicationContext(), R.raw.libarm }); 48 | // 49 | //// Field vitamioLibraryPath = c.getDeclaredField("vitamioLibraryPath"); 50 | //// 51 | //// AndroidContextUtils.getDataDir(ctx) + "libs/" 52 | // 53 | // } catch (NoSuchMethodException e) { 54 | // Log.e("extractLibs", e); 55 | // e.printStackTrace(); 56 | // } catch (IllegalArgumentException e) { 57 | // e.printStackTrace(); 58 | // } catch (IllegalAccessException e) { 59 | // e.printStackTrace(); 60 | // } catch (InvocationTargetException e) { 61 | // e.printStackTrace(); 62 | // } catch (ClassNotFoundException e) { 63 | // e.printStackTrace(); 64 | // } 65 | 66 | uiHandler.sendEmptyMessage(0); 67 | return null; 68 | } 69 | }.execute(); 70 | } 71 | 72 | private Handler uiHandler = new Handler() { 73 | @Override 74 | public void handleMessage(Message msg) { 75 | mPD.dismiss(); 76 | Intent src = getIntent(); 77 | Intent i = new Intent(); 78 | i.setClassName(src.getStringExtra("package"), src.getStringExtra("className")); 79 | i.setData(src.getData()); 80 | i.putExtras(src); 81 | i.putExtra(FROM_ME, true); 82 | startActivity(i); 83 | 84 | finish(); 85 | } 86 | }; 87 | } 88 | -------------------------------------------------------------------------------- /src/com/nmbb/oplayer/ui/vitamio/LibsChecker.java: -------------------------------------------------------------------------------- 1 | package com.nmbb.oplayer.ui.vitamio; 2 | 3 | import io.vov.vitamio.Vitamio; 4 | import android.app.Activity; 5 | import android.content.Intent; 6 | 7 | public final class LibsChecker { 8 | public static final String FROM_ME = "fromVitamioInitActivity"; 9 | 10 | // 11 | // public static final boolean checkVitamioLibs(Activity ctx, int msgID, int rawID) { 12 | // new Vitamio(). 13 | // if (!Vitamio.isInitialized(ctx) && !ctx.getIntent().getBooleanExtra(FROM_ME, false)) { 14 | // Intent i = new Intent(); 15 | // i.setClassName(Vitamio.getCompatiblePackage(), "com.nmbb.oplayer.ui.vitamio.InitActivity"); 16 | // i.putExtras(ctx.getIntent()); 17 | // i.setData(ctx.getIntent().getData()); 18 | // i.putExtra("package", ctx.getApplicationInfo().packageName); 19 | // i.putExtra("className", ctx.getClass().getName()); 20 | // i.putExtra("EXTRA_MSG", msgID); 21 | // i.putExtra("EXTRA_FILE", rawID); 22 | // ctx.startActivity(i); 23 | // ctx.finish(); 24 | // return false; 25 | // } 26 | // return true; 27 | // } 28 | 29 | public static final boolean checkVitamioLibs(Activity ctx, int msgID) { 30 | if ((!Vitamio.isInitialized(ctx)) && (!ctx.getIntent().getBooleanExtra("fromVitamioInitActivity", false))) { 31 | Intent i = new Intent(); 32 | i.setClassName(ctx.getPackageName(), "com.nmbb.oplayer.ui.vitamio.InitActivity");//io.vov.vitamio.activity.InitActivity 33 | i.putExtras(ctx.getIntent()); 34 | i.setData(ctx.getIntent().getData()); 35 | i.putExtra("package", ctx.getPackageName()); 36 | i.putExtra("className", ctx.getClass().getName()); 37 | i.putExtra("EXTRA_MSG", msgID); 38 | ctx.startActivity(i); 39 | ctx.finish(); 40 | return false; 41 | } 42 | return true; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/com/nmbb/oplayer/util/ApplicationUtils.java: -------------------------------------------------------------------------------- 1 | package com.nmbb.oplayer.util; 2 | 3 | import java.io.File; 4 | import java.io.FileInputStream; 5 | import java.io.FileOutputStream; 6 | import java.io.IOException; 7 | import java.util.List; 8 | 9 | import android.app.Activity; 10 | import android.app.ActivityManager; 11 | import android.content.Context; 12 | import android.content.pm.ApplicationInfo; 13 | import android.content.pm.PackageManager; 14 | import android.content.pm.PackageManager.NameNotFoundException; 15 | import android.os.Environment; 16 | import android.widget.Toast; 17 | 18 | public class ApplicationUtils { 19 | /** 20 | * 备份App 首先无需提升权限就就可以复制APK,查看权限你就会知道,在data/app下的APK权限如下:-rw-r--r-- system 21 | * system 5122972 2012-12-13 10:38 com.taobao.taobao-1.apk 我们是有读取权限的。 22 | * 23 | * @param packageName 24 | * @param mActivity 25 | * @throws IOException 26 | */ 27 | public static void backupApp(String packageName, Activity mActivity) 28 | throws IOException { 29 | // 存放位置 30 | String newFile = Environment.getExternalStorageDirectory() 31 | .getAbsolutePath() + File.separator; 32 | String oldFile = null; 33 | try { 34 | // 原始位置 35 | oldFile = mActivity.getPackageManager().getApplicationInfo( 36 | packageName, 0).sourceDir; 37 | } catch (NameNotFoundException e) { 38 | e.printStackTrace(); 39 | } 40 | System.out.println(newFile); 41 | System.out.println(oldFile); 42 | 43 | File in = new File(oldFile); 44 | File out = new File(newFile + packageName + ".apk"); 45 | if (!out.exists()) { 46 | out.createNewFile(); 47 | Toast.makeText(mActivity, "文件备份成功!" + "存放于" + newFile + "目录下", 1) 48 | .show(); 49 | } else { 50 | Toast.makeText(mActivity, "文件已经存在!" + "查看" + newFile + "目录下", 1) 51 | .show(); 52 | } 53 | 54 | FileInputStream fis = new FileInputStream(in); 55 | FileOutputStream fos = new FileOutputStream(out); 56 | 57 | int count; 58 | // 文件太大的话,我觉得需要修改 59 | byte[] buffer = new byte[256 * 1024]; 60 | while ((count = fis.read(buffer)) > 0) { 61 | fos.write(buffer, 0, count); 62 | } 63 | 64 | fis.close(); 65 | fos.flush(); 66 | fos.close(); 67 | } 68 | 69 | /** 70 | * 获取当前Apk版本号 android:versionCode 71 | * 72 | * @param context 73 | * @return 74 | */ 75 | public static int getVerCode(Context context) { 76 | int verCode = -1; 77 | try { 78 | verCode = context.getPackageManager().getPackageInfo( 79 | context.getPackageName(), 0).versionCode; 80 | } catch (NameNotFoundException e) { 81 | } 82 | return verCode; 83 | } 84 | 85 | public static String getVerName(Context context) { 86 | try { 87 | return context.getPackageManager().getPackageInfo( 88 | context.getPackageName(), 0).versionName; 89 | } catch (NameNotFoundException e) { 90 | } 91 | return ""; 92 | } 93 | 94 | /** 95 | * 返回当前的应用是否处于前台显示状态 不需要android.permission.GET_TASKS权限 96 | * http://zengrong.net/post/1680.htm 97 | * 98 | * @param packageName 99 | * @return 100 | */ 101 | public static boolean isTopActivity(Context context, String packageName) { 102 | // _context是一个保存的上下文 103 | ActivityManager am = (ActivityManager) context.getApplicationContext() 104 | .getSystemService(Context.ACTIVITY_SERVICE); 105 | List list = am 106 | .getRunningAppProcesses(); 107 | if (list.size() == 0) 108 | return false; 109 | for (ActivityManager.RunningAppProcessInfo process : list) { 110 | // Log.d(getTAG(), Integer.toString(__process.importance)); 111 | // Log.d(getTAG(), __process.processName); 112 | if (process.importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND 113 | && process.processName.equals(packageName)) { 114 | return true; 115 | } 116 | } 117 | return false; 118 | } 119 | 120 | /** 121 | * 检测APP是否存在 122 | * @param context 123 | * @param packageName 124 | * @return 125 | */ 126 | public static boolean checkAppExist(Context context, String packageName) { 127 | try { 128 | ApplicationInfo info = context.getPackageManager() 129 | .getApplicationInfo(packageName, 0); 130 | return info != null && info.packageName.equals(packageName); 131 | } catch (PackageManager.NameNotFoundException e) { 132 | 133 | } catch (Exception e) { 134 | } 135 | return false; 136 | } 137 | } 138 | -------------------------------------------------------------------------------- /src/com/nmbb/oplayer/util/ArrayUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2012 YIXIA.COM 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.nmbb.oplayer.util; 17 | 18 | import java.lang.reflect.Array; 19 | 20 | public class ArrayUtils { 21 | public static T[] concat(T[] A, T[] B) { 22 | final Class typeofA = A.getClass().getComponentType(); 23 | @SuppressWarnings("unchecked") 24 | T[] C = (T[]) Array.newInstance(typeofA, A.length + B.length); 25 | System.arraycopy(A, 0, C, 0, A.length); 26 | System.arraycopy(B, 0, C, A.length, B.length); 27 | 28 | return C; 29 | } 30 | 31 | public static int indexOf(T[] array, T s) { 32 | for (int i = 0; i < array.length; i++) { 33 | if (array[i].equals(s)) { 34 | return i; 35 | } 36 | } 37 | return -1; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/com/nmbb/oplayer/util/ConvertUtils.java: -------------------------------------------------------------------------------- 1 | package com.nmbb.oplayer.util; 2 | 3 | import android.content.Context; 4 | 5 | /** 6 | * 数据转换类 7 | * 8 | * @author 农民伯伯 9 | * @see http://www.cnblogs.com/over140 10 | * 11 | */ 12 | public final class ConvertUtils { 13 | 14 | private static final float UNIT = 1000.0F; 15 | 16 | /** 17 | * 毫秒转秒 18 | * 19 | * @param time 毫秒 20 | * @return 21 | */ 22 | public static float ms2s(long time) { 23 | return time / UNIT; 24 | } 25 | 26 | /** 27 | * 微秒转秒 28 | * 29 | * @param time 微秒 30 | * @return 31 | */ 32 | public static float us2s(long time) { 33 | return time / UNIT / UNIT; 34 | } 35 | 36 | /** 37 | * 纳秒转秒 38 | * 39 | * @param time 纳秒 40 | * @return 41 | */ 42 | public static float ns2s(long time) { 43 | return time / UNIT / UNIT / UNIT; 44 | } 45 | 46 | /** 47 | * 转换字符串为boolean 48 | * 49 | * @param str 50 | * @return 51 | */ 52 | public static boolean toBoolean(String str) { 53 | return toBoolean(str, false); 54 | } 55 | 56 | /** 57 | * 转换字符串为boolean 58 | * 59 | * @param str 60 | * @param def 61 | * @return 62 | */ 63 | public static boolean toBoolean(String str, boolean def) { 64 | if (StringUtils.isEmpty(str)) 65 | return def; 66 | if ("false".equalsIgnoreCase(str) || "0".equals(str)) 67 | return false; 68 | else if ("true".equalsIgnoreCase(str) || "1".equals(str)) 69 | return true; 70 | else 71 | return def; 72 | } 73 | 74 | /** 75 | * 转换字符串为float 76 | * 77 | * @param str 78 | * @return 79 | */ 80 | public static float toFloat(String str) { 81 | return toFloat(str, 0F); 82 | } 83 | 84 | /** 85 | * 转换字符串为float 86 | * 87 | * @param str 88 | * @param def 89 | * @return 90 | */ 91 | public static float toFloat(String str, float def) { 92 | if (StringUtils.isEmpty(str)) 93 | return def; 94 | try { 95 | return Float.parseFloat(str); 96 | } catch (NumberFormatException e) { 97 | return def; 98 | } 99 | } 100 | 101 | /** 102 | * 转换字符串为long 103 | * 104 | * @param str 105 | * @return 106 | */ 107 | public static long toLong(String str) { 108 | return toLong(str, 0L); 109 | } 110 | 111 | /** 112 | * 转换字符串为long 113 | * 114 | * @param str 115 | * @param def 116 | * @return 117 | */ 118 | public static long toLong(String str, long def) { 119 | if (StringUtils.isEmpty(str)) 120 | return def; 121 | try { 122 | return Long.parseLong(str); 123 | } catch (NumberFormatException e) { 124 | return def; 125 | } 126 | } 127 | 128 | /** 129 | * 转换字符串为short 130 | * 131 | * @param str 132 | * @return 133 | */ 134 | public static short toShort(String str) { 135 | return toShort(str, (short) 0); 136 | } 137 | 138 | /** 139 | * 转换字符串为short 140 | * 141 | * @param str 142 | * @param def 143 | * @return 144 | */ 145 | public static short toShort(String str, short def) { 146 | if (StringUtils.isEmpty(str)) 147 | return def; 148 | try { 149 | return Short.parseShort(str); 150 | } catch (NumberFormatException e) { 151 | return def; 152 | } 153 | } 154 | 155 | /** 156 | * 转换字符串为int 157 | * 158 | * @param str 159 | * @return 160 | */ 161 | public static int toInt(String str) { 162 | return toInt(str, 0); 163 | } 164 | 165 | /** 166 | * 转换字符串为int 167 | * 168 | * @param str 169 | * @param def 170 | * @return 171 | */ 172 | public static int toInt(String str, int def) { 173 | if (StringUtils.isEmpty(str)) 174 | return def; 175 | try { 176 | return Integer.parseInt(str); 177 | } catch (NumberFormatException e) { 178 | return def; 179 | } 180 | } 181 | 182 | public static String toString(Object o) { 183 | return toString(o, ""); 184 | } 185 | 186 | public static String toString(Object o, String def) { 187 | if (o == null) 188 | return def; 189 | 190 | return o.toString(); 191 | } 192 | 193 | public static int dipToPX(final Context ctx, int dip) { 194 | float scale = ctx.getResources().getDisplayMetrics().density; 195 | return (int) (dip / 1.5D * scale + 0.5D); 196 | } 197 | } 198 | -------------------------------------------------------------------------------- /src/com/nmbb/oplayer/util/DeviceUtils.java: -------------------------------------------------------------------------------- 1 | package com.nmbb.oplayer.util; 2 | 3 | import java.io.BufferedReader; 4 | import java.io.File; 5 | import java.io.FileReader; 6 | import java.io.IOException; 7 | import java.util.List; 8 | 9 | import android.app.Activity; 10 | import android.content.ComponentName; 11 | import android.content.Context; 12 | import android.content.Intent; 13 | import android.content.pm.PackageInfo; 14 | import android.content.pm.PackageManager; 15 | import android.content.pm.PackageManager.NameNotFoundException; 16 | import android.content.pm.ResolveInfo; 17 | import android.content.res.Configuration; 18 | import android.os.Build; 19 | import android.os.Environment; 20 | import android.os.StatFs; 21 | import android.util.DisplayMetrics; 22 | import android.view.Display; 23 | import android.view.View; 24 | import android.view.WindowManager; 25 | import android.view.inputmethod.InputMethodManager; 26 | 27 | import com.nmbb.oplayer.exception.Logger; 28 | 29 | /** 30 | * 系统版本信息类 31 | * 32 | * @author tangjun 33 | * 34 | */ 35 | public class DeviceUtils { 36 | 37 | /** >=2.2 */ 38 | public static boolean hasFroyo() { 39 | return Build.VERSION.SDK_INT >= Build.VERSION_CODES.FROYO; 40 | } 41 | 42 | /** >=2.3 */ 43 | public static boolean hasGingerbread() { 44 | return Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD; 45 | } 46 | 47 | /** >=3.0 LEVEL:11 */ 48 | public static boolean hasHoneycomb() { 49 | return Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB; 50 | } 51 | 52 | /** >=3.1 */ 53 | public static boolean hasHoneycombMR1() { 54 | return Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR1; 55 | } 56 | 57 | /** >=4.0 14 */ 58 | public static boolean hasICS() { 59 | return Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH; 60 | } 61 | 62 | public static int getSDKVersionInt() { 63 | return Build.VERSION.SDK_INT; 64 | } 65 | 66 | @SuppressWarnings("deprecation") 67 | public static String getSDKVersion() { 68 | return Build.VERSION.SDK; 69 | } 70 | 71 | /** 72 | * 判断是否是平板电脑 73 | * 74 | * @param context 75 | * @return 76 | */ 77 | public static boolean isTablet(Context context) { 78 | return (context.getResources().getConfiguration().screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK) >= Configuration.SCREENLAYOUT_SIZE_LARGE; 79 | } 80 | 81 | public static boolean isHoneycombTablet(Context context) { 82 | return hasHoneycomb() && isTablet(context); 83 | } 84 | 85 | /** 86 | * 获得设备型号 87 | * 88 | * @return 89 | */ 90 | public static String getDeviceModel() { 91 | return StringUtils.trim(Build.MODEL); 92 | } 93 | 94 | /** 检测是否魅族手机 */ 95 | public static boolean isMeizu() { 96 | return getDeviceModel().toLowerCase().indexOf("meizu") != -1; 97 | } 98 | 99 | /** 检测是否HTC手机 */ 100 | public static boolean isHTC() { 101 | return getDeviceModel().toLowerCase().indexOf("htc") != -1; 102 | } 103 | 104 | public static boolean isXiaomi() { 105 | return getDeviceModel().toLowerCase().indexOf("xiaomi") != -1; 106 | } 107 | 108 | /** 109 | * 获得设备制造商 110 | * 111 | * @return 112 | */ 113 | public static String getManufacturer() { 114 | return StringUtils.trim(Build.MANUFACTURER); 115 | } 116 | 117 | @SuppressWarnings("deprecation") 118 | public static int getScreenHeight(Context context) { 119 | Display display = ((WindowManager) context 120 | .getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay(); 121 | return display.getHeight(); 122 | } 123 | 124 | /** 获取屏幕宽度 */ 125 | @SuppressWarnings("deprecation") 126 | public static int getScreenWidth(Context context) { 127 | Display display = ((WindowManager) context 128 | .getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay(); 129 | return display.getWidth(); 130 | } 131 | 132 | /** 133 | * 获得设备屏幕密度 134 | */ 135 | public static float getScreenDensity(Context context) { 136 | DisplayMetrics metrics = context.getApplicationContext().getResources() 137 | .getDisplayMetrics(); 138 | return metrics.density; 139 | } 140 | 141 | public static int[] getScreenSize(int w, int h, Context context) { 142 | int phoneW = getScreenWidth(context); 143 | int phoneH = getScreenHeight(context); 144 | 145 | if (w * phoneH > phoneW * h) { 146 | phoneH = phoneW * h / w; 147 | } else if (w * phoneH < phoneW * h) { 148 | phoneW = phoneH * w / h; 149 | } 150 | 151 | return new int[] { phoneW, phoneH }; 152 | } 153 | 154 | public static int[] getScreenSize(int w, int h, int phoneW, int phoneH) { 155 | if (w * phoneH > phoneW * h) { 156 | phoneH = phoneW * h / w; 157 | } else if (w * phoneH < phoneW * h) { 158 | phoneW = phoneH * w / h; 159 | } 160 | return new int[] { phoneW, phoneH }; 161 | } 162 | 163 | /** 设置屏幕亮度 */ 164 | public static void setBrightness(final Activity context, float f) { 165 | WindowManager.LayoutParams lp = context.getWindow().getAttributes(); 166 | lp.screenBrightness = f; 167 | if (lp.screenBrightness > 1.0f) 168 | lp.screenBrightness = 1.0f; 169 | else if (lp.screenBrightness < 0.01f) 170 | lp.screenBrightness = 0.01f; 171 | context.getWindow().setAttributes(lp); 172 | } 173 | 174 | // private static final long NO_STORAGE_ERROR = -1L; 175 | private static final long CANNOT_STAT_ERROR = -2L; 176 | 177 | /** 检测磁盘状态 */ 178 | // public static int getStorageStatus(boolean mayHaveSd) { 179 | // long remaining = mayHaveSd ? getAvailableStorage() : NO_STORAGE_ERROR; 180 | // if (remaining == NO_STORAGE_ERROR) { 181 | // return CommonStatus.STORAGE_STATUS_NONE; 182 | // } 183 | // return remaining < CommonConstants.LOW_STORAGE_THRESHOLD ? 184 | // CommonStatus.STORAGE_STATUS_LOW : CommonStatus.STORAGE_STATUS_OK; 185 | // } 186 | 187 | public static long getAvailableStorage() { 188 | try { 189 | String storageDirectory = Environment.getExternalStorageDirectory() 190 | .toString(); 191 | StatFs stat = new StatFs(storageDirectory); 192 | return (long) stat.getAvailableBlocks() 193 | * (long) stat.getBlockSize(); 194 | } catch (RuntimeException ex) { 195 | // if we can't stat the filesystem then we don't know how many 196 | // free bytes exist. It might be zero but just leave it 197 | // blank since we really don't know. 198 | return CANNOT_STAT_ERROR; 199 | } 200 | } 201 | 202 | /** 隐藏软键盘 */ 203 | public static void hideSoftInput(Context ctx, View v) { 204 | InputMethodManager imm = (InputMethodManager) ctx 205 | .getSystemService(Context.INPUT_METHOD_SERVICE); 206 | // 这个方法可以实现输入法在窗口上切换显示,如果输入法在窗口上已经显示,则隐藏,如果隐藏,则显示输入法到窗口上 207 | imm.hideSoftInputFromWindow(v.getApplicationWindowToken(), 208 | InputMethodManager.HIDE_NOT_ALWAYS); 209 | } 210 | 211 | /** 显示软键盘 */ 212 | public static void showSoftInput(Context ctx) { 213 | InputMethodManager imm = (InputMethodManager) ctx 214 | .getSystemService(Context.INPUT_METHOD_SERVICE); 215 | imm.toggleSoftInput(0, InputMethodManager.SHOW_FORCED);// (v, 216 | // InputMethodManager.SHOW_FORCED); 217 | } 218 | 219 | /** 220 | * 软键盘是否已经打开 221 | * 222 | * @return 223 | */ 224 | protected boolean isHardKeyboardOpen(Context ctx) { 225 | return ctx.getResources().getConfiguration().hardKeyboardHidden == Configuration.HARDKEYBOARDHIDDEN_NO; 226 | } 227 | 228 | public static String getCpuInfo() { 229 | String cpuInfo = ""; 230 | try { 231 | if (new File("/proc/cpuinfo").exists()) { 232 | FileReader fr = new FileReader("/proc/cpuinfo"); 233 | BufferedReader localBufferedReader = new BufferedReader(fr, 234 | 8192); 235 | cpuInfo = localBufferedReader.readLine(); 236 | localBufferedReader.close(); 237 | 238 | if (cpuInfo != null) { 239 | cpuInfo = cpuInfo.split(":")[1].trim().split(" ")[0]; 240 | } 241 | } 242 | } catch (IOException e) { 243 | } catch (Exception e) { 244 | } 245 | return cpuInfo; 246 | } 247 | 248 | public static void startApkActivity(final Context ctx, String packageName) { 249 | PackageManager pm = ctx.getPackageManager(); 250 | PackageInfo pi; 251 | try { 252 | pi = pm.getPackageInfo(packageName, 0); 253 | Intent intent = new Intent(Intent.ACTION_MAIN, null); 254 | intent.addCategory(Intent.CATEGORY_LAUNCHER); 255 | intent.setPackage(pi.packageName); 256 | 257 | List apps = pm.queryIntentActivities(intent, 0); 258 | 259 | ResolveInfo ri = apps.iterator().next(); 260 | if (ri != null) { 261 | String className = ri.activityInfo.name; 262 | intent.setComponent(new ComponentName(packageName, className)); 263 | ctx.startActivity(intent); 264 | } 265 | } catch (NameNotFoundException e) { 266 | Logger.e(e); 267 | } 268 | } 269 | } 270 | -------------------------------------------------------------------------------- /src/com/nmbb/oplayer/util/FractionalTouchDelegate.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2012 YIXIA.COM 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.nmbb.oplayer.util; 17 | 18 | import android.graphics.Rect; 19 | import android.graphics.RectF; 20 | import android.view.MotionEvent; 21 | import android.view.TouchDelegate; 22 | import android.view.View; 23 | 24 | /** 25 | * {@link TouchDelegate} that gates {@link MotionEvent} instances by comparing 26 | * then against fractional dimensions of the source view. 27 | *

28 | * This is particularly useful when you want to define a rectangle in terms of 29 | * the source dimensions, but when those dimensions might change due to pending 30 | * or future layout passes. 31 | *

32 | * One example is catching touches that occur in the top-right quadrant of 33 | * {@code sourceParent}, and relaying them to {@code targetChild}. This could be 34 | * done with: 35 | * FractionalTouchDelegate.setupDelegate(sourceParent, targetChild, new RectF(0.5f, 0f, 1f, 0.5f)); 36 | * 37 | */ 38 | public class FractionalTouchDelegate extends TouchDelegate { 39 | 40 | private View mSource; 41 | private View mTarget; 42 | 43 | private RectF mSourceFraction; 44 | 45 | private Rect mScrap = new Rect(); 46 | 47 | /** Cached full dimensions of {@link #mSource}. */ 48 | private Rect mSourceFull = new Rect(); 49 | /** Cached projection of {@link #mSourceFraction} onto {@link #mSource}. */ 50 | private Rect mSourcePartial = new Rect(); 51 | 52 | private boolean mDelegateTargeted; 53 | 54 | public FractionalTouchDelegate(View source, View target, RectF sourceFraction) { 55 | super(new Rect(0, 0, 0, 0), target); 56 | mSource = source; 57 | mTarget = target; 58 | mSourceFraction = sourceFraction; 59 | } 60 | 61 | /** 62 | * Helper to create and setup a {@link FractionalTouchDelegate} between the 63 | * given {@link View}. 64 | * 65 | * @param source Larger source {@link View}, usually a parent, that will be 66 | * assigned {@link View#setTouchDelegate(TouchDelegate)}. 67 | * @param target Smaller target {@link View} which will receive 68 | * {@link MotionEvent} that land in requested fractional area. 69 | * @param sourceFraction Fractional area projected onto source {@link View} 70 | * which determines when {@link MotionEvent} will be passed to 71 | * target {@link View}. 72 | */ 73 | public static void setupDelegate(View source, View target, RectF sourceFraction) { 74 | source.setTouchDelegate(new FractionalTouchDelegate(source, target, sourceFraction)); 75 | } 76 | 77 | /** 78 | * Consider updating {@link #mSourcePartial} when {@link #mSource} 79 | * dimensions have changed. 80 | */ 81 | private void updateSourcePartial() { 82 | mSource.getHitRect(mScrap); 83 | if (!mScrap.equals(mSourceFull)) { 84 | // Copy over and calculate fractional rectangle 85 | mSourceFull.set(mScrap); 86 | 87 | final int width = mSourceFull.width(); 88 | final int height = mSourceFull.height(); 89 | 90 | mSourcePartial.left = (int) (mSourceFraction.left * width); 91 | mSourcePartial.top = (int) (mSourceFraction.top * height); 92 | mSourcePartial.right = (int) (mSourceFraction.right * width); 93 | mSourcePartial.bottom = (int) (mSourceFraction.bottom * height); 94 | } 95 | } 96 | 97 | @Override 98 | public boolean onTouchEvent(MotionEvent event) { 99 | updateSourcePartial(); 100 | 101 | // The logic below is mostly copied from the parent class, since we 102 | // can't update private mBounds variable. 103 | 104 | // http://android.git.kernel.org/?p=platform/frameworks/base.git;a=blob; 105 | // f=core/java/android/view/TouchDelegate.java;hb=eclair#l98 106 | 107 | final Rect sourcePartial = mSourcePartial; 108 | final View target = mTarget; 109 | 110 | int x = (int)event.getX(); 111 | int y = (int)event.getY(); 112 | 113 | boolean sendToDelegate = false; 114 | boolean hit = true; 115 | boolean handled = false; 116 | 117 | switch (event.getAction()) { 118 | case MotionEvent.ACTION_DOWN: 119 | if (sourcePartial.contains(x, y)) { 120 | mDelegateTargeted = true; 121 | sendToDelegate = true; 122 | } 123 | break; 124 | case MotionEvent.ACTION_UP: 125 | case MotionEvent.ACTION_MOVE: 126 | sendToDelegate = mDelegateTargeted; 127 | if (sendToDelegate) { 128 | if (!sourcePartial.contains(x, y)) { 129 | hit = false; 130 | } 131 | } 132 | break; 133 | case MotionEvent.ACTION_CANCEL: 134 | sendToDelegate = mDelegateTargeted; 135 | mDelegateTargeted = false; 136 | break; 137 | } 138 | 139 | if (sendToDelegate) { 140 | if (hit) { 141 | event.setLocation(target.getWidth() / 2, target.getHeight() / 2); 142 | } else { 143 | event.setLocation(-1, -1); 144 | } 145 | handled = target.dispatchTouchEvent(event); 146 | } 147 | return handled; 148 | } 149 | } 150 | -------------------------------------------------------------------------------- /src/com/nmbb/oplayer/util/IntentHelper.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2012 YIXIA.COM 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.nmbb.oplayer.util; 17 | 18 | import io.vov.vitamio.utils.Log; 19 | 20 | import java.util.List; 21 | import java.util.regex.Matcher; 22 | import java.util.regex.Pattern; 23 | 24 | import android.content.ComponentName; 25 | import android.content.Context; 26 | import android.content.Intent; 27 | import android.content.pm.PackageInfo; 28 | import android.content.pm.PackageManager; 29 | import android.content.pm.PackageManager.NameNotFoundException; 30 | import android.content.pm.ResolveInfo; 31 | import android.net.Uri; 32 | import android.os.Parcelable; 33 | import android.text.Html; 34 | 35 | public final class IntentHelper { 36 | 37 | public static final String MEDIA_PATTERN = "(http[s]?://)+([\\w-]+\\.)+[\\w-]+([\\w-./?%&=]*)?"; 38 | private static final Pattern mMediaPattern; 39 | 40 | static { 41 | mMediaPattern = Pattern.compile(MEDIA_PATTERN); 42 | } 43 | 44 | public static Uri getIntentUri(Intent intent) { 45 | Uri result = null; 46 | if (intent != null) { 47 | result = intent.getData(); 48 | if (result == null) { 49 | final String type = intent.getType(); 50 | String sharedUrl = intent.getStringExtra(Intent.EXTRA_TEXT); 51 | if (!StringUtils.isEmpty(sharedUrl)) { 52 | if ("text/plain".equals(type) && sharedUrl != null) { 53 | result = getTextUri(sharedUrl); 54 | } else if ("text/html".equals(type) && sharedUrl != null) { 55 | result = getTextUri(Html.fromHtml(sharedUrl).toString()); 56 | } 57 | } else { 58 | Parcelable parce = intent.getParcelableExtra(Intent.EXTRA_STREAM); 59 | if (parce != null) 60 | result = (Uri) parce; 61 | } 62 | } 63 | } 64 | return result; 65 | } 66 | 67 | private static Uri getTextUri(String sharedUrl) { 68 | Matcher matcher = mMediaPattern.matcher(sharedUrl); 69 | if (matcher.find()) { 70 | sharedUrl = matcher.group(); 71 | if (!StringUtils.isEmpty(sharedUrl)) { 72 | return Uri.parse(sharedUrl); 73 | } 74 | } 75 | return null; 76 | } 77 | 78 | public static boolean existPackage(final Context ctx, String packageName) { 79 | if (!StringUtils.isEmpty(packageName)) { 80 | for (PackageInfo p : ctx.getPackageManager().getInstalledPackages(0)) { 81 | if (packageName.equals(p.packageName)) 82 | return true; 83 | } 84 | } 85 | return false; 86 | } 87 | 88 | public static void startApkActivity(final Context ctx, String packageName) { 89 | PackageManager pm = ctx.getPackageManager(); 90 | PackageInfo pi; 91 | try { 92 | pi = pm.getPackageInfo(packageName, 0); 93 | Intent intent = new Intent(Intent.ACTION_MAIN, null); 94 | intent.setPackage(pi.packageName); 95 | 96 | List apps = pm.queryIntentActivities(intent, 0); 97 | 98 | ResolveInfo ri = apps.iterator().next(); 99 | if (ri != null) { 100 | String className = ri.activityInfo.name; 101 | intent.setComponent(new ComponentName(packageName, className)); 102 | ctx.startActivity(intent); 103 | } 104 | } catch (NameNotFoundException e) { 105 | Log.e("startActivity", e); 106 | } 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /src/com/nmbb/oplayer/util/MediaUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2012 YIXIA.COM 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.nmbb.oplayer.util; 17 | 18 | import java.io.File; 19 | import java.util.regex.Pattern; 20 | 21 | import android.net.Uri; 22 | 23 | public final class MediaUtils { 24 | public static final String[] EXTENSIONS; 25 | // http://www.fileinfo.com/filetypes/video 26 | public static final String[] VIDEO_EXTENSIONS = { "\\.264", "\\.3g2", "\\.3gp", "\\.3gp2", "\\.3gpp", "\\.3gpp2", "\\.3mm", "\\.3p2", "\\.60d", "\\.aep", "\\.ajp", "\\.amv", "\\.amx", "\\.arf", "\\.asf", "\\.asx", "\\.avb", "\\.avd", "\\.avi", "\\.avs", "\\.avs", "\\.axm", "\\.bdm", "\\.bdmv", "\\.bik", "\\.bin", "\\.bix", "\\.bmk", "\\.box", "\\.bs4", "\\.bsf", "\\.byu", "\\.camre", "\\.clpi", "\\.cpi", "\\.cvc", "\\.d2v", "\\.d3v", "\\.dat", "\\.dav", "\\.dce", "\\.dck", "\\.ddat", "\\.dif", "\\.dir", "\\.divx", "\\.dlx", "\\.dmb", "\\.dmsm", "\\.dmss", "\\.dnc", "\\.dpg", "\\.dream", "\\.dsy", "\\.dv", "\\.dv-avi", "\\.dv4", "\\.dvdmedia", "\\.dvr-ms", "\\.dvx", "\\.dxr", "\\.dzm", "\\.dzp", "\\.dzt", "\\.evo", "\\.eye", "\\.f4p", "\\.f4v", "\\.fbr", "\\.fbr", "\\.fbz", "\\.fcp", "\\.flc", "\\.flh", "\\.fli", "\\.flv", "\\.flx", "\\.gl", "\\.grasp", "\\.gts", "\\.gvi", "\\.gvp", "\\.hdmov", "\\.hkm", "\\.ifo", "\\.imovi", "\\.imovi", "\\.iva", "\\.ivf", "\\.ivr", "\\.ivs", "\\.izz", "\\.izzy", "\\.jts", "\\.lsf", "\\.lsx", "\\.m15", "\\.m1pg", "\\.m1v", "\\.m21", "\\.m21", "\\.m2a", "\\.m2p", "\\.m2t", "\\.m2ts", "\\.m2v", "\\.m4e", "\\.m4u", "\\.m4v", "\\.m75", "\\.meta", "\\.mgv", "\\.mj2", "\\.mjp", "\\.mjpg", "\\.mkv", "\\.mmv", "\\.mnv", "\\.mod", "\\.modd", "\\.moff", "\\.moi", "\\.moov", "\\.mov", "\\.movie", "\\.mp21", "\\.mp21", "\\.mp2v", "\\.mp4", "\\.mp4v", "\\.mpe", "\\.mpeg", "\\.mpeg4", "\\.mpf", "\\.mpg", "\\.mpg2", "\\.mpgin", "\\.mpl", "\\.mpls", "\\.mpv", "\\.mpv2", "\\.mqv", "\\.msdvd", "\\.msh", "\\.mswmm", "\\.mts", "\\.mtv", "\\.mvb", "\\.mvc", "\\.mvd", "\\.mve", "\\.mvp", "\\.mxf", "\\.mys", "\\.ncor", "\\.nsv", "\\.nvc", "\\.ogm", "\\.ogv", "\\.ogx", "\\.osp", "\\.par", "\\.pds", "\\.pgi", "\\.piv", "\\.playlist", "\\.pmf", "\\.prel", "\\.pro", "\\.prproj", "\\.psh", "\\.pva", "\\.pvr", "\\.pxv", "\\.qt", "\\.qtch", "\\.qtl", "\\.qtm", "\\.qtz", "\\.rcproject", "\\.rdb", "\\.rec", "\\.rm", "\\.rmd", "\\.rmp", "\\.rms", "\\.rmvb", "\\.roq", "\\.rp", "\\.rts", "\\.rts", "\\.rum", "\\.rv", "\\.sbk", "\\.sbt", "\\.scm", "\\.scm", "\\.scn", "\\.sec", "\\.seq", "\\.sfvidcap", "\\.smil", "\\.smk", "\\.sml", "\\.smv", "\\.spl", "\\.ssm", "\\.str", "\\.stx", "\\.svi", "\\.swf", "\\.swi", "\\.swt", "\\.tda3mt", "\\.tivo", "\\.tix", "\\.tod", "\\.tp", "\\.tp0", "\\.tpd", "\\.tpr", "\\.trp", "\\.ts", "\\.tvs", "\\.vc1", "\\.vcr", "\\.vcv", "\\.vdo", "\\.vdr", "\\.veg", "\\.vem", "\\.vf", "\\.vfw", "\\.vfz", "\\.vgz", "\\.vid", "\\.viewlet", "\\.viv", "\\.vivo", "\\.vlab", "\\.vob", "\\.vp3", "\\.vp6", "\\.vp7", "\\.vpj", "\\.vro", "\\.vsp", "\\.w32", "\\.wcp", "\\.webm", "\\.wm", "\\.wmd", "\\.wmmp", "\\.wmv", "\\.wmx", "\\.wp3", "\\.wpl", "\\.wtv", "\\.wvx", "\\.xfl", "\\.xvid", "\\.yuv", "\\.zm1", "\\.zm2", "\\.zm3", "\\.zmv" }; 27 | // http://www.fileinfo.com/filetypes/audio 28 | public static final String[] AUDIO_EXTENSIONS = { "\\.4mp", "\\.669", "\\.6cm", "\\.8cm", "\\.8med", "\\.8svx", "\\.a2m", "\\.aa", "\\.aa3", "\\.aac", "\\.aax", "\\.abc", "\\.abm", "\\.ac3", "\\.acd", "\\.acd-bak", "\\.acd-zip", "\\.acm", "\\.act", "\\.adg", "\\.afc", "\\.agm", "\\.ahx", "\\.aif", "\\.aifc", "\\.aiff", "\\.ais", "\\.akp", "\\.al", "\\.alaw", "\\.all", "\\.amf", "\\.amr", "\\.ams", "\\.ams", "\\.aob", "\\.ape", "\\.apf", "\\.apl", "\\.ase", "\\.at3", "\\.atrac", "\\.au", "\\.aud", "\\.aup", "\\.avr", "\\.awb", "\\.band", "\\.bap", "\\.bdd", "\\.box", "\\.bun", "\\.bwf", "\\.c01", "\\.caf", "\\.cda", "\\.cdda", "\\.cdr", "\\.cel", "\\.cfa", "\\.cidb", "\\.cmf", "\\.copy", "\\.cpr", "\\.cpt", "\\.csh", "\\.cwp", "\\.d00", "\\.d01", "\\.dcf", "\\.dcm", "\\.dct", "\\.ddt", "\\.dewf", "\\.df2", "\\.dfc", "\\.dig", "\\.dig", "\\.dls", "\\.dm", "\\.dmf", "\\.dmsa", "\\.dmse", "\\.drg", "\\.dsf", "\\.dsm", "\\.dsp", "\\.dss", "\\.dtm", "\\.dts", "\\.dtshd", "\\.dvf", "\\.dwd", "\\.ear", "\\.efa", "\\.efe", "\\.efk", "\\.efq", "\\.efs", "\\.efv", "\\.emd", "\\.emp", "\\.emx", "\\.esps", "\\.f2r", "\\.f32", "\\.f3r", "\\.f4a", "\\.f64", "\\.far", "\\.fff", "\\.flac", "\\.flp", "\\.fls", "\\.frg", "\\.fsm", "\\.fzb", "\\.fzf", "\\.fzv", "\\.g721", "\\.g723", "\\.g726", "\\.gig", "\\.gp5", "\\.gpk", "\\.gsm", "\\.gsm", "\\.h0", "\\.hdp", "\\.hma", "\\.hsb", "\\.ics", "\\.iff", "\\.imf", "\\.imp", "\\.ins", "\\.ins", "\\.it", "\\.iti", "\\.its", "\\.jam", "\\.k25", "\\.k26", "\\.kar", "\\.kin", "\\.kit", "\\.kmp", "\\.koz", "\\.koz", "\\.kpl", "\\.krz", "\\.ksc", "\\.ksf", "\\.kt2", "\\.kt3", "\\.ktp", "\\.l", "\\.la", "\\.lqt", "\\.lso", "\\.lvp", "\\.lwv", "\\.m1a", "\\.m3u", "\\.m4a", "\\.m4b", "\\.m4p", "\\.m4r", "\\.ma1", "\\.mdl", "\\.med", "\\.mgv", "\\.mid", "\\.midi", "\\.miniusf", "\\.mka", "\\.mlp", "\\.mmf", "\\.mmm", "\\.mmp", "\\.mo3", "\\.mod", "\\.mp1", "\\.mp2", "\\.mp3", "\\.mpa", "\\.mpc", "\\.mpga", "\\.mpu", "\\.mp_", "\\.mscx", "\\.mscz", "\\.msv", "\\.mt2", "\\.mt9", "\\.mte", "\\.mti", "\\.mtm", "\\.mtp", "\\.mts", "\\.mus", "\\.mws", "\\.mxl", "\\.mzp", "\\.nap", "\\.nki", "\\.nra", "\\.nrt", "\\.nsa", "\\.nsf", "\\.nst", "\\.ntn", "\\.nvf", "\\.nwc", "\\.odm", "\\.oga", "\\.ogg", "\\.okt", "\\.oma", "\\.omf", "\\.omg", "\\.omx", "\\.ots", "\\.ove", "\\.ovw", "\\.pac", "\\.pat", "\\.pbf", "\\.pca", "\\.pcast", "\\.pcg", "\\.pcm", "\\.peak", "\\.phy", "\\.pk", "\\.pla", "\\.pls", "\\.pna", "\\.ppc", "\\.ppcx", "\\.prg", "\\.prg", "\\.psf", "\\.psm", "\\.ptf", "\\.ptm", "\\.pts", "\\.pvc", "\\.qcp", "\\.r", "\\.r1m", "\\.ra", "\\.ram", "\\.raw", "\\.rax", "\\.rbs", "\\.rcy", "\\.rex", "\\.rfl", "\\.rmf", "\\.rmi", "\\.rmj", "\\.rmm", "\\.rmx", "\\.rng", "\\.rns", "\\.rol", "\\.rsn", "\\.rso", "\\.rti", "\\.rtm", "\\.rts", "\\.rvx", "\\.rx2", "\\.s3i", "\\.s3m", "\\.s3z", "\\.saf", "\\.sam", "\\.sb", "\\.sbg", "\\.sbi", "\\.sbk", "\\.sc2", "\\.sd", "\\.sd", "\\.sd2", "\\.sd2f", "\\.sdat", "\\.sdii", "\\.sds", "\\.sdt", "\\.sdx", "\\.seg", "\\.seq", "\\.ses", "\\.sf", "\\.sf2", "\\.sfk", "\\.sfl", "\\.shn", "\\.sib", "\\.sid", "\\.sid", "\\.smf", "\\.smp", "\\.snd", "\\.snd", "\\.snd", "\\.sng", "\\.sng", "\\.sou", "\\.sppack", "\\.sprg", "\\.spx", "\\.sseq", "\\.sseq", "\\.ssnd", "\\.stm", "\\.stx", "\\.sty", "\\.svx", "\\.sw", "\\.swa", "\\.syh", "\\.syw", "\\.syx", "\\.td0", "\\.tfmx", "\\.thx", "\\.toc", "\\.tsp", "\\.txw", "\\.u", "\\.ub", "\\.ulaw", "\\.ult", "\\.ulw", "\\.uni", "\\.usf", "\\.usflib", "\\.uw", "\\.uwf", "\\.vag", "\\.val", "\\.vc3", "\\.vmd", "\\.vmf", "\\.vmf", "\\.voc", "\\.voi", "\\.vox", "\\.vpm", "\\.vqf", "\\.vrf", "\\.vyf", "\\.w01", "\\.wav", "\\.wav", "\\.wave", "\\.wax", "\\.wfb", "\\.wfd", "\\.wfp", "\\.wma", "\\.wow", "\\.wpk", "\\.wproj", "\\.wrk", "\\.wus", "\\.wut", "\\.wv", "\\.wvc", "\\.wve", "\\.wwu", "\\.xa", "\\.xa", "\\.xfs", "\\.xi", "\\.xm", "\\.xmf", "\\.xmi", "\\.xmz", "\\.xp", "\\.xrns", "\\.xsb", "\\.xspf", "\\.xt", "\\.xwb", "\\.ym", "\\.zvd", "\\.zvr" }; 29 | public static final String[] SUBTRACK_EXTENSIONS = { ".srt", ".ssa", ".smi", ".txt", ".sub", ".ass" }; 30 | public static final Pattern VIDEO_EXTENSIONS_PATTERN; 31 | public static final Pattern AUDIO_EXTENSIONS_PATTERN; 32 | public static final Pattern EXTENSIONS_PATTERN; 33 | public static final Pattern SUBTRACK_EXTENSIONS_PATTERN; 34 | static { 35 | EXTENSIONS = ArrayUtils.concat(VIDEO_EXTENSIONS, AUDIO_EXTENSIONS); 36 | EXTENSIONS_PATTERN = generatePattern(EXTENSIONS); 37 | VIDEO_EXTENSIONS_PATTERN = generatePattern(VIDEO_EXTENSIONS); 38 | AUDIO_EXTENSIONS_PATTERN = generatePattern(AUDIO_EXTENSIONS); 39 | SUBTRACK_EXTENSIONS_PATTERN = generatePattern(SUBTRACK_EXTENSIONS); 40 | } 41 | 42 | public static boolean isVideoOrAudio(String url) { 43 | return EXTENSIONS_PATTERN.matcher(url.trim()).find(); 44 | } 45 | 46 | public static boolean isVideoOrAudio(File file) { 47 | return EXTENSIONS_PATTERN.matcher(file.getName().trim()).find(); 48 | } 49 | 50 | public static boolean isVideo(String url) { 51 | return VIDEO_EXTENSIONS_PATTERN.matcher(url.trim()).find(); 52 | } 53 | 54 | public static boolean isVideo(File file) { 55 | return VIDEO_EXTENSIONS_PATTERN.matcher(file.getName().trim()).find(); 56 | } 57 | 58 | public static boolean isAudio(String url) { 59 | return AUDIO_EXTENSIONS_PATTERN.matcher(url.trim()).find(); 60 | } 61 | 62 | public static boolean isAudio(File file) { 63 | return AUDIO_EXTENSIONS_PATTERN.matcher(file.getName().trim()).find(); 64 | } 65 | 66 | public static boolean isSubTrack(File file) { 67 | return SUBTRACK_EXTENSIONS_PATTERN.matcher(file.getName().trim()).find(); 68 | } 69 | 70 | public static boolean isNative(String uri) { 71 | uri = Uri.decode(uri); 72 | return uri != null && (uri.startsWith("/") || uri.startsWith("content:") || uri.startsWith("file:")); 73 | } 74 | 75 | private static Pattern generatePattern(String[] args) { 76 | StringBuffer sb = new StringBuffer(); 77 | for (String ext : args) { 78 | if (sb.length() > 0) 79 | sb.append("|"); 80 | sb.append(ext); 81 | } 82 | return Pattern.compile("(" + sb.toString() + ")$", Pattern.CASE_INSENSITIVE); 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /src/com/nmbb/oplayer/util/PinyinUtils.java: -------------------------------------------------------------------------------- 1 | package com.nmbb.oplayer.util; 2 | 3 | import net.sourceforge.pinyin4j.PinyinHelper; 4 | import net.sourceforge.pinyin4j.format.HanyuPinyinCaseType; 5 | import net.sourceforge.pinyin4j.format.HanyuPinyinOutputFormat; 6 | import net.sourceforge.pinyin4j.format.HanyuPinyinToneType; 7 | import net.sourceforge.pinyin4j.format.exception.BadHanyuPinyinOutputFormatCombination; 8 | 9 | public final class PinyinUtils { 10 | 11 | private static HanyuPinyinOutputFormat spellFormat = new HanyuPinyinOutputFormat(); 12 | 13 | static { 14 | spellFormat.setCaseType(HanyuPinyinCaseType.LOWERCASE); 15 | spellFormat.setToneType(HanyuPinyinToneType.WITHOUT_TONE); 16 | //spellFormat.setVCharType(HanyuPinyinVCharType.WITH_V); 17 | } 18 | 19 | public static String chineneToSpell(String chineseStr) throws BadHanyuPinyinOutputFormatCombination { 20 | StringBuffer result = new StringBuffer(); 21 | for (char c : chineseStr.toCharArray()) { 22 | if (c > 128) { 23 | String[] array = PinyinHelper.toHanyuPinyinStringArray(c, spellFormat); 24 | if (array != null && array.length > 0) 25 | result.append(array[0]); 26 | else 27 | result.append(" "); 28 | } else 29 | result.append(c); 30 | } 31 | return result.toString(); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/com/nmbb/oplayer/util/ToastUtils.java: -------------------------------------------------------------------------------- 1 | package com.nmbb.oplayer.util; 2 | 3 | import android.app.Activity; 4 | import android.content.Context; 5 | import android.view.View; 6 | import android.widget.Toast; 7 | 8 | import com.nmbb.oplayer.OPlayerApplication; 9 | import com.nmbb.oplayer.R; 10 | 11 | public class ToastUtils { 12 | 13 | public static void showToast(int resID) { 14 | showToast(OPlayerApplication.getContext(), Toast.LENGTH_SHORT, resID); 15 | } 16 | 17 | public static void showToast(String text) { 18 | showToast(OPlayerApplication.getContext(), Toast.LENGTH_SHORT, text); 19 | } 20 | 21 | public static void showToast(Context ctx, int resID) { 22 | showToast(ctx, Toast.LENGTH_SHORT, resID); 23 | } 24 | 25 | public static void showToast(Context ctx, String text) { 26 | showToast(ctx, Toast.LENGTH_SHORT, text); 27 | } 28 | 29 | public static void showLongToast(Context ctx, int resID) { 30 | showToast(ctx, Toast.LENGTH_LONG, resID); 31 | } 32 | 33 | public static void showLongToast(int resID) { 34 | showToast(OPlayerApplication.getContext(), Toast.LENGTH_LONG, resID); 35 | } 36 | 37 | public static void showLongToast(Context ctx, String text) { 38 | showToast(ctx, Toast.LENGTH_LONG, text); 39 | } 40 | 41 | public static void showLongToast(String text) { 42 | showToast(OPlayerApplication.getContext(), Toast.LENGTH_LONG, text); 43 | } 44 | 45 | public static void showToast(Context ctx, int duration, int resID) { 46 | showToast(ctx, duration, ctx.getString(resID)); 47 | } 48 | 49 | public static void showToast(Context ctx, int duration, String text) { 50 | Toast toast = Toast.makeText(ctx, text, duration); 51 | View mNextView = toast.getView(); 52 | if (mNextView != null) 53 | mNextView.setBackgroundResource(R.drawable.toast_frame); 54 | toast.show(); 55 | // Toast.makeText(ctx, text, duration).show(); 56 | } 57 | 58 | // public static void showToastOnUiThread(final String text) { 59 | // showToastOnUiThread(FSAppliction.getCurrentActivity(), text); 60 | // } 61 | 62 | /** 在UI线程运行弹出 */ 63 | public static void showToastOnUiThread(final Activity ctx, final String text) { 64 | if (ctx != null) { 65 | ctx.runOnUiThread(new Runnable() { 66 | 67 | @Override 68 | public void run() { 69 | showToast(ctx, text); 70 | } 71 | }); 72 | } 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /src/com/nmbb/oplayer/video/VideoThumbnailUtils.java: -------------------------------------------------------------------------------- 1 | package com.nmbb.oplayer.video; 2 | 3 | import android.graphics.Bitmap; 4 | 5 | public final class VideoThumbnailUtils { 6 | 7 | /** 获取视频的缩略图 */ 8 | public static Bitmap createVideoThumbnail() { 9 | return null; 10 | } 11 | 12 | /** 获取视频的时长 */ 13 | public int getDuration() { 14 | return 1; 15 | } 16 | 17 | /** 获取视频的高度 */ 18 | public int getVideoHeight() { 19 | return 1; 20 | } 21 | 22 | /** 获取视频的宽度 */ 23 | public int getVideoWidth() { 24 | return 1; 25 | } 26 | } 27 | --------------------------------------------------------------------------------