Repository: android-cjj/BiliClient Branch: Bilibili Commit: 9e55e1cffded Files: 198 Total size: 12.8 MB Directory structure: gitextract__3zxuyt5/ ├── .gitattributes ├── .gitignore ├── .gradle/ │ └── 2.2.1/ │ └── taskArtifacts/ │ └── cache.properties ├── .idea/ │ ├── .name │ ├── compiler.xml │ ├── copyright/ │ │ └── profiles_settings.xml │ ├── encodings.xml │ ├── gradle.xml │ ├── inspectionProfiles/ │ │ ├── Project_Default.xml │ │ └── profiles_settings.xml │ ├── libraries/ │ │ ├── appcompat_v7_22_1_1.xml │ │ ├── jsoup_1_8_1.xml │ │ ├── multidex_1_0_0.xml │ │ ├── support_annotations_22_1_1.xml │ │ ├── support_v4_22_1_1.xml │ │ └── universal_image_loader_1_9_3.xml │ ├── misc.xml │ ├── modules.xml │ ├── scopes/ │ │ └── scope_settings.xml │ ├── vcs.xml │ └── workspace.xml ├── BilibiliClient.iml ├── README.md ├── apk/ │ └── bb.apk ├── app/ │ ├── .gitignore │ ├── app.iml │ ├── build.gradle │ ├── libs/ │ │ ├── jsoup-1.8.1.jar │ │ └── universal-image-loader-1.9.3.jar │ ├── proguard-rules.pro │ └── src/ │ ├── androidTest/ │ │ └── java/ │ │ └── com/ │ │ └── cjj/ │ │ └── bb/ │ │ └── ApplicationTest.java │ └── main/ │ ├── AndroidManifest.xml │ ├── assets/ │ │ ├── comment.json │ │ └── online.xml │ ├── java/ │ │ ├── com/ │ │ │ └── cjj/ │ │ │ └── bb/ │ │ │ ├── activity/ │ │ │ │ ├── ABPlayerApplication.java │ │ │ │ ├── BiliVideoViewActivity.java │ │ │ │ ├── BiliWebviewActivity.java │ │ │ │ ├── DonghuaActivity.java │ │ │ │ ├── MainActivity.java │ │ │ │ ├── TVActivity.java │ │ │ │ ├── VideoInfoActivity.java │ │ │ │ └── VideoViewActivity.java │ │ │ ├── adapter/ │ │ │ │ ├── AreaGridAdapter.java │ │ │ │ ├── ArrayAdapter.java │ │ │ │ ├── BankumiTabAdapter.java │ │ │ │ ├── DianyingTabAdapter.java │ │ │ │ ├── DonghuaTabAdapter.java │ │ │ │ ├── GameListAdapter.java │ │ │ │ ├── GridAdapter.java │ │ │ │ ├── ItemsAdapter.java │ │ │ │ ├── KejiTabAdapter.java │ │ │ │ ├── MainTabAdapter.java │ │ │ │ ├── MusicTabAdapter.java │ │ │ │ ├── RankAdapter.java │ │ │ │ ├── VideoInfoListAdapter.java │ │ │ │ ├── VideoListAdapter.java │ │ │ │ ├── YouxiTabAdapter.java │ │ │ │ └── YuleTabAdapter.java │ │ │ ├── fragment/ │ │ │ │ ├── BangumiFragment.java │ │ │ │ ├── BroadcastTimetableFragment.java │ │ │ │ ├── DonghuaFragment.java │ │ │ │ ├── FragmentLogin.java │ │ │ │ ├── FramentTime.java │ │ │ │ ├── GamesCenterFragment.java │ │ │ │ ├── HomePageFragment.java │ │ │ │ ├── HomePageFragment2.java │ │ │ │ ├── OnlineFragment.java │ │ │ │ ├── PersonCenterFragment.java │ │ │ │ ├── RankFragment.java │ │ │ │ ├── RelevantVideoFragment.java │ │ │ │ ├── SubareaFragment.java │ │ │ │ └── VideoInfoFragment.java │ │ │ ├── model/ │ │ │ │ ├── AreaItem.java │ │ │ │ ├── BannerItem.java │ │ │ │ ├── GameItem.java │ │ │ │ ├── OnlineVideo.java │ │ │ │ ├── Page.java │ │ │ │ ├── User.java │ │ │ │ ├── Video.java │ │ │ │ └── VideoItem.java │ │ │ ├── utils/ │ │ │ │ ├── ArrayUtils.java │ │ │ │ ├── CompressionTools.java │ │ │ │ ├── Constants.java │ │ │ │ ├── DeviceUtils.java │ │ │ │ ├── DownUtil.java │ │ │ │ ├── FileUitl.java │ │ │ │ ├── FileUtils.java │ │ │ │ ├── FractionalTouchDelegate.java │ │ │ │ ├── HttpDownloader.java │ │ │ │ ├── HttpUtil.java │ │ │ │ ├── ImageUtils.java │ │ │ │ ├── IntentHelper.java │ │ │ │ ├── JsoupUtil.java │ │ │ │ ├── Logger.java │ │ │ │ ├── MediaUtils.java │ │ │ │ ├── MultiMemberGZIPInputStream.java │ │ │ │ ├── PreferenceUtils.java │ │ │ │ ├── StringUtils.java │ │ │ │ ├── ToastUtils.java │ │ │ │ ├── URLUtil.java │ │ │ │ └── XmlReaderHelper.java │ │ │ └── view/ │ │ │ ├── ApplicationUtils.java │ │ │ ├── CircleImageView.java │ │ │ ├── CommonGestures.java │ │ │ ├── FileUtils.java │ │ │ ├── LeftSliderLayout.java │ │ │ ├── MediaController.java │ │ │ ├── PlayerService.java │ │ │ ├── PullToZoomListView.java │ │ │ ├── VP.java │ │ │ └── VideoView.java │ │ └── viewpagerindicator/ │ │ ├── CirclePageIndicator.java │ │ ├── IconPageIndicator.java │ │ ├── IconPagerAdapter.java │ │ ├── IcsLinearLayout.java │ │ ├── LinePageIndicator.java │ │ ├── PageIndicator.java │ │ ├── TabPageIndicator.java │ │ ├── TitlePageIndicator.java │ │ └── UnderlinePageIndicator.java │ └── res/ │ ├── anim/ │ │ ├── bili_anim.xml │ │ ├── push_left_in.xml │ │ ├── push_no.xml │ │ ├── slide_in_bottom.xml │ │ ├── slide_in_top.xml │ │ ├── slide_out_bottom.xml │ │ └── slide_out_top.xml │ ├── color/ │ │ ├── vpi__dark_theme.xml │ │ └── vpi__light_theme.xml │ ├── drawable/ │ │ ├── back_btn.xml │ │ ├── base_action_bar_action_more_selector.xml │ │ ├── card_background.xml │ │ ├── comment_btn.xml │ │ ├── corner.xml │ │ ├── dot_focused.xml │ │ ├── dot_normal.xml │ │ ├── focus_show.xml │ │ ├── home_btn_bg.xml │ │ ├── image_corner.xml │ │ ├── list_selector.xml │ │ ├── normal_show.xml │ │ ├── progressbar_large.xml │ │ ├── selector_tabtext.xml │ │ ├── tab_indicator.xml │ │ └── vpi__tab_indicator.xml │ ├── drawable-xhdpi/ │ │ └── mediacontroller_btn_bg.xml │ ├── layout/ │ │ ├── activity_main.xml │ │ ├── activity_video.xml │ │ ├── activity_video_info.xml │ │ ├── area_item.xml │ │ ├── back_head.xml │ │ ├── banner.xml │ │ ├── bili_videoview.xml │ │ ├── bili_webview.xml │ │ ├── bili_webview_head.xml │ │ ├── brightness_volumn.xml │ │ ├── card_layout.xml │ │ ├── donghua_tab.xml │ │ ├── fragment_donghua.xml │ │ ├── fragment_gamecenter.xml │ │ ├── fragment_homepage.xml │ │ ├── fragment_main.xml │ │ ├── fragment_online.xml │ │ ├── fragment_online_item.xml │ │ ├── fragment_subarea.xml │ │ ├── fragment_videoinfo.xml │ │ ├── game_list_item.xml │ │ ├── homepage_item.xml │ │ ├── item.xml │ │ ├── items_list.xml │ │ ├── main_head.xml │ │ ├── mediacontroller.xml │ │ ├── video_info_list_item.xml │ │ ├── video_list_item.xml │ │ └── videoview.xml │ ├── menu/ │ │ ├── main.xml │ │ └── menu_main.xml │ ├── raw/ │ │ └── comments.xml │ ├── values/ │ │ ├── attrs.xml │ │ ├── colors.xml │ │ ├── dimens.xml │ │ ├── integers.xml │ │ ├── strings.xml │ │ ├── styles.xml │ │ ├── vpi__attrs.xml │ │ ├── vpi__colors.xml │ │ ├── vpi__defaults.xml │ │ └── vpi__styles.xml │ └── values-w820dp/ │ └── dimens.xml ├── build/ │ └── intermediates/ │ └── dex-cache/ │ └── cache.xml ├── build.gradle ├── gradle/ │ └── wrapper/ │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradle.properties ├── gradlew ├── gradlew.bat ├── local.properties └── settings.gradle ================================================ FILE CONTENTS ================================================ ================================================ FILE: .gitattributes ================================================ # Auto detect text files and perform LF normalization * text=auto # Custom for Visual Studio *.cs diff=csharp # Standard to msysgit *.doc diff=astextplain *.DOC diff=astextplain *.docx diff=astextplain *.DOCX diff=astextplain *.dot diff=astextplain *.DOT diff=astextplain *.pdf diff=astextplain *.PDF diff=astextplain *.rtf diff=astextplain *.RTF diff=astextplain ================================================ FILE: .gitignore ================================================ # Windows image file caches Thumbs.db ehthumbs.db # Folder config file Desktop.ini # Recycle Bin used on file shares $RECYCLE.BIN/ # Windows Installer files *.cab *.msi *.msm *.msp # Windows shortcuts *.lnk # ========================= # Operating System Files # ========================= # OSX # ========================= .DS_Store .AppleDouble .LSOverride # Thumbnails ._* # Files that might appear on external disk .Spotlight-V100 .Trashes # Directories potentially created on remote AFP share .AppleDB .AppleDesktop Network Trash Folder Temporary Items .apdisk ================================================ FILE: .gradle/2.2.1/taskArtifacts/cache.properties ================================================ #Mon May 25 14:28:55 CST 2015 ================================================ FILE: .idea/.name ================================================ BilibiliClient ================================================ FILE: .idea/compiler.xml ================================================ ================================================ FILE: .idea/copyright/profiles_settings.xml ================================================ ================================================ FILE: .idea/encodings.xml ================================================ ================================================ FILE: .idea/gradle.xml ================================================ ================================================ FILE: .idea/inspectionProfiles/Project_Default.xml ================================================ ================================================ FILE: .idea/inspectionProfiles/profiles_settings.xml ================================================ ================================================ FILE: .idea/libraries/appcompat_v7_22_1_1.xml ================================================ ================================================ FILE: .idea/libraries/jsoup_1_8_1.xml ================================================ ================================================ FILE: .idea/libraries/multidex_1_0_0.xml ================================================ ================================================ FILE: .idea/libraries/support_annotations_22_1_1.xml ================================================ ================================================ FILE: .idea/libraries/support_v4_22_1_1.xml ================================================ ================================================ FILE: .idea/libraries/universal_image_loader_1_9_3.xml ================================================ ================================================ FILE: .idea/misc.xml ================================================ 1.7 ================================================ FILE: .idea/modules.xml ================================================ ================================================ FILE: .idea/scopes/scope_settings.xml ================================================ ================================================ FILE: .idea/vcs.xml ================================================ ================================================ FILE: .idea/workspace.xml ================================================ localhost 5050 1432535307771 1432535307771 ================================================ FILE: BilibiliClient.iml ================================================ ================================================ FILE: README.md ================================================ BiliClient ========================================================================================================================= 说明 ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ###这是仿bilibili客户端,是我一个刚学android的朋友写的,原作地址: https://github.com/winkstu/ABPlayer ###开发工具是eclipse,我下了下来,迁移到as上, ###和做了一些修改。 bilibili截图 --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ![](http://www.apkbus.com/data/attachment/album/201505/26/164030en9nb4rsmso9nqpc.png) ![](http://www.apkbus.com/data/attachment/album/201505/26/164035tgq1hqt7boy7zbtq.png) ![](http://www.apkbus.com/data/attachment/album/201505/26/164031wptzct3jhnj9n6c6.png) ![](http://www.apkbus.com/data/attachment/album/201505/26/164033sgz2y2un1xa7wy3e.png) ![](http://www.apkbus.com/data/attachment/album/201505/26/164032ezo7xm6a36rm3flp.png) ![](http://www.apkbus.com/data/attachment/album/201505/26/164032w6zwrz9zdvw6k1d3.jpg) btw:图片仅供参考,请以apk为标准,啊哈哈,不过所给图片的功能逻辑都已经实现。。。 ![](http://www.apkbus.com/data/attachment/forum/201505/26/181654rgzwvvz5gt9mxgzm.gif) ================================================ FILE: apk/bb.apk ================================================ [File too large to display: 11.8 MB] ================================================ FILE: app/.gitignore ================================================ /build ================================================ FILE: app/app.iml ================================================ ================================================ FILE: app/build.gradle ================================================ apply plugin: 'com.android.application' android { compileSdkVersion 22 buildToolsVersion "22.0.1" defaultConfig { applicationId "com.cjj.bb" minSdkVersion 15 targetSdkVersion 22 versionCode 1 versionName "1.0" multiDexEnabled true // dex突破65535的限制 multiDexEnabled true // 默认是xinhao的渠道 manifestPlaceholders = [UMENG_CHANNEL_VALUE: "bili"] } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } productFlavors { xinhao { manifestPlaceholders = [UMENG_CHANNEL_VALUE: "cjj"] } weixin { manifestPlaceholders = [UMENG_CHANNEL_VALUE: "bili"] } // baidu { // manifestPlaceholders = [UMENG_CHANNEL_VALUE: "baidu"] // } // wandoujia { // manifestPlaceholders = [UMENG_CHANNEL_VALUE: "wandoujia"] // } } } dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) compile 'com.android.support:appcompat-v7:22.1.1' compile project(':vitamio') compile files('libs/universal-image-loader-1.9.3.jar') compile files('libs/jsoup-1.8.1.jar') compile project(':DanmakuFlameMaster') // compile project(':VPIndexLibrary') compile 'com.android.support:support-v4:22.1.1' } ================================================ FILE: app/proguard-rules.pro ================================================ # Add project specific ProGuard rules here. # By default, the flags in this file are appended to flags specified # in D:\as\sdk-install/tools/proguard/proguard-android.txt # You can edit the include path and order by changing the proguardFiles # directive in build.gradle. # # For more details, see # http://developer.android.com/guide/developing/tools/proguard.html # Add any project specific keep options here: # If your project uses WebView with JS, uncomment the following # and specify the fully qualified class name to the JavaScript interface # class: #-keepclassmembers class fqcn.of.javascript.interface.for.webview { # public *; #} ================================================ FILE: app/src/androidTest/java/com/cjj/bb/ApplicationTest.java ================================================ package com.cjj.bb; import android.app.Application; import android.test.ApplicationTestCase; /** * Testing Fundamentals */ public class ApplicationTest extends ApplicationTestCase { public ApplicationTest() { super(Application.class); } } ================================================ FILE: app/src/main/AndroidManifest.xml ================================================ ================================================ FILE: app/src/main/assets/comment.json ================================================ [{"c":"0,16777215,1,25,196050,1364468342","m":"。。。。。。。。。。。。。。。。。。。。。。"},{"c":"3.619,16777215,1,25,196050,1364468347","m":"。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。"},{"c":"7.539,16777215,1,25,196050,1364468351","m":"。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。"},{"c":"11.291,16777215,1,25,196050,1364468355","m":"。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。"},{"c":"13.476,16777215,1,25,196050,1364468357","m":"。。。。。。。。"},{"c":"1.724,16777215,1,25,196050,1364468442","m":"3.28 打卡"},{"c":"31.229,16777215,1,25,478568,1364994609","m":"0 0"},{"c":"54.791,16777215,1,25,418656,1365183861","m":"...."},{"c":"65.617,10027008,1,25,2ack2073121228,1365184819","m":"一天不看香蕉君,不舒服斯基丶"},{"c":"11.188,16776960,1,25,478568,1365823290","m":"。。。。"},{"c":"61.625,16776960,1,25,478568,1365823340","m":"卧槽"},{"c":"87.933,16777215,1,25,461326,1366819637","m":"小湿机你在看咩"},{"c":"87.933,16777215,1,25,461326,1366819652","m":"小湿机"},{"c":"0,16776960,1,25,1bak1902192501,1368157455","m":".."},{"c":"10.711,16776960,1,25,1bak1902192501,1368157482","m":"............................"},{"c":"39.512,16777215,1,25,27dk1948164898,1368848882","m":"科比"},{"c":"35.673,16777215,1,25,22ck1867180364,1369403593","m":"播放次数:396042"},{"c":"61.976,16777215,1,25,24ek2015510060,1370615680","m":"在线2 "},{"c":"6.519,16777215,1,25,17dk3730002906,1370623489","m":"卧槽...点错了"},{"c":"27.787,16777215,1,25,36ek248534870,1370698155","m":"金♂刚♂如♂来"},{"c":"87.589,16777215,1,25,350k2104532353,1370921441","m":" 萎了、、、、、、、、、、、、"},{"c":"23.343,16777215,1,25,1f0k242492437,1371043001","m":"fuck"},{"c":"79.84,16777215,1,25,1f0k242492437,1371043057","m":"顶上去报复社会"},{"c":"49.79,16777215,1,25,231580,1371209285","m":"美国"},{"c":"47.652,65280,1,25,498k2063980741,1371983881","m":" 暖被窝一次一千円节假日半价 / 发布于 2011年 4月28日(星期四) 7时24分 / 播放:397078 评论:2456 收藏:1504 "},{"c":"25.769,16777215,1,25,38ek1896980399,1373078365","m":"炒饭无误"},{"c":"15.499,16777215,1,25,104k3072012724,1373078412","m":"顶上去!!!!!报复社会!!!!!!!!!!"},{"c":"87.927,16777215,1,25,535868,1373078428","m":"打卡"},{"c":"54.177,16777215,1,25,104k3072012724,1373078485","m":"收藏的什么性取向?"},{"c":"55.095,16777215,1,25,2d9k2101697339,1373082287","m":"我瞎了。。。"},{"c":"8.009,16777215,1,25,1fbk1946851889,1373082945","m":"报复社会"},{"c":"64.865,16777215,1,25,2e5k1018989651,1373083835","m":"耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶"},{"c":"15.102,16777215,1,25,2e5k1018989651,1373083865","m":"耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶"},{"c":"72.016,16777215,1,25,563619,1373086101","m":"顶上去报复社会"},{"c":"4.466,16777215,1,25,563619,1373086131","m":"1584个收藏是闹那样"},{"c":"65.066,16777215,1,25,4c7k2002975241,1373086719","m":"改版后老多老坟"},{"c":"33.342,16777215,1,25,1ffk2090928940,1373087526","m":"2013年7月6日 13:12:22"},{"c":"22.229,16777215,1,25,247k1855594942,1373088592","m":"2013.7.6"},{"c":"11.035,16777215,1,25,117k3702574478,1373089139","m":"yoooooooooooooooooooooooooooooo"},{"c":"23.519,16777215,1,25,115k3078797035,1373092760","m":"2013年7月6日14:39:18"},{"c":"17.136,16777215,1,25,484k1017188638,1373093593","m":"......................................................"},{"c":"82.21,16777215,1,25,4c3k244535907,1373094036","m":"石更了"},{"c":"3.156,65280,1,25,551590,1373094641","m":"。。。。。。。。。。。。"},{"c":"18.774,65280,1,25,551590,1373094657","m":"我次奥"},{"c":"5.036,16777215,1,25,329k987402398,1373095195","m":"草"},{"c":"17.707,16777215,1,25,33ck249485211,1373103359","m":"耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶"},{"c":"15.1,16777215,1,37,33ck249485211,1373103502","m":"耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶"},{"c":"15.246,3407616,1,25,48ek3702141711,1373106289","m":"耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶"},{"c":"22.92,3407616,1,25,48ek3702141711,1373106384","m":"耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶"},{"c":"21.267,16711833,1,25,1f8k3671002319,1373107024","m":"耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶"},{"c":"35.259,16777215,1,25,482k3721736082,1373107177","m":"打卡"},{"c":"16.772,16777215,1,25,123k2075644583,1373108045","m":"耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶"},{"c":"81.461,16777215,1,25,308543,1373109391","m":"我居然无耻的看完了"},{"c":"16.612,16777215,1,25,36ek1035411925,1373109676","m":"炒饭小号 无误"},{"c":"6.797,16777215,1,25,501507,1373110201","m":"每日打卡"},{"c":"20.621,16777215,1,25,192k2103294627,1373110747","m":"............"},{"c":"84.827,16777215,1,25,28ak467794641,1373111880","m":"双手打字以示清白"},{"c":"7.152,16737792,1,25,262k455357332,1373112100","m":"啊"},{"c":"14.061,16777215,1,25,562163,1373115212","m":"耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶"},{"c":"2.747,65280,1,25,30bk3722666395,1373115887","m":"打卡啦"},{"c":"32.453,16777215,1,25,1adk3736329486,1373116156","m":"求BGM!!!!!!!!!!!!!!!!!!!!!!!!!!"},{"c":"55.498,16777215,1,25,1aak3072357289,1373118377","m":" 还能动。。。。"},{"c":"61.828,16777215,1,25,1aak3072357289,1373118380","m":"FUCK"},{"c":"20.848,16777215,1,25,3eek1962717247,1373121959","m":"我来打卡了......."},{"c":"40.693,3381759,1,25,1edk1962794156,1373123160","m":"1111111111111111111111111111111111111111"},{"c":"52.029,3381759,1,25,1edk1962794156,1373123171","m":"1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111"},{"c":"4.408,16777215,1,25,2f9k454125677,1373124185","m":"哦草!"},{"c":"50.444,65280,1,25,553421,1373125176","m":"收藏1618什么心态..."},{"c":"38.361,16777215,1,25,4a4k29683238,1373126181","m":"你麻痹?"},{"c":"19.81,16777215,1,25,3d2k1967534807,1373132178","m":"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"},{"c":"17.87,16777215,1,25,451k465242735,1373135469","m":"哎呦卧槽,顶上去报复世界"},{"c":"12.465,16777215,1,25,1abk2016062444,1373146913","m":"2013年7月7日5:40:08"},{"c":"22.633,16777215,1,25,420552,1373155854","m":"必须顶上去报复社会"},{"c":"0,16777215,1,25,548565,1373158670","m":"打卡"},{"c":"21.253,16777215,1,25,548565,1373158760","m":""},{"c":"12.916,16777215,1,25,406k2091038619,1373159899","m":"打卡2013年7月7日9:17:11"},{"c":"16.102,16777215,1,25,174857,1373163531","m":"耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶"},{"c":"28.248,16777215,1,25,418656,1373164750","m":"打卡"},{"c":"28.434,16777215,1,25,258613,1373166524","m":"香蕉君无敌了"},{"c":"16.911,16777215,1,25,444k1861315545,1373166705","m":"香蕉君!"},{"c":"77.817,16777215,1,25,186k1885029973,1373166760","m":"双手打字以示清白"},{"c":"32.187,16777215,1,25,184k2102925457,1373168322","m":"bibli"},{"c":"12.112,16777215,1,25,489191,1373168409","m":"2013年7月7日11:40:17"},{"c":"16.479,16776960,1,25,334k3740305770,1373168589","m":"烧死这些同性恋"},{"c":"15.867,16711680,1,25,357k3730546841,1373170277","m":"简直丧心病狂"},{"c":"10.316,16777215,1,25,3cdk1035642435,1373171091","m":"501"},{"c":"19.164,16711782,1,25,3ffk717661093,1373171300","m":"。。。。。。。。。。。。。。。。。。。。。。。。。。"},{"c":"17.066,16711782,1,25,3ffk717661093,1373171306","m":"!!!"},{"c":"4.323,16777215,1,25,269k3738528475,1373172137","m":"2013 7.7"},{"c":"42.129,10027008,4,37,31dk3033839023,1373174002","m":"科比!"},{"c":"12.815,16777215,1,25,26ck3074307386,1373175261","m":" 打卡"},{"c":"46.931,16777215,1,25,187k3682680642,1373176996","m":"..........."},{"c":"78.136,16777215,1,25,13ak1874150387,1373180305","m":"报复社会。。"},{"c":"9.993,16711680,1,25,16dk3071440325,1373181548","m":"我是小伙伴! 我是小伙伴!"},{"c":"44.141,16711680,4,37,16dk3071440325,1373181608","m":"我是小伙伴!"},{"c":"15.061,16777215,1,25,150k1987611877,1373181620","m":"耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶"},{"c":"64.491,16711680,4,37,16dk3071440325,1373181628","m":"我是小伙伴!我是小伙伴!我是小伙伴!我是小伙伴!我是小伙伴!我是小伙伴!我是小伙伴!我是小伙伴!我是小伙伴!我是小伙伴!我是小伙伴!我是小伙伴!我是小伙伴!我是小伙伴!我是小伙伴!我是小伙伴!我是小伙"},{"c":"15.237,16777215,1,25,415083,1373182130","m":"日常打卡,"},{"c":"23.934,16777215,1,25,420552,1373186603","m":"报复社会节奏开启"},{"c":"8.832,16777215,1,25,366k2936106977,1373186676","m":"2013年7月7日16:43:41"},{"c":"52.229,16777215,1,25,217k3722465722,1373187469","m":"主页 \u003e 生活娱乐 / 暖被窝一次一千円节假日半价 / 发布于 2011年 4月28日(星期四) 7时24分 / 播放:404511 评论:2486 收藏:1638 / 举"},{"c":"9.524,16777215,1,25,446k987429084,1373190152","m":"- - - - - - "},{"c":"37.971,16777215,1,25,446k987429084,1373190180","m":" 这打吗的好屌"},{"c":"14.824,16777215,1,25,36ak1874994172,1373192037","m":"耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶"},{"c":"58.871,16777215,1,25,2bak2006106235,1373192955","m":"无法直视Ort"},{"c":"48.069,16777215,1,25,376k242592647,1373197574","m":"主页 \u003e 生活娱乐 / 暖被窝一次一千円节假日半价 / 发布于 2011年 4月28日(星期四) 7时24分 / 播放:404903 评论:2502 收藏:1646 / 举"},{"c":"41.6,3407616,1,25,385k3726527761,1373198456","m":"耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶"},{"c":"43.539,16777215,1,25,317k3740600479,1373201930","m":"吊..................................................................................................."},{"c":"0,16777215,1,25,2dfk3683682083,1373202156","m":"呵呵呵呵呵"},{"c":"40.008,16777215,1,25,247k1946749991,1373205163","m":"叼暴了"},{"c":"86.723,16777215,1,37,247k1946749991,1373205210","m":"撸起来,骚年"},{"c":"16.624,16777215,1,25,395k3740450750,1373205479","m":"18个香蕉不说话"},{"c":"11.544,16777215,1,25,2c7k1965573824,1373205504","m":"2013年7月7日 21:57:24 打卡"},{"c":"29.134,13369344,1,25,27fk3062632765,1373206329","m":"啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊"},{"c":"34.049,16777215,1,25,1a2k1968491684,1373207523","m":"卧槽"},{"c":"84.827,16777215,1,25,420552,1373208023","m":"顶上去报复社会"},{"c":"14.981,16777215,1,25,361k1912296216,1373209053","m":"顶上去啊!!!!!!!!!!!!!!!!!!"},{"c":"51.766,16777215,1,25,361k1912296216,1373209106","m":"1657个收藏 我干"},{"c":"14.226,3407616,1,25,304k3722405032,1373209311","m":"。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。"},{"c":"40.375,16777215,1,25,152k3661681594,1373211071","m":"啊婆主 已经在上心病狂"},{"c":"8.751,16777215,1,25,4a8k3029030104,1373212120","m":"打卡"},{"c":"63.029,16777215,1,25,3dck454568877,1373214809","m":"yooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo"},{"c":"82.312,16777215,1,25,545714,1373215092","m":"2013年7月8日0:38:20"},{"c":"21.909,16777215,1,25,237975,1373224589","m":"谁挖坟的"},{"c":"22.424,16777215,1,25,451k465242735,1373240898","m":"每日报复社会节奏"},{"c":"14.501,16777215,1,25,3ack1901744269,1373242869","m":"耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶"},{"c":"10.479,65280,1,25,150k1870239625,1373244297","m":"科比加强版"},{"c":"20.483,16777215,1,25,466k986806395,1373249876","m":"耶"},{"c":"14.877,16777215,1,25,144k1896832537,1373250214","m":"耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶"},{"c":"12.279,16777215,1,25,2c4k2095314541,1373250965","m":"我来打卡了"},{"c":"62.535,16777215,1,25,261770,1373251247","m":"...."},{"c":"82.023,16777215,1,25,451k465242735,1373253347","m":"赢了怎么破"},{"c":"12.744,52479,1,25,451k465242735,1373342293","m":"顶上去报复社会"},{"c":"17.345,16777215,1,25,423547,1373815673","m":"报复社会,走你"},{"c":"42.26,16777215,1,25,244k2004555617,1373984022","m":"x笑尿。。"},{"c":"39.958,65280,1,25,360346,1374154683","m":"好吧我手滑一下"},{"c":"54.943,65280,1,25,360346,1374154698","m":"无法直视"},{"c":"13.424,16777215,1,25,325344,1374311786","m":"打卡。。 2013年7月20日 17:15:56"},{"c":"0,16724838,1,25,3c5k242233919,1374320952","m":"吾欲报复社会"},{"c":"15.278,16777215,1,25,585664,1376018232","m":"耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶"},{"c":"18.567,16777215,1,25,585664,1376018236","m":"耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶"},{"c":"37.071,13434624,1,25,104k2003100892,1376019458","m":"耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶"},{"c":"19.153,13369344,1,25,458834,1376019767","m":"我擦破"},{"c":"17.607,13369344,1,25,458834,1376019864","m":"耶耶耶耶耶耶耶耶耶爷爷夜"},{"c":"0,6750003,1,25,612871,1376020469","m":"...."},{"c":"20.048,16776960,4,25,539076,1376020667","m":"打卡! "},{"c":"10.402,16777215,1,25,460k3707822210,1376022278","m":"........................"},{"c":"1.338,16777215,1,25,19ak3084018091,1376023699","m":"摇起来"},{"c":"47.208,16777215,1,25,611704,1376025935","m":"...............收藏的什么心态"},{"c":"19.201,16777215,1,25,149k993230092,1376025990","m":"我去"},{"c":"50.283,16777215,1,25,149k993230092,1376026021","m":"鹅鹅鹅鹅鹅鹅鹅鹅鹅鹅鹅鹅鹅鹅鹅鹅鹅鹅鹅鹅鹅鹅鹅鹅鹅鹅鹅鹅鹅鹅鹅鹅鹅鹅鹅鹅鹅鹅鹅鹅鹅鹅鹅鹅鹅鹅鹅鹅鹅鹅鹅鹅鹅鹅鹅鹅鹅鹅鹅鹅饿鹅鹅鹅鹅鹅鹅鹅鹅鹅鹅鹅鹅鹅鹅鹅鹅鹅鹅鹅鹅鹅鹅鹅鹅鹅鹅鹅鹅鹅鹅鹅鹅鹅鹅鹅鹅鹅鹅鹅"},{"c":"80.286,16777215,1,25,149k993230092,1376026051","m":"啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊"},{"c":"27.743,16777215,1,25,403201,1376027204","m":"看上瘾了咋办"},{"c":"25.821,16737996,1,25,530815,1376028242","m":"!!!!!!!!!!!!!!!!!!!!"},{"c":"36.653,16737996,1,25,530815,1376028253","m":"干干干干干干干干干干干干干干干干干干干干干干干干干干干干干干干干干干干干干干干干干干干干干干干干干干干干干干干干干干干干干干干干干干"},{"c":"39.751,16737996,1,25,530815,1376028257","m":"干干干干干干干干干干干干干干干干干干干干干干"},{"c":"43.081,16737996,1,25,530815,1376028260","m":"干干干干干干干干干干干干干干干干干干干干干干干干干干干"},{"c":"45.765,16737996,1,25,530815,1376028263","m":"干干干干干干干干干干干干干干干干干干干干干干"},{"c":"48.797,16737996,1,25,530815,1376028266","m":"干干干干干干干干干干干干干干干干干干干干干干干干"},{"c":"51.47,16737996,1,25,530815,1376028268","m":"干干干干干干干干干干干干干干干干干干干干干干干干干干"},{"c":"54.289,16737996,1,25,530815,1376028271","m":"干干干干干干干干干干干干干干干干干干干干干干干干干干干"},{"c":"56.611,16737996,1,25,530815,1376028274","m":"干干干干干干干干干干干干干干干干干干干干干干干干"},{"c":"58.936,16737996,1,25,530815,1376028276","m":"干干干干干干干干干干干干干干干干干干干干干"},{"c":"61.193,16737996,1,25,530815,1376028278","m":"干干干干干干干干干干干干干干干干干干干"},{"c":"63.175,16737996,1,25,530815,1376028280","m":"干干干干干干干干干干干干干"},{"c":"26.562,16777215,1,25,571814,1376028282","m":"耶耶耶耶耶耶耶耶耶耶耶"},{"c":"66.757,16737996,1,25,530815,1376028284","m":"干干干干干干干干干干干干干干干干"},{"c":"69.165,16737996,1,25,530815,1376028286","m":"干干干干干干干干干干干干干干干干干干干干干干干"},{"c":"71.557,16737996,1,25,530815,1376028288","m":"干干干干干干干干干干干干干干干干干干干干干干"},{"c":"73.735,16737996,1,25,530815,1376028291","m":"干干干干干干干干干干干干干干干干干干干干干"},{"c":"76.557,16737996,1,25,530815,1376028293","m":"干干干干干干干干干干干干干干干干干干干干"},{"c":"29.092,16711680,1,37,614672,1376028731","m":"16个基友"},{"c":"22.594,16777215,1,25,309584,1376030511","m":"耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶"},{"c":"17.225,16777215,5,25,44bk3071973485,1376031371","m":"耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶"},{"c":"3.602,16777215,1,25,13ek3664566159,1376031421","m":"。。。。。。。。"},{"c":"60.201,16777215,5,25,44bk3071973485,1376031433","m":"开撸"},{"c":"33.999,16777215,1,25,13ek3664566159,1376031451","m":"。。。。。。。。。。。。。。。。。。。。。。。。。。。。"},{"c":"81.941,16777215,1,25,27ek1017187980,1376032222","m":"诱惑"},{"c":"5.011,16777215,1,25,139k2015525676,1376032988","m":"打卡- -!"},{"c":"44.246,65535,1,37,455173,1376033209","m":"啊"},{"c":"36.058,16777215,1,25,377k1911910901,1376033512","m":"2013年8月9日15:31:52"},{"c":"21.127,16777215,1,25,104k1947652358,1376033802","m":"AHAHHAHAHA"},{"c":"2.284,16777215,1,25,194k2032039251,1376037377","m":"这么有来首页了"},{"c":"9.476,16776960,1,25,3f6k3070804403,1376042411","m":"打卡"},{"c":"0,16777215,1,25,325344,1376043241","m":"哈哈哈 又上来了 打卡 2013年8月9日 18:12:36"},{"c":"44.144,16777215,1,25,25fk3061655078,1376043624","m":"收藏的什么心态收藏的什么心态收藏的什么心态收藏的什么心态收藏的什么心态"},{"c":"10.301,16777215,1,25,1cak241839552,1376044031","m":"打卡"},{"c":"50.969,16777215,1,25,318k1904807183,1376045391","m":"。。。"},{"c":"73.398,16777215,1,25,318k1904807183,1376045413","m":"好大的屌!"},{"c":"26.087,16711680,1,25,614708,1376045441","m":".."},{"c":"31.691,16777215,1,25,4d4k3030298853,1376046937","m":"2013年马薇留"},{"c":"6.405,16777215,1,25,619757,1376048357","m":"重口味"},{"c":"24.329,16777215,1,25,619757,1376048374","m":"打卡"},{"c":"67.762,16777215,1,25,258k3730122316,1376050181","m":"0000000000000000000000000000000000000000000000"},{"c":"73.064,16777215,1,25,258k3730122316,1376050186","m":".0000000000000000000000000"},{"c":"78.785,16777215,1,25,258k3730122316,1376050192","m":"00000000000000000000000000000000000"},{"c":"87.771,16777215,1,25,258k3730122316,1376050203","m":"0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"},{"c":"1.437,13421772,1,25,611275,1376050973","m":"我看了这个就想走。。"},{"c":"15.69,13421772,1,37,611275,1376051015","m":"耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶"},{"c":"15.69,13421772,1,37,611275,1376051017","m":"耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶"},{"c":"15.69,13421772,1,37,611275,1376051019","m":"耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶"},{"c":"15.69,13421772,1,37,611275,1376051022","m":"耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶"},{"c":"15.69,13421772,1,25,611275,1376051026","m":"耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶"},{"c":"15.69,13421772,1,16,611275,1376051030","m":"耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶"},{"c":"67.909,3381759,1,37,611275,1376051114","m":"我不知道我想干什么。可是我就是想说话。。"},{"c":"79.327,3381759,1,37,611275,1376051135","m":"不觉得。。。杨坤么。。"},{"c":"7.009,13369344,1,25,458834,1376053218","m":".................."},{"c":"27.069,13369344,1,25,458834,1376053280","m":"草"},{"c":"34.131,16777215,1,25,367k1035115771,1376053822","m":"耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶"},{"c":"13.785,16777215,1,25,330k1885029985,1376056009","m":"每日打卡"},{"c":"21.79,16777215,1,25,486050,1376056370","m":"......................."},{"c":"19.539,16711731,1,25,12bk2059537792,1376056446","m":"瞬间被刷屏了……"},{"c":"70.195,16711731,1,25,12bk2059537792,1376056498","m":"我竟然看完了……"},{"c":"12.902,16777215,1,25,393225,1376056911","m":"主页 \u003e 生活娱乐 / 暖被窝一次一千円节假日半价 / 发布于 2011年 4月28日(星期四) 7时24分 / 播放:408,415 评论:2,512 收藏:1,721 /"},{"c":"48.342,16777215,1,25,41ek3701560160,1376057555","m":"0 0"},{"c":"59.019,16777215,1,25,41ek3701560160,1376057566","m":"收藏什么心态"},{"c":"41.194,10027008,1,25,419k1007188745,1376057962","m":"基佬在此"},{"c":"69.806,10027008,1,25,419k1007188745,1376057991","m":"曹操草草草草草草草草草草草草草草草草草草草草草草草草草草草草草草草草"},{"c":"28.757,16777215,1,25,349k1965803175,1376058287","m":"是谁"},{"c":"0,16751001,4,25,617145,1376059073","m":"我操,史前巨坟,考古队赛高"},{"c":"49.29,16777215,1,25,546869,1376059201","m":"同步率爆表!"},{"c":"2.347,16711680,4,37,134k1020459866,1376060215","m":"杨坤即视感!爆表!"},{"c":"18.808,3394560,1,25,383341,1376061683","m":"顶起来顶起来"},{"c":"32.758,16777215,1,25,401332,1376062619","m":"..............................................."},{"c":"79.203,16777215,1,25,600050,1376063136","m":"1728个收藏是什么情况?"},{"c":"7.577,16711680,1,25,591937,1376066729","m":"打卡"},{"c":"14.959,16777215,1,25,312k2005722785,1376068554","m":"耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶"},{"c":"27.52,16777215,1,25,620468,1376071363","m":"wocao"},{"c":"74.958,16711935,1,25,32ek3723106730,1376073723","m":"毫无节操"},{"c":"14.71,16777215,1,25,244k3703207273,1376075750","m":"耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶"},{"c":"19.997,16777215,1,25,244k3703207273,1376075756","m":"耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶"},{"c":"69.767,16777215,1,25,244k3703207273,1376075786","m":"耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶"},{"c":"20.485,16776960,1,25,394k2021656327,1376097000","m":"什么情况?"},{"c":"82.358,16776960,1,25,394k2021656327,1376097055","m":"石更了"},{"c":"15.177,16777215,1,25,537000,1376098220","m":"耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶"},{"c":"15.402,16777215,1,25,537000,1376098244","m":"耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶"},{"c":"33.161,16777215,1,25,4d0k3059467444,1376098921","m":"我日"},{"c":"0.655,6723840,1,25,24ak1919230024,1376099553","m":"打卡"},{"c":"32.027,65280,1,25,566893,1376102189","m":"主页 \u003e 生活娱乐 / 暖被窝一次一千円节假日半价 / 发布于 2011年 4月28日(星期四) 7时24分 / "},{"c":"11.472,16777215,1,25,307884,1376104108","m":"每日打开"},{"c":"12.86,16777215,1,25,382659,1376104392","m":"++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++"},{"c":"15.413,16777215,1,25,382659,1376104409","m":"耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶"},{"c":"15.413,16777215,1,25,382659,1376104415","m":"耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶"},{"c":"15.413,16777215,1,25,382659,1376104422","m":"耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶"},{"c":"15.413,16777215,1,25,382659,1376104428","m":"耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶"},{"c":"15.413,16777215,1,25,382659,1376104435","m":"耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶"},{"c":"29.998,13408665,1,25,439024,1376104583","m":"打卡"},{"c":"29.078,16777215,1,25,245951,1376105072","m":"打卡..."},{"c":"16.893,16777215,1,25,611704,1376108149","m":"走起来~也噩噩噩噩噩噩噩噩噩噩"},{"c":"15.124,16777215,1,25,252k1933384533,1376117070","m":"耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶"},{"c":"25.018,16777215,1,25,338k1939335882,1376119947","m":"耶"},{"c":"0.482,16777215,1,25,566783,1376120825","m":"\u003d \u003d"},{"c":"34.632,16711680,1,25,289013,1376120976","m":"可耻的银恶灵"},{"c":"4.284,16777215,1,25,566697,1376121670","m":"神甩头……"},{"c":"16.939,13369344,4,25,48ck1942933904,1376124247","m":"报复社会搞起啊"},{"c":"12.574,16777215,1,25,499k3662479322,1376126734","m":"。。。。。"},{"c":"77.721,16777215,1,25,499k3662479322,1376126799","m":"我居然看完了+1..."},{"c":"66.386,6737151,1,25,621354,1376127623","m":"飞 "},{"c":"33.26,16777215,1,25,621447,1376131168","m":"日常打卡系列"},{"c":"13.877,16777215,1,25,4b1k3662454931,1376131296","m":"2013年8月10日 18:40:29"},{"c":"8.711,16777215,1,25,127k2104708180,1376131476","m":"..."},{"c":"13.243,16777215,1,25,10fk1034146970,1376131479","m":"来打卡。。。。。。。。。。"},{"c":"13.691,16777215,1,25,237582,1376131564","m":"啊♂"},{"c":"84.488,16777215,1,25,237582,1376131657","m":"这健美的肌肉,王の谜微笑"},{"c":"18.155,16777215,1,25,4d2k1018810962,1376133311","m":"顶上去报复社会"},{"c":"55.547,16776960,4,25,418k1996750992,1376133796","m":"小伙伴好强悍"},{"c":"14.218,13434624,1,25,576058,1376134995","m":"wocao "},{"c":"26.499,13434624,1,25,576058,1376135008","m":"3333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333"},{"c":"39.818,13434624,1,25,576058,1376135021","m":"3333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333"},{"c":"52.38,13434624,1,25,576058,1376135033","m":"3333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333"},{"c":"35.837,16777215,1,25,2c9k2078827628,1376135639","m":"顶上去报复社会"},{"c":"15.832,16777215,1,25,186k3074211670,1376137394","m":"杨坤 卧槽"},{"c":"38.655,16777215,1,25,186k3074211670,1376137417","m":"啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊"},{"c":"51.2,16777215,1,25,186k3074211670,1376137430","m":"科比"},{"c":"37.391,16777215,1,25,608896,1376137620","m":"挖坟老坑了!!- -"},{"c":"20.606,16777215,1,25,325344,1376139878","m":"打卡 2013年8月10日 21:03:12 "},{"c":"31.826,13369344,1,25,3b9k1947407437,1376139894","m":"啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊"},{"c":"23.769,16777215,1,25,249393,1376142115","m":"耶耶耶"},{"c":"6.929,13434777,1,25,404k2086353330,1376145403","m":"打卡吧……"},{"c":"76.145,16777215,1,25,458k2034184434,1376146315","m":"好屌屌屌屌屌屌屌屌屌屌屌屌屌屌"},{"c":"87.886,16777215,1,25,317k3729928182,1376147520","m":"有木有感觉像罗纳尔多"},{"c":"46.027,16777215,1,25,1cek2105502321,1376149328","m":"410000"},{"c":"66.967,13369395,5,25,489k3661677826,1376150846","m":"前来打卡"},{"c":"12.447,16777215,1,25,37ck1785980621,1376179903","m":"- -2013.8.11"},{"c":"48.757,16777215,1,25,37ck1785980621,1376179940","m":"硬了怎么办"},{"c":"0.297,6749952,5,25,516261,1376181869","m":"欢迎观看《肌肉进行曲》"},{"c":"14.965,16777215,1,25,44bk3071973485,1376182825","m":"耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶"},{"c":"12.347,16776960,4,37,507878,1376183526","m":"AV画质"},{"c":"44.318,16776960,4,37,507878,1376183560","m":"1765个收藏心态"},{"c":"15.332,16777215,1,25,1d4k236011651,1376187564","m":"罗纳尔多"},{"c":"23.92,16777215,1,25,1dbk1786742976,1376190305","m":"............."},{"c":"87.917,16777215,1,25,1dbk1786742976,1376190407","m":"迷の微笑"},{"c":"47.296,16777215,1,25,2b5k3730060046,1376191845","m":"广西频道发来贺电"},{"c":"47.032,16777215,1,25,1b7k2095450225,1376193392","m":"我要吐了"},{"c":"77.956,6684672,5,25,1b7k2095450225,1376193474","m":"?????????????????????????????????????????????"},{"c":"14.184,16777215,1,25,320k2883429025,1376193568","m":"YEYEYEYEYEYEYEYEYEYEYEYEYEYEYEYEYEYEYEYEYEYEYEYEYEYEYEYEYEYEYEYEYEYEYEYEYEYEYEYEYEYEYEYEYEYE"},{"c":"77.956,6684672,5,25,1b7k2095450225,1376193581","m":"?????????欢迎使用护眼弹幕??????????"},{"c":"77.956,6684672,5,25,1b7k2095450225,1376193596","m":"??????????????????????????????????????"},{"c":"16.222,13395609,1,25,320k2883429025,1376193605","m":"耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶"},{"c":"27.023,16777215,1,25,529412,1376193841","m":"节操掉了一地"},{"c":"1.652,13434624,1,25,595888,1376197519","m":"看过不说话"},{"c":"8.227,16777215,1,25,622565,1376199281","m":"打卡"},{"c":"14.5,3394815,1,25,506067,1376202751","m":"打卡"},{"c":"18.145,16777215,1,25,584461,1376203682","m":"每日打卡!!!!"},{"c":"3.565,16777215,1,25,622662,1376203695","m":"..."},{"c":"12.625,16777215,1,25,39ak977057938,1376205596","m":"哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇"},{"c":"73.017,16777215,1,25,592163,1376206800","m":"光滑 没毛!!!!"},{"c":"73.017,10092441,1,25,592163,1376206815","m":"没毛!!"},{"c":"6.05,16777215,1,25,37ck1785980621,1376206948","m":"2013.8.11"},{"c":"58.484,16711680,1,37,2d8k1946238324,1376208217","m":"他要自摸了。。。。。。。。。受不鸟了。。。。"},{"c":"5.201,16777215,1,25,250k409716719,1376208782","m":"打开"},{"c":"18.939,16777215,1,25,206k1911775910,1376210523","m":"呵呵"},{"c":"52.488,16777215,1,25,206k1911775910,1376210557","m":"刷屏+1"},{"c":"67.016,16777215,1,25,206k1911775910,1376210571","m":"法克"},{"c":"81.281,16777215,1,25,3f4k2073541231,1376210956","m":"啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊"},{"c":"80.625,16777215,1,25,100k3030428551,1376211394","m":"打证白"},{"c":"31.416,16777215,1,25,614007,1376212423","m":"什么东西"},{"c":"14.009,16777215,1,25,44bk3071973485,1376212845","m":"耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶"},{"c":"27.607,16777215,1,25,572231,1376213936","m":"日常打卡"},{"c":"16.912,16777215,1,25,605743,1376218302","m":"耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶"},{"c":"9.1,16777215,1,25,605743,1376219700","m":"看一遍笑一次。。"},{"c":"16.279,16777215,1,25,605743,1376219708","m":"耶耶耶耶耶"},{"c":"15.025,16777215,1,25,2a0k1010239990,1376219790","m":"........................................................................"},{"c":"4.305,16777215,1,25,11ak1894547491,1376220450","m":"..."},{"c":"10.339,16777215,1,25,482k2034062684,1376221602","m":"d打卡"},{"c":"20.025,16777215,1,25,482k2034062684,1376221611","m":"夜夜夜夜"},{"c":"30.814,16777215,1,25,498k2102044667,1376224344","m":"耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶爷爷爷爷夜夜夜yee5"},{"c":"58.483,16777215,1,25,498k2102044667,1376224371","m":"擦擦擦擦擦擦擦擦擦擦擦擦擦擦擦擦擦擦擦擦擦擦擦擦擦擦擦擦擦擦擦"},{"c":"12.275,16777215,1,25,23bk3733406631,1376224558","m":"打卡"},{"c":"9.587,16711782,1,25,367k2057138470,1376225672","m":"表情超销魂!"},{"c":"13.88,16711680,1,25,334k3070638933,1376226617","m":" "},{"c":"18.243,16777215,1,25,375895,1376228032","m":"我也来打个卡吧"},{"c":"35.603,16777215,1,25,309177,1376228477","m":"夜夜夜夜夜夜夜夜夜夜夜夜夜夜夜夜夜夜夜夜夜夜夜夜夜夜夜夜夜夜夜夜夜夜夜夜夜夜夜夜夜夜夜夜夜夜夜夜夜夜夜夜夜夜夜夜夜夜夜夜夜夜夜夜夜夜夜夜夜夜夜夜夜夜夜夜夜夜夜夜夜夜夜夜夜夜夜夜夜夜夜夜夜夜夜夜夜夜夜夜"},{"c":"24.416,16777215,1,25,158576,1376228832","m":"无法直视"},{"c":"13.837,13382502,1,25,620591,1376231904","m":"打卡"},{"c":"25.387,13382502,1,25,620591,1376231916","m":"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"},{"c":"53.762,13382502,1,25,620591,1376231944","m":"耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶"},{"c":"73.111,13382502,4,25,620591,1376231964","m":"耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶"},{"c":"84.769,13382502,1,25,620591,1376231975","m":"耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶"},{"c":"22.134,16777215,1,25,623376,1376232266","m":"......................"},{"c":"55.778,16777215,1,25,597552,1376232792","m":"神弹幕 不可否认 我是看弹幕的"},{"c":"8.139,16777215,1,25,130k2876188882,1376234404","m":"a"},{"c":"15.353,16777215,1,25,121k3730778254,1376234861","m":"耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶"},{"c":"14.659,6684825,1,25,189k2073480635,1376239744","m":"夜夜夜夜夜夜夜夜夜夜夜夜"},{"c":"23.454,16724736,1,25,1b3k3670962492,1376266101","m":"2013.8.12"},{"c":"14.862,16724736,1,25,1b3k3670962492,1376266182","m":"耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶"},{"c":"22.954,16724736,1,25,1b3k3670962492,1376266190","m":"耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶"},{"c":"30.16,16776960,1,25,180k249509149,1376275642","m":"液"},{"c":"6.397,16777215,1,25,624035,1376276334","m":"打卡"},{"c":"30.983,16777215,1,25,4a5k1946234471,1376279150","m":"软掉了 T.T..."},{"c":"54.218,16777215,1,25,4a5k1946234471,1376279174","m":"竟然软掉了 ,,,,"},{"c":"40.096,16777215,1,25,1e2k3029168501,1376279250","m":"我是来听BGM的"},{"c":"30.241,16777215,1,25,454k463273829,1376280162","m":"打卡"},{"c":"48.883,16777215,1,25,393225,1376281142","m":"今日打卡2013年8月12日 12:19:05"},{"c":"45.148,13369599,4,37,1b3k1033710953,1376282278","m":"2013.8.12"},{"c":"57.568,16777215,1,25,44bk1851130326,1376282652","m":"真的是香蕉吗"},{"c":"17.456,16777215,1,25,2c3k3702014318,1376283657","m":"\u003d \u003d"},{"c":"10.043,6749952,1,25,4d8k3722613906,1376285088","m":"打卡"},{"c":"81.256,6749952,1,25,4d8k3722613906,1376285159","m":"我艹!不能直视啊 "},{"c":"77.976,16777215,1,25,532917,1376287835","m":"1799收藏"},{"c":"0.632,16777215,1,25,624425,1376289715","m":"打卡"},{"c":"24.667,16777215,1,25,622912,1376291639","m":"2013-8-12 15:13:58"},{"c":"0,16777215,1,25,567743,1376294017","m":"打卡了绅士们..."},{"c":"21.687,13408512,1,25,20bk986871394,1376294378","m":"耶耶耶"},{"c":"15.04,13408512,1,25,20bk986871394,1376294480","m":"耶耶耶耶耶"},{"c":"18.614,16777215,1,25,585664,1376297871","m":"耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶"},{"c":"14.819,16711680,1,25,591937,1376297948","m":"打卡!!!!!!!!!"},{"c":"16.468,16711680,1,25,591937,1376298006","m":"耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶"},{"c":"17.037,16777215,1,25,566697,1376300118","m":"耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶夜夜2"},{"c":"14.844,16777215,1,25,566697,1376300171","m":"耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶"},{"c":"14.789,16777215,1,25,20ek2007451346,1376301534","m":"耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶"},{"c":"13.681,16777215,1,25,559740,1376302153","m":"yoo"},{"c":"14.361,16777215,1,25,597374,1376304489","m":"打卡"},{"c":"3.66,16777215,1,25,266k3723106730,1376308867","m":"打卡"},{"c":"30.341,16711731,4,37,266k3723106730,1376308894","m":"继续丧心病狂"},{"c":"10.565,16777215,1,25,3c6k3757386694,1376309156","m":"打卡"},{"c":"16.416,16777215,1,25,4d2k1018810962,1376309537","m":"耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶"},{"c":"12.315,16777215,1,25,4d2k1018810962,1376309718","m":"看了7遍了。。"},{"c":"45.952,16777215,1,25,271k1867408839,1376310116","m":"顶上去报复社会"},{"c":"59.282,16777215,1,25,315k3396199020,1376310939","m":"我擦啊啊 啊啊啊啊啊啊啊"},{"c":"24.622,16777215,1,25,248k1911799324,1376311419","m":"打卡+1"},{"c":"41.684,16777215,1,25,248k1911799324,1376311436","m":"每日必看- -"},{"c":"80.693,16777215,1,25,38ak1960930797,1376312094","m":"..."},{"c":"25.238,16777215,1,25,1b5k3701977691,1376318290","m":"................"},{"c":"13.113,16777215,1,25,172661,1376318903","m":"2013.8.12"},{"c":"51.958,16711680,1,25,387645,1376321267","m":"顶上去报复社会"},{"c":"19.408,16777215,1,25,178252,1376325904","m":"金刚如来!"},{"c":"13.351,16777215,1,25,166k3662278790,1376328310","m":"求BGM"},{"c":"52.529,16777215,1,25,166k3662278790,1376328349","m":"文化接触太给力了"},{"c":"46.894,16777215,1,25,258k3658903074,1376342389","m":"丧心病狂!"},{"c":"23.442,16777215,1,25,625727,1376342676","m":"打卡啊"},{"c":"11.096,16777215,1,25,385k2006107404,1376352828","m":"前来打卡"},{"c":"19.957,16777215,1,25,313k2074454599,1376353232","m":"弹幕好多啊"},{"c":"76.404,16777215,1,25,522845,1376353426","m":" - -"},{"c":"14.544,16777215,1,25,34fk245272954,1376357240","m":"耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶"},{"c":"16.276,16777215,1,25,34fk245272954,1376357245","m":"耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶"},{"c":"16.276,16777215,1,25,34fk245272954,1376357250","m":"耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶"},{"c":"9.564,16777215,1,25,572231,1376360217","m":"每日打卡"},{"c":"14.666,3407616,1,25,576285,1376361161","m":"耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶"},{"c":"14.666,3407616,1,25,576285,1376361165","m":"耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶"},{"c":"14.666,3407616,1,25,576285,1376361168","m":"耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶"},{"c":"14.666,3407616,1,25,576285,1376361171","m":"耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶"},{"c":"14.666,3407616,4,25,576285,1376361178","m":"耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶"},{"c":"14.666,3407616,4,25,576285,1376361181","m":"耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶"},{"c":"14.666,3407616,4,25,576285,1376361183","m":"耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶"},{"c":"14.666,3407616,1,25,576285,1376361192","m":"耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶"},{"c":"14.666,3407616,1,25,576285,1376361196","m":"耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶"},{"c":"14.666,3407616,1,25,576285,1376361198","m":"耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶"},{"c":"14.666,3407616,1,25,576285,1376361200","m":"耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶"},{"c":"14.666,3407616,1,25,576285,1376361202","m":"耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶"},{"c":"14.666,3407616,1,25,576285,1376361204","m":"耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶"},{"c":"14.666,3407616,1,25,576285,1376361206","m":"耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶"},{"c":"14.666,3407616,1,25,576285,1376361210","m":"耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶"},{"c":"14.666,3407616,1,25,576285,1376361213","m":"耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶"},{"c":"14.666,3407616,1,25,576285,1376361218","m":"耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶"},{"c":"5.177,26316,4,25,267k2090994000,1376361508","m":"炒饭?"},{"c":"87.933,16777215,1,25,1a7k3069283466,1376361779","m":"2013年8月13"},{"c":"27.815,16777215,1,25,171405,1376362569","m":"耶耶!!!!!!!!!!!耶耶!!!!!!!!!!!耶耶!!!!!!!!!!!耶耶!!!!!!!!!!!耶耶!!!!!!!!!!!耶耶!!!!!!!!!!!耶耶!!!!!!!!!!!耶耶!!!!!!!"},{"c":"32.579,16777215,1,25,171405,1376362574","m":"耶耶!!!!!!!!!!!耶耶!!!!!!!!!!!耶耶!!!!!!!!!!!耶耶!!!!!!!!!!!耶耶!!!!!!!!!!!耶耶!!!!!!!!!!!"},{"c":"7.32,16777215,1,25,119k1857965230,1376365425","m":"耶耶耶耶~"},{"c":"15.537,16777215,1,25,1c7k2101364304,1376365766","m":"没弹幕"},{"c":"45.25,10027161,1,25,387k453943713,1376367231","m":"杨坤,"},{"c":"7.229,16776960,1,25,606859,1376370237","m":"打卡。。"},{"c":"0,6710886,1,25,582628,1376370715","m":"wa"},{"c":"5.823,16777215,1,25,352k1017434011,1376371231","m":"......................."},{"c":"3.909,16777215,1,25,417219,1376371271","m":"打卡。。。。。。"},{"c":"17.374,16777215,1,25,566697,1376373973","m":"耶耶耶耶耶耶耶耶耶"},{"c":"14.054,16777215,1,37,566697,1376374027","m":"are you ready"},{"c":"13.541,16711680,5,37,566697,1376374083","m":"Are you ready"},{"c":"17.659,3381759,1,25,424199,1376374824","m":"耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶"},{"c":"33.684,16777011,1,25,406k3029170287,1376377099","m":"耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶"},{"c":"13.417,16777215,1,25,532321,1376377112","m":"2013-08-13 14:58:38 打卡"},{"c":"16.714,13158,1,37,532321,1376377128","m":"耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶"},{"c":"20.598,13158,1,37,532321,1376377132","m":"耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶"},{"c":"22.68,13158,1,37,532321,1376377134","m":"耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶"},{"c":"76.478,16777011,4,25,406k3029170287,1376377142","m":"耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶"},{"c":"87.215,16777011,4,25,406k3029170287,1376377153","m":"500个基友不说话"},{"c":"19.279,13369344,5,37,532321,1376377169","m":"2013-08-13 14:59:35 每日打卡"},{"c":"29.294,16777215,1,25,626391,1376377489","m":"我看了3次了"},{"c":"79.901,16777215,1,25,626391,1376377540","m":"耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶"},{"c":"59.807,16777215,1,25,4dck1035737753,1376377654","m":"杨坤有木有?"},{"c":"11.296,16777215,1,25,4dck1035737753,1376377695","m":"杨坤杨坤杨坤"},{"c":"39.395,16777215,1,25,4dck1035737753,1376377708","m":"杨坤"},{"c":"63.041,16777215,1,25,532917,1376377930","m":"主页 \u003e 生活娱乐 / 暖被窝一次一千円节假日半价 / 发布于 2011年 4月28日(星期四) 7时24分 / 播放:415,449 评论:2,533 收藏:1,824 /"},{"c":"25.6,16777215,1,25,145k3395750786,1376378270","m":"打卡日常!"},{"c":"24.629,6750207,1,25,478k3072636344,1376385749","m":"弄得一手好洛阳铲!"},{"c":"64.338,6750207,1,37,478k3072636344,1376385789","m":"大香蕉!"},{"c":"76.837,6750207,1,37,478k3072636344,1376385802","m":"有耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶"},{"c":"9.913,16711680,1,25,461k2032076344,1376387128","m":"不是这首歌捏"},{"c":"41.313,16711680,1,25,461k2032076344,1376387160","m":"怎么可能是炒饭呢 我不认识他……\u003d。\u003d"},{"c":"66.44,16777215,1,25,605539,1376392369","m":"1826个收藏什么心态"},{"c":"5.782,16777215,1,25,360088,1376396483","m":"摇起来"},{"c":"26.991,16777215,1,25,21ak1033502638,1376397265","m":"耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶"},{"c":"16.38,16777215,1,25,21ak1033502638,1376397277","m":"耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶v耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶"},{"c":"44.459,16777215,1,25,3bdk2947511981,1376398050","m":"耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶"},{"c":"55.836,16777215,1,25,3bdk2947511981,1376398062","m":"小丁丁"},{"c":"24.275,3407616,1,25,597033,1376398577","m":"耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶"},{"c":"15.221,16711680,1,25,120k3085204837,1376398889","m":"......"},{"c":"14.751,16711680,1,25,120k3085204837,1376398919","m":"耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶"},{"c":"19.935,16711680,1,25,120k3085204837,1376398924","m":"耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶"},{"c":"33.583,16777215,1,25,441775,1376402422","m":"打卡不解释"},{"c":"18.175,16777215,1,25,600087,1376402531","m":"耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶"},{"c":"14.615,16777215,5,25,585664,1376402819","m":"Are you ready?"},{"c":"10.981,16777215,1,25,400k3061677543,1376402907","m":"打卡"},{"c":"19.41,16777215,1,25,29ck1900353397,1376403241","m":"................."},{"c":"40.775,16777215,1,25,223k244518479,1376406469","m":"看不到啊看不到啊看不到啊看不到啊看不到啊看不到啊看不到啊看不到啊看不到啊看不到啊看不到啊看不到啊看不到啊"},{"c":"17.361,16777215,1,25,3b3k3659281694,1376407201","m":"2013年8月13日 23:19:57"},{"c":"34.2,16777215,1,25,599621,1376409181","m":"我又来了"},{"c":"0,16711680,1,25,611275,1376410430","m":"这是一个让大家都变基佬的阴谋。"},{"c":"47.866,16711680,1,25,611275,1376410484","m":"我的眼睛!!!"},{"c":"55.535,16711680,4,37,611275,1376410502","m":"我的眼睛!"},{"c":"84.865,65535,1,25,3a5k1781617181,1376411413","m":"干干干干干干干干干干干干干干干干干干干干干干干干干干干干干干干干干干干干干干干干干干干干干干干干干干干干干干干干干干干干干干干干干干干干干干干干干干干干干干干干干"},{"c":"12.776,16777215,1,25,276k1981480729,1376412042","m":"。。。。"},{"c":"47.856,16711680,1,25,4cek1867427908,1376414470","m":"耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶"},{"c":"78.741,16711680,1,37,4cek1867427908,1376414501","m":"耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶"},{"c":"70.281,16777215,1,25,40fk2948117381,1376427964","m":"无法直视 丧心病狂"},{"c":"17.25,16777215,1,25,20ek3083468584,1376428049","m":"打卡8.14早上"},{"c":"17.965,16777215,1,25,20ek3083468584,1376428081","m":"耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶耶"},{"c":"36.487,16777215,1,25,254049,1376429548","m":"求bgm"},{"c":"43.589,16777215,1,25,177k3662843066,1376435280","m":"丧心病狂的七夕"},{"c":"15.152,16777215,1,25,453k3723125416,1376444152","m":"打卡"},{"c":"65.262,16777215,1,25,453k3723125416,1376444202","m":"卧槽、"},{"c":"16.507,16777215,1,25,166316,1376446088","m":"美国大雕"},{"c":"17.339,13369344,1,25,532321,1376453125","m":"2013年8月14日 12:05:26 打卡"},{"c":"48.351,6750003,1,25,615328,1376453285","m":"baofushehui!!!!!!!!!!!"},{"c":"58.802,16777215,1,25,3d0k2095941037,1376456170","m":"⑨个小伙你好"},{"c":"68.467,16777215,1,25,3d0k2095941037,1376456180","m":"曹。。。。"},{"c":"18.832,16711680,1,25,385421,1376457625","m":"8月14日赵志斌打卡"},{"c":"0.493,16711680,4,25,385421,1376457661","m":"8月14日赵志斌打卡广州北大附中贺电"},{"c":"0,16777215,1,25,403k3721738134,1376458877","m":"2013年8月14日13:42"},{"c":"5.345,16777215,1,25,19ak2000570677,1376459956","m":"打卡"},{"c":"4.087,16777215,1,25,580660,1376461730","m":"兄贵--------------------------------------------------------------------------------------------------"},{"c":"12.885,16777215,1,25,149k1912070066,1376466041","m":"......................"},{"c":"21.97,16777215,1,25,149k1912070066,1376466070","m":"表情帝!!!!!!!!!!!!!!!!!!"},{"c":"5.968,13408512,1,25,4d9k3736983214,1376466747","m":"日常打卡"},{"c":"63.916,13408512,1,25,4d9k3736983214,1376466805","m":" 收藏:1,842 "},{"c":"38.359,16777215,1,25,18ck3663086991,1376468188","m":".."},{"c":"10.45,16777215,1,25,554498,1376469294","m":"k "},{"c":"14.564,16777215,1,25,146k3740635017,1376470286","m":"```````````````````````"},{"c":"77.734,16777215,1,25,376k1900079524,1376471392","m":"一样呀呀呀呀呀呀呀呀呀呀呀呀呀呀呀呀呀呀呀呀呀呀呀呀呀呀呀呀呀呀"}] ================================================ FILE: app/src/main/assets/online.xml ================================================ 1.1.0 default stream 001 002 003 004 005 006 007 008 009 010 011 012 013 014 214 216 072 073 366 370 018 027 036 037 038 039 042 043 044 045 046 047 048 049 050 051 052 053 054 055 056 057 058 059 061 064 170 171 172 174 286 016 017 068 070 075 107 159 160 161 162 163 164 231 294 203 204 208 209 212 213 201 277 005 015 094 126 140 322 366 367 368 277 369 018 022 112 113 114 027 108 111 126 127 128 130 131 132 133 372 373 240 320 368 036 085 086 087 088 089 090 094 056 115 116 117 118 119 202 337 338 339 340 341 342 040 134 140 141 225 064 015 060 061 062 065 066 123 124 165 191 192 193 194 195 196 197 198 199 200 234 235 334 335 369 055 295 296 297 298 299 300 301 057 323 324 325 326 327 328 329 059 302 303 304 305 306 307 308 170 226 345 346 347 348 349 350 286 042 322 332 047 310 311 312 063 352 353 354 355 356 171 045 187 236 ================================================ FILE: app/src/main/java/com/cjj/bb/activity/ABPlayerApplication.java ================================================ package com.cjj.bb.activity; import android.app.Application; import android.content.Context; import android.os.Environment; import com.cjj.bb.view.FileUtils; public class ABPlayerApplication extends Application{ private static ABPlayerApplication mApplication; /** OPlayer SD卡缓存路径 */ public static final String OPLAYER_CACHE_BASE = Environment.getExternalStorageDirectory() + "/oplayer"; /** 视频截图缓冲路径 */ public static final String OPLAYER_VIDEO_THUMB = OPLAYER_CACHE_BASE + "/thumb/"; /** 首次扫描 */ public static final String PREF_KEY_FIRST = "application_first"; @Override public void onCreate() { super.onCreate(); mApplication = this; init(); } private void init() { //创建缓存目录 FileUtils.createIfNoExists(OPLAYER_CACHE_BASE); FileUtils.createIfNoExists(OPLAYER_VIDEO_THUMB); } public static ABPlayerApplication getApplication() { return mApplication; } public static Context getContext() { return mApplication; } /** 销毁 */ public void destory() { mApplication = null; } } ================================================ FILE: app/src/main/java/com/cjj/bb/activity/BiliVideoViewActivity.java ================================================ package com.cjj.bb.activity; /* * Copyright (C) 2012 YIXIA.COM * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import io.vov.vitamio.utils.FileUtils; import io.vov.vitamio.utils.Log; import io.vov.vitamio.widget.OutlineTextView; import java.io.ByteArrayInputStream; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.nio.ByteBuffer; import java.text.SimpleDateFormat; import java.util.Date; import java.util.concurrent.atomic.AtomicBoolean; import java.util.zip.DataFormatException; import org.json.JSONException; import org.json.JSONObject; import org.jsoup.Jsoup; import org.jsoup.helper.HttpConnection.Response; import master.flame.danmaku.controller.IDanmakuView; import master.flame.danmaku.danmaku.loader.ILoader; import master.flame.danmaku.danmaku.loader.IllegalDataException; import master.flame.danmaku.danmaku.loader.android.DanmakuLoaderFactory; import master.flame.danmaku.danmaku.model.android.DanmakuGlobalConfig; import master.flame.danmaku.danmaku.model.android.Danmakus; import master.flame.danmaku.danmaku.parser.BaseDanmakuParser; import master.flame.danmaku.danmaku.parser.IDataSource; import master.flame.danmaku.danmaku.parser.android.BiliDanmukuParser; import android.annotation.SuppressLint; import android.app.Activity; import android.app.KeyguardManager; import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.ServiceConnection; import android.content.res.Configuration; import android.graphics.Bitmap; import android.graphics.drawable.AnimationDrawable; import android.media.AudioManager; import android.net.Uri; import android.os.AsyncTask; import android.os.BatteryManager; import android.os.Build; import android.os.Bundle; import android.os.Environment; import android.os.Handler; import android.os.IBinder; import android.os.Message; import android.text.TextUtils; import android.view.KeyEvent; import android.view.SurfaceHolder; import android.view.View; import android.view.ViewGroup.MarginLayoutParams; import android.view.WindowManager; import android.widget.ImageView; import android.widget.TextView; import android.widget.Toast; import com.cjj.bb.R; import com.cjj.bb.utils.CompressionTools; import com.cjj.bb.utils.DeviceUtils; import com.cjj.bb.utils.HttpUtil; import com.cjj.bb.utils.ImageUtils; import com.cjj.bb.utils.MediaUtils; import com.cjj.bb.utils.PreferenceUtils; import com.cjj.bb.utils.StringUtils; import com.cjj.bb.utils.ToastUtils; import com.cjj.bb.view.ApplicationUtils; import com.cjj.bb.view.MediaController; import com.cjj.bb.view.PlayerService; import com.cjj.bb.view.VP; import com.cjj.bb.view.VideoView; @SuppressLint("HandlerLeak") public class BiliVideoViewActivity extends Activity implements MediaController.MediaPlayerControl, VideoView.SurfaceCallback { public static final int RESULT_FAILED = -7; private static final IntentFilter USER_PRESENT_FILTER = new IntentFilter( Intent.ACTION_USER_PRESENT); private static final IntentFilter SCREEN_FILTER = new IntentFilter( Intent.ACTION_SCREEN_ON); private static final IntentFilter HEADSET_FILTER = new IntentFilter( Intent.ACTION_HEADSET_PLUG); private static final IntentFilter BATTERY_FILTER = new IntentFilter( Intent.ACTION_BATTERY_CHANGED); private IDanmakuView mDanmakuView;//弹幕控件 private BaseDanmakuParser mParser; private String danmakuPath; private String av; private String page; private boolean isload = false; private boolean isfirst = true; private View startVideo; private TextView startVideoInfo; private String startText = "初始化播放器..."; private ImageView biliAnim; private AnimationDrawable anim; private boolean mCreated = false; private boolean mNeedLock; private String mDisplayName; private String mBatteryLevel; private boolean mFromStart; private int mLoopCount; private boolean mSaveUri; private int mParentId; private float mStartPos; private boolean mEnd = false; private String mSubPath; private boolean mSubShown; private View mViewRoot; private VideoView mVideoView; private View mVideoLoadingLayout; private TextView mVideoLoadingText; private View mSubtitleContainer; private OutlineTextView mSubtitleText; private ImageView mSubtitleImage; private Uri mUri; private ScreenReceiver mScreenReceiver; private HeadsetPlugReceiver mHeadsetPlugReceiver; private UserPresentReceiver mUserPresentReceiver; private BatteryReceiver mBatteryReceiver; private boolean mReceiverRegistered = false; private boolean mHeadsetPlaying = false; private boolean mCloseComplete = false; private boolean mIsHWCodec = false; private MediaController mMediaController; private PlayerService vPlayer; private ServiceConnection vPlayerServiceConnection; // private Animation mLoadingAnimation; // private View mLoadingProgressView; static { SCREEN_FILTER.addAction(Intent.ACTION_SCREEN_OFF); } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); if (!io.vov.vitamio.LibsChecker.checkVitamioLibs(this)) return; vPlayerServiceConnection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { vPlayer = ((PlayerService.LocalBinder) service).getService(); mServiceConnected = true; if (mSurfaceCreated) vPlayerHandler.sendEmptyMessage(OPEN_FILE); } @Override public void onServiceDisconnected(ComponentName name) { vPlayer = null; mServiceConnected = false; } }; setVolumeControlStream(AudioManager.STREAM_MUSIC); parseIntent(getIntent()); loadView(R.layout.activity_video); manageReceivers(); findViews(); mCreated = true; startText = startText + "【完成】\n解析视频地址...【完成】\n全舰弹幕填装..."; startVideoInfo.setText(startText); new VideoViewInitTask().execute(); } private void findViews(){ // DanmakuView mDanmakuView = (IDanmakuView) findViewById(R.id.sv_danmaku); startVideo = (View) findViewById(R.id.video_start); startVideo.setVisibility(View.VISIBLE); startVideoInfo = (TextView) findViewById(R.id.video_start_info); biliAnim = (ImageView) findViewById(R.id.bili_anim); anim = (AnimationDrawable) biliAnim.getBackground(); anim.start(); DanmakuGlobalConfig.DEFAULT.setDanmakuStyle(DanmakuGlobalConfig.DANMAKU_STYLE_STROKEN, 3).setDuplicateMergingEnabled(false); // if (mDanmakuView != null) { // //mParser = createParser(this.getResources().openRawResource(R.raw.comments)); // mParser = createParser(openFileInput(danmakuPath)); // //mParser = createParser(danmakuPath); // mDanmakuView.setCallback(new Callback() { // // @Override // public void updateTimer(DanmakuTimer timer) { // // } // // @Override // public void prepared() { // isload = true; // startPlayer(); // //mDanmakuView.start(); // } // }); // mDanmakuView.prepare(mParser); // // mDanmakuView.showFPS(true); // mDanmakuView.enableDanmakuDrawingCache(true); // ((View) mDanmakuView).setOnClickListener(new View.OnClickListener() { // // @Override // public void onClick(View view) { // mMediaController.setVisibility(View.VISIBLE); // } // }); // } } private BaseDanmakuParser createParser(InputStream stream) { if(stream==null){ return new BaseDanmakuParser() { @Override protected Danmakus parse() { return new Danmakus(); } }; } ILoader loader = DanmakuLoaderFactory.create(DanmakuLoaderFactory.TAG_BILI); try { loader.load(stream); } catch (IllegalDataException e) { e.printStackTrace(); } BaseDanmakuParser parser = new BiliDanmukuParser(); IDataSource dataSource = loader.getDataSource(); parser.load(dataSource); return parser; } private BaseDanmakuParser createParser(String uri) { InputStream stream = null; if(uri==null){ return new BaseDanmakuParser() { @Override protected Danmakus parse() { return new Danmakus(); } }; } try { Response rsp = (Response) Jsoup.connect(uri).execute(); stream = new ByteArrayInputStream(CompressionTools.decompressXML(rsp.bodyAsBytes())); } catch (IOException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } catch (DataFormatException e) { // TODO Auto-generated catch block e.printStackTrace(); } ILoader loader = DanmakuLoaderFactory.create(DanmakuLoaderFactory.TAG_BILI); try { loader.load(stream); } catch (IllegalDataException e) { e.printStackTrace(); } BaseDanmakuParser parser = new BiliDanmukuParser(); IDataSource dataSource = loader.getDataSource(); parser.load(dataSource); return parser; } private void attachMediaController() { if (mMediaController != null) { mNeedLock = mMediaController.isLocked(); mMediaController.release(); } mMediaController = new MediaController(this, mNeedLock); mMediaController.setMediaPlayer(this); mMediaController.setAnchorView(mVideoView.getRootView()); setFileName(); setBatteryLevel(); } @Override public void onStart() { super.onStart(); if (!mCreated) return; // Intent serviceIntent = new Intent(this, PlayerService.class); // serviceIntent.putExtra("isHWCodec", mIsHWCodec); // bindService(serviceIntent, vPlayerServiceConnection, // Context.BIND_AUTO_CREATE); } @Override public void onResume() { super.onResume(); if (!mCreated) return; if (isInitialized()) { KeyguardManager keyguardManager = (KeyguardManager) getSystemService(KEYGUARD_SERVICE); if (!keyguardManager.inKeyguardRestrictedInputMode()) { startPlayer(); } } else { if (mCloseComplete) { reOpen(); } } if (mDanmakuView != null && mDanmakuView.isPrepared() && mDanmakuView.isPaused()) { mDanmakuView.resume(); } } @Override public void onPause() { super.onPause(); if (!mCreated) return; if (isInitialized()) { //savePosition(); if (vPlayer != null && vPlayer.isPlaying()) { stopPlayer(); } } if (mDanmakuView != null && mDanmakuView.isPrepared()) { mDanmakuView.pause(); } } @Override public void onStop() { super.onStop(); if (!mCreated) return; if (isInitialized()) { vPlayer.releaseSurface(); } if (mServiceConnected) { unbindService(vPlayerServiceConnection); mServiceConnected = false; } // if (mDanmakuView != null) { // // dont forget release! // mDanmakuView.release(); // mDanmakuView = null; // } } @Override public void onDestroy() { super.onDestroy(); if (!mCreated) return; manageReceivers(); if (isInitialized() && !vPlayer.isPlaying()) release(); if (mMediaController != null) mMediaController.release(); if (mDanmakuView != null) { // dont forget release! mDanmakuView.release(); mDanmakuView = null; } } @Override public void onConfigurationChanged(Configuration newConfig) { if (isInitialized()) { setVideoLayout(); attachMediaController(); } super.onConfigurationChanged(newConfig); } @Override public void onBackPressed() { // super.onBackPressed(); // if (mDanmakuView != null) { // // dont forget release! // mDanmakuView.release(); // mDanmakuView = null; // } } @Override protected void onSaveInstanceState(Bundle outState) { // http://code.google.com/p/android/issues/detail?id=19917 outState.putString("WORKAROUND_FOR_BUG_19917_KEY", "WORKAROUND_FOR_BUG_19917_VALUE"); super.onSaveInstanceState(outState); } @Override public void showMenu() { } private void loadView(int id) { setContentView(id); getWindow().setBackgroundDrawable(null); mViewRoot = findViewById(R.id.video_root); mVideoView = (VideoView) findViewById(R.id.video); mVideoView.initialize(this, this, mIsHWCodec); mSubtitleContainer = findViewById(R.id.subtitle_container); mSubtitleText = (OutlineTextView) findViewById(R.id.subtitle_text); mSubtitleImage = (ImageView) findViewById(R.id.subtitle_image); mVideoLoadingText = (TextView) findViewById(R.id.video_loading_text); mVideoLoadingLayout = findViewById(R.id.video_loading); // mLoadingProgressView = // mVideoLoadingLayout.findViewById(R.id.video_loading_progress); // mLoadingAnimation = AnimationUtils.loadAnimation(VideoActivity.this, // R.anim.loading_rotate); getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); } private void parseIntent(Intent i) { // Uri dat = IntentHelper.getIntentUri(i); // if (dat == null) // resultFinish(RESULT_FAILED); // // String datString = dat.toString(); // if (!datString.equals(dat.toString())) // dat = Uri.parse(datString); // // mUri = dat; // danmakuPath = "http://comment.bilibili.com/"+i.getStringExtra("CID")+".xml"; // Logger.d(danmakuPath); av = i.getStringExtra("av"); page = i.getStringExtra("page"); mNeedLock = i.getBooleanExtra("lockScreen", false); mDisplayName = i.getStringExtra("displayName"); mFromStart = i.getBooleanExtra("fromStart", false); mSaveUri = i.getBooleanExtra("saveUri", true); mStartPos = i.getFloatExtra("startPosition", -1.0f); mLoopCount = i.getIntExtra("loopCount", 1); mParentId = i.getIntExtra("parentId", 0); mSubPath = i.getStringExtra("subPath"); mSubShown = i.getBooleanExtra("subShown", true); mIsHWCodec = i.getBooleanExtra("hwCodec", false); Log.i("L: %b, N: %s, S: %b, P: %f, LP: %d", mNeedLock, mDisplayName, mFromStart, mStartPos, mLoopCount); } private void manageReceivers() { if (!mReceiverRegistered) { mScreenReceiver = new ScreenReceiver(); registerReceiver(mScreenReceiver, SCREEN_FILTER); mUserPresentReceiver = new UserPresentReceiver(); registerReceiver(mUserPresentReceiver, USER_PRESENT_FILTER); mBatteryReceiver = new BatteryReceiver(); registerReceiver(mBatteryReceiver, BATTERY_FILTER); mHeadsetPlugReceiver = new HeadsetPlugReceiver(); registerReceiver(mHeadsetPlugReceiver, HEADSET_FILTER); mReceiverRegistered = true; } else { try { if (mScreenReceiver != null) unregisterReceiver(mScreenReceiver); if (mUserPresentReceiver != null) unregisterReceiver(mUserPresentReceiver); if (mHeadsetPlugReceiver != null) unregisterReceiver(mHeadsetPlugReceiver); if (mBatteryReceiver != null) unregisterReceiver(mBatteryReceiver); } catch (IllegalArgumentException e) { } mReceiverRegistered = false; } } private void setFileName() { if (mUri != null) { String name = null; if (mUri.getScheme() == null || mUri.getScheme().equals("file")) name = FileUtils.getName(mUri.toString()); else name = mUri.getLastPathSegment(); if (name == null) name = "null"; if (mDisplayName == null) mDisplayName = name; mMediaController.setFileName(mDisplayName); } } private void applyResult(int resultCode) { vPlayerHandler.removeMessages(BUFFER_PROGRESS); Intent i = new Intent(); i.putExtra("filePath", mUri.toString()); if (isInitialized()) { i.putExtra("position", (double) vPlayer.getCurrentPosition() / vPlayer.getDuration()); i.putExtra("duration", vPlayer.getDuration()); //savePosition(); } switch (resultCode) { case RESULT_FAILED: ToastUtils.showLongToast(R.string.video_cannot_play); break; case RESULT_CANCELED: case RESULT_OK: break; } setResult(resultCode, i); } private void resultFinish(int resultCode) { applyResult(resultCode); if (DeviceUtils.hasICS() && resultCode != RESULT_FAILED) { android.os.Process.killProcess(android.os.Process.myPid()); } else { finish(); } } private void release() { if (vPlayer != null) { if (DeviceUtils.hasICS()) { android.os.Process.killProcess(android.os.Process.myPid()); } else { vPlayer.release(); vPlayer.releaseContext(); } } } private void reOpen(Uri path, String name, boolean fromStart) { if (isInitialized()) { //savePosition(); vPlayer.release(); vPlayer.releaseContext(); } Intent i = getIntent(); if (mMediaController != null) i.putExtra("lockScreen", mMediaController.isLocked()); i.putExtra("startPosition", PreferenceUtils.getFloat(mUri + VP.SESSION_LAST_POSITION_SUFIX, 7.7f)); i.putExtra("fromStart", fromStart); i.putExtra("displayName", name); i.setData(path); parseIntent(i); mUri = path; if (mViewRoot != null) mViewRoot.invalidate(); if (mOpened != null) mOpened.set(false); } public void reOpen() { reOpen(mUri, mDisplayName, false); } protected void startPlayer() { if (isInitialized() && mScreenReceiver.screenOn && !vPlayer.isBuffering()&&isload) { Log.i("VideoActivity#startPlayer"); if (!vPlayer.isPlaying()) { vPlayer.start(); if(mDanmakuView.isPaused()) mDanmakuView.resume(); else mDanmakuView.start(); } } } protected void stopPlayer() { if (isInitialized()) { vPlayer.stop(); if(mDanmakuView != null){ if(mDanmakuView.isPrepared()&&mDanmakuView.isShown()); mDanmakuView.pause(); } } } private void setBatteryLevel() { if (mMediaController != null) mMediaController.setBatteryLevel(mBatteryLevel); } private class BatteryReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { int level = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, 0); int scale = intent.getIntExtra(BatteryManager.EXTRA_SCALE, 100); int percent = scale > 0 ? level * 100 / scale : 0; if (percent > 100) percent = 100; mBatteryLevel = String.valueOf(percent) + "%"; setBatteryLevel(); } } private class UserPresentReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { if (isRootActivity()) { startPlayer(); } } } private boolean isRootActivity() { return ApplicationUtils.isTopActivity(getApplicationContext(), getClass().getName()); // ActivityManager activity = (ActivityManager) // getSystemService(Context.ACTIVITY_SERVICE); // return // activity.getRunningTasks(1).get(0).topActivity.flattenToString().endsWith("io.vov.vitamio.activity.VideoActivity"); } public class HeadsetPlugReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { if (intent != null && intent.hasExtra("state")) { int state = intent.getIntExtra("state", -1); if (state == 0) { mHeadsetPlaying = isPlaying(); stopPlayer(); } else if (state == 1) { if (mHeadsetPlaying) startPlayer(); } } }; } private class ScreenReceiver extends BroadcastReceiver { private boolean screenOn = true; @Override public void onReceive(Context context, Intent intent) { if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) { screenOn = false; stopPlayer(); } else if (intent.getAction().equals(Intent.ACTION_SCREEN_ON)) { screenOn = true; } } } private void loadVPlayerPrefs() { if (!isInitialized()) return; vPlayer.setBuffer(VP.DEFAULT_BUF_SIZE); vPlayer.setVideoQuality(VP.DEFAULT_VIDEO_QUALITY); vPlayer.setDeinterlace(VP.DEFAULT_DEINTERLACE); vPlayer.setVolume(VP.DEFAULT_STEREO_VOLUME, VP.DEFAULT_STEREO_VOLUME); vPlayer.setSubEncoding(VP.DEFAULT_SUB_ENCODING); MarginLayoutParams lp = (MarginLayoutParams) mSubtitleContainer .getLayoutParams(); lp.bottomMargin = (int) VP.DEFAULT_SUB_POS; mSubtitleContainer.setLayoutParams(lp); vPlayer.setSubShown(mSubShown); setTextViewStyle(mSubtitleText); if (!TextUtils.isEmpty(mSubPath)) vPlayer.setSubPath(mSubPath); if (mVideoView != null && isInitialized()) setVideoLayout(); } private void setTextViewStyle(OutlineTextView v) { v.setTextColor(VP.DEFAULT_SUB_COLOR); v.setTypeface(VP.getTypeface(VP.DEFAULT_TYPEFACE_INT), VP.DEFAULT_SUB_STYLE); v.setShadowLayer(VP.DEFAULT_SUB_SHADOWRADIUS, 0, 0, VP.DEFAULT_SUB_SHADOWCOLOR); } private boolean isInitialized() { return (mCreated && vPlayer != null && vPlayer.isInitialized()); } private Handler mSubHandler = new Handler() { Bundle data; String text; byte[] pixels; int width = 0, height = 0; Bitmap bm = null; int oldType = SUBTITLE_TEXT; @Override public void handleMessage(Message msg) { data = msg.getData(); switch (msg.what) { case SUBTITLE_TEXT: if (oldType != SUBTITLE_TEXT) { mSubtitleImage.setVisibility(View.GONE); mSubtitleText.setVisibility(View.VISIBLE); oldType = SUBTITLE_TEXT; } text = data.getString(VP.SUB_TEXT_KEY); mSubtitleText.setText(text == null ? "" : text.trim()); break; case SUBTITLE_BITMAP: if (oldType != SUBTITLE_BITMAP) { mSubtitleText.setVisibility(View.GONE); mSubtitleImage.setVisibility(View.VISIBLE); oldType = SUBTITLE_BITMAP; } pixels = data.getByteArray(VP.SUB_PIXELS_KEY); if (bm == null || width != data.getInt(VP.SUB_WIDTH_KEY) || height != data.getInt(VP.SUB_HEIGHT_KEY)) { width = data.getInt(VP.SUB_WIDTH_KEY); height = data.getInt(VP.SUB_HEIGHT_KEY); bm = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); } if (pixels != null) bm.copyPixelsFromBuffer(ByteBuffer.wrap(pixels)); mSubtitleImage.setImageBitmap(bm); break; } } }; private AtomicBoolean mOpened = new AtomicBoolean(Boolean.FALSE); private boolean mSurfaceCreated = false; private boolean mServiceConnected = false; private Object mOpenLock = new Object(); private static final int OPEN_FILE = 0; private static final int OPEN_START = 1; private static final int OPEN_SUCCESS = 2; private static final int OPEN_FAILED = 3; private static final int HW_FAILED = 4; private static final int LOAD_PREFS = 5; private static final int BUFFER_START = 11; private static final int BUFFER_PROGRESS = 12; private static final int BUFFER_COMPLETE = 13; private static final int CLOSE_START = 21; private static final int CLOSE_COMPLETE = 22; private static final int SUBTITLE_TEXT = 0; private static final int SUBTITLE_BITMAP = 1; private Handler vPlayerHandler = new Handler() { @Override public void handleMessage(Message msg) { switch (msg.what) { case OPEN_FILE: synchronized (mOpenLock) { if (!mOpened.get() && vPlayer != null) { mOpened.set(true); vPlayer.setVPlayerListener(vPlayerListener); if (vPlayer.isInitialized()) mUri = vPlayer.getUri(); if (mVideoView != null) vPlayer.setDisplay(mVideoView.getHolder()); if (mUri != null) vPlayer.initialize(mUri, mDisplayName, mSaveUri, getStartPosition(), vPlayerListener, mParentId, mIsHWCodec); } } break; case OPEN_START: mVideoLoadingText.setText(R.string.video_layout_loading); setVideoLoadingLayoutVisibility(View.VISIBLE); break; case OPEN_SUCCESS: loadVPlayerPrefs(); setVideoLoadingLayoutVisibility(View.GONE); setVideoLayout(); vPlayer.start(); if(mDanmakuView.isPaused()) mDanmakuView.resume(); else mDanmakuView.start(); attachMediaController(); break; case OPEN_FAILED: resultFinish(RESULT_FAILED); break; case BUFFER_START: setVideoLoadingLayoutVisibility(View.VISIBLE); vPlayerHandler.sendEmptyMessageDelayed(BUFFER_PROGRESS, 1000); break; case BUFFER_PROGRESS: if (vPlayer.getBufferProgress() >= 100) { setVideoLoadingLayoutVisibility(View.GONE); } else { mVideoLoadingText.setText(getString( R.string.video_layout_buffering_progress, vPlayer.getBufferProgress())); vPlayerHandler.sendEmptyMessageDelayed(BUFFER_PROGRESS, 1000); stopPlayer(); } break; case BUFFER_COMPLETE: setVideoLoadingLayoutVisibility(View.GONE); vPlayerHandler.removeMessages(BUFFER_PROGRESS); break; case CLOSE_START: mVideoLoadingText.setText(R.string.closing_file); setVideoLoadingLayoutVisibility(View.VISIBLE); break; case CLOSE_COMPLETE: mCloseComplete = true; break; case HW_FAILED: if (mVideoView != null) { mVideoView.setVisibility(View.GONE); mVideoView.setVisibility(View.VISIBLE); mVideoView.initialize(BiliVideoViewActivity.this, BiliVideoViewActivity.this, false); } break; case LOAD_PREFS: loadVPlayerPrefs(); break; } } }; private void setVideoLoadingLayoutVisibility(int visibility) { if (mVideoLoadingLayout != null) { // if (visibility == View.VISIBLE) // mLoadingProgressView.startAnimation(mLoadingAnimation); mVideoLoadingLayout.setVisibility(visibility); } } private PlayerService.VPlayerListener vPlayerListener = new PlayerService.VPlayerListener() { @Override public void onHWRenderFailed() { if (Build.VERSION.SDK_INT < 11 && mIsHWCodec) { vPlayerHandler.sendEmptyMessage(HW_FAILED); vPlayerHandler.sendEmptyMessageDelayed(HW_FAILED, 200); } } @Override public void onSubChanged(String sub) { Message msg = new Message(); Bundle b = new Bundle(); b.putString(VP.SUB_TEXT_KEY, sub); msg.setData(b); msg.what = SUBTITLE_TEXT; mSubHandler.sendMessage(msg); } @Override public void onSubChanged(byte[] pixels, int width, int height) { Message msg = new Message(); Bundle b = new Bundle(); b.putByteArray(VP.SUB_PIXELS_KEY, pixels); b.putInt(VP.SUB_WIDTH_KEY, width); b.putInt(VP.SUB_HEIGHT_KEY, height); msg.setData(b); msg.what = SUBTITLE_BITMAP; mSubHandler.sendMessage(msg); } @Override public void onOpenStart() { vPlayerHandler.sendEmptyMessage(OPEN_START); } @Override public void onOpenSuccess() { vPlayerHandler.sendEmptyMessage(OPEN_SUCCESS); } @Override public void onOpenFailed() { vPlayerHandler.sendEmptyMessage(OPEN_FAILED); } @Override public void onBufferStart() { //if(isfirst){} vPlayerHandler.sendEmptyMessage(BUFFER_START); stopPlayer(); } @Override public void onBufferComplete() { Log.i("VideoActivity#onBufferComplete " + vPlayer.needResume()); if(isfirst){ startVideo.setVisibility(View.GONE); anim.stop(); isfirst = false; } vPlayerHandler.sendEmptyMessage(BUFFER_COMPLETE); if (vPlayer != null && !vPlayer.needResume()) startPlayer(); } @Override public void onPlaybackComplete() { mEnd = true; if (mLoopCount == 0 || mLoopCount-- > 1) { vPlayer.start(); if(mDanmakuView.isPaused()) mDanmakuView.resume(); else mDanmakuView.start(); vPlayer.seekTo(0); } else { resultFinish(RESULT_OK); } } @Override public void onCloseStart() { vPlayerHandler.sendEmptyMessage(CLOSE_START); } @Override public void onCloseComplete() { vPlayerHandler.sendEmptyMessage(CLOSE_COMPLETE); } @Override public void onVideoSizeChanged(int width, int height) { if (mVideoView != null) { setVideoLayout(); } } @Override public void onDownloadRateChanged(int kbPerSec) { if (!MediaUtils.isNative(mUri.toString()) && mMediaController != null) { mMediaController.setDownloadRate(String.format("%dKB/s", kbPerSec)); } } }; private int mVideoMode = VideoView.VIDEO_LAYOUT_SCALE; private void setVideoLayout() { mVideoView.setVideoLayout(mVideoMode, VP.DEFAULT_ASPECT_RATIO, vPlayer.getVideoWidth(), vPlayer.getVideoHeight(), vPlayer.getVideoAspectRatio()); } private void savePosition() { if (vPlayer != null && mUri != null) { PreferenceUtils.put( mUri.toString(), StringUtils.generateTime((int) (0.5 + vPlayer .getCurrentPosition())) + " / " + StringUtils.generateTime(vPlayer.getDuration())); if (mEnd) PreferenceUtils .put(mUri + VP.SESSION_LAST_POSITION_SUFIX, 1.0f); else PreferenceUtils .put(mUri + VP.SESSION_LAST_POSITION_SUFIX, (float) (vPlayer.getCurrentPosition() / (double) vPlayer .getDuration())); } } private float getStartPosition() { if (mFromStart) return 1.1f; if (mStartPos <= 0.0f || mStartPos >= 1.0f) return PreferenceUtils.getFloat(mUri + VP.SESSION_LAST_POSITION_SUFIX, 7.7f); return mStartPos; } @Override public int getBufferPercentage() { if (isInitialized()) return (int) (vPlayer.getBufferProgress() * 100); return 0; } @Override public long getCurrentPosition() { if (isInitialized()) return vPlayer.getCurrentPosition(); return (long) (getStartPosition() * vPlayer.getDuration()); } @Override public long getDuration() { if (isInitialized()) return vPlayer.getDuration(); return 0; } @Override public boolean isPlaying() { if (isInitialized()) return vPlayer.isPlaying(); return false; } @Override public void pause() { if (isInitialized()) vPlayer.stop(); mDanmakuView.pause(); } @Override public void seekTo(long arg0) { if (isInitialized()) vPlayer.seekTo((float) ((double) arg0 / vPlayer.getDuration())); mDanmakuView.seekTo(arg0); mDanmakuView.pause(); } @Override public void start() { if (isInitialized()) vPlayer.start(); if(mDanmakuView.isPaused()) mDanmakuView.resume(); else mDanmakuView.start(); } @Override public void previous() { } @Override public void next() { } private static final int VIDEO_MAXIMUM_HEIGHT = 2048; private static final int VIDEO_MAXIMUM_WIDTH = 2048; @Override public float scale(float scaleFactor) { float userRatio = VP.DEFAULT_ASPECT_RATIO; int videoWidth = vPlayer.getVideoWidth(); int videoHeight = vPlayer.getVideoHeight(); float videoRatio = vPlayer.getVideoAspectRatio(); float currentRatio = mVideoView.mVideoHeight / (float) videoHeight; currentRatio += (scaleFactor - 1); if (videoWidth * currentRatio >= VIDEO_MAXIMUM_WIDTH) currentRatio = VIDEO_MAXIMUM_WIDTH / (float) videoWidth; if (videoHeight * currentRatio >= VIDEO_MAXIMUM_HEIGHT) currentRatio = VIDEO_MAXIMUM_HEIGHT / (float) videoHeight; if (currentRatio < 0.5f) currentRatio = 0.5f; mVideoView.mVideoHeight = (int) (videoHeight * currentRatio); mVideoView.setVideoLayout(mVideoMode, userRatio, videoWidth, videoHeight, videoRatio); return currentRatio; } @SuppressLint("SimpleDateFormat") @Override public void snapshot() { if (!com.cjj.bb.utils.FileUtils.sdAvailable()) { ToastUtils.showToast(R.string.file_explorer_sdcard_not_available); } else { Uri imgUri = null; Bitmap bitmap = vPlayer.getCurrentFrame(); if (bitmap != null) { File screenshotsDirectory = new File( Environment .getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES) + VP.SNAP_SHOT_PATH); if (!screenshotsDirectory.exists()) { screenshotsDirectory.mkdirs(); } File savePath = new File( screenshotsDirectory.getPath() + "/" + new SimpleDateFormat("yyyyMMddHHmmss") .format(new Date()) + ".jpg"); if (ImageUtils.saveBitmap(savePath.getPath(), bitmap)) { imgUri = Uri.fromFile(savePath); } } if (imgUri != null) { sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, imgUri)); ToastUtils.showLongToast(getString( R.string.video_screenshot_save_in, imgUri.getPath())); } else { ToastUtils.showToast(R.string.video_screenshot_failed); } } } @Override public void toggleVideoMode(int mode) { mVideoMode = mode; setVideoLayout(); } @Override public void stop() { onBackPressed(); } @Override public long goForward() { return 0; } @Override public long goBack() { return 0; } @Override public void removeLoadingView() { mVideoLoadingLayout.setVisibility(View.GONE); } @Override public void onSurfaceCreated(SurfaceHolder holder) { Log.i("onSurfaceCreated"); mSurfaceCreated = true; if (mServiceConnected) vPlayerHandler.sendEmptyMessage(OPEN_FILE); if (vPlayer != null) vPlayer.setDisplay(holder); } @Override public void onSurfaceChanged(SurfaceHolder holder, int format, int width, int height) { if (vPlayer != null) { setVideoLayout(); } } @Override public void onSurfaceDestroyed(SurfaceHolder holder) { Log.i("onSurfaceDestroyed"); if (vPlayer != null && vPlayer.isInitialized()) { if (vPlayer.isPlaying()) { vPlayer.stop(); vPlayer.setState(PlayerService.STATE_NEED_RESUME); } vPlayer.releaseSurface(); if (vPlayer.needResume()){ vPlayer.start(); if(mDanmakuView.isPaused()) mDanmakuView.resume(); else mDanmakuView.start(); } } } @Override public void setDanmakushow(boolean isShow) { // TODO Auto-generated method stub if(mDanmakuView != null){ if(isShow){ mDanmakuView.show(); }else{ mDanmakuView.hide(); } } } private class VideoViewInitTask extends AsyncTask { @Override protected Integer doInBackground(String... arg0) { // TODO Auto-generated method stub Log.d("TAG", "开始解析视频地址"); try { JSONObject videopathjson = new JSONObject(HttpUtil.getHtmlString("http://www.bilibili.com/m/html5?aid=" + av + "&page=" + page)); Log.d("QAQ--->","===>"+videopathjson.getString("src").toString()); danmakuPath = videopathjson.getString("cid").toString(); mUri = Uri.parse(videopathjson.getString("src").toString()); } catch (JSONException e) { // TODO Auto-generated catch block e.printStackTrace(); } Log.d("TAG", "开始加载弹幕"); mParser = createParser(danmakuPath); return null; } @Override protected void onPostExecute(Integer result) { // TODO Auto-generated method stub super.onPostExecute(result); Log.d("TAG", "加载弹幕成功"); // if (mDanmakuView != null) { // mDanmakuView.prepare(mParser); // mDanmakuView.showFPS(true); // mDanmakuView.enableDanmakuDrawingCache(true); // isload = true; // //startPlayer(); // // } if(mParser != null){ mDanmakuView.prepare(mParser); mDanmakuView.showFPS(false); mDanmakuView.enableDanmakuDrawingCache(false); }else{ startText = startText + "【失败】\n视频缓冲中..."; startVideoInfo.setText(startText); } // mDanmakuView.prepare(mParser); // mDanmakuView.showFPS(true); // mDanmakuView.enableDanmakuDrawingCache(true); isload = true; Intent serviceIntent = new Intent(getApplicationContext(), PlayerService.class); serviceIntent.putExtra("isHWCodec", mIsHWCodec); bindService(serviceIntent, vPlayerServiceConnection,Context.BIND_AUTO_CREATE); startText = startText + "【完成】\n视频缓冲中..."; startVideoInfo.setText(startText); } } /*退出的间隔时间 */ private static final long EXIT_INTERVAL_TIME = 2000; private long touchTime = 0; public boolean onKeyUp(int keyCode, KeyEvent event) { if (keyCode == KeyEvent.KEYCODE_BACK ) { long currentTime = System.currentTimeMillis(); if ((currentTime - touchTime) >= EXIT_INTERVAL_TIME) { Toast.makeText(BiliVideoViewActivity.this, "再按一下退出喵(。・ω・。)~", Toast.LENGTH_SHORT).show(); touchTime = currentTime; } else { finish(); if(mDanmakuView!=null) mDanmakuView.release(); } return false; } else { return true; } } } ================================================ FILE: app/src/main/java/com/cjj/bb/activity/BiliWebviewActivity.java ================================================ package com.cjj.bb.activity; import android.app.Activity; import android.os.Bundle; import android.view.View; import android.view.Window; import android.view.View.OnClickListener; import android.webkit.WebView; import android.webkit.WebViewClient; import android.widget.ImageView; import android.widget.ProgressBar; import com.cjj.bb.R; public class BiliWebviewActivity extends Activity{ private ProgressBar progressBar; // 进度条 private ImageView reLoadImageView; // 重新加载的图片 private WebView biliWebView;//网页控件 private ImageView backBtn; // 回退按钮 private ImageView commentBtn; // 评论按钮 public static String url; private String filename; @Override protected void onCreate(Bundle savedInstanceState) { requestWindowFeature(Window.FEATURE_NO_TITLE);// 无标题 super.onCreate(savedInstanceState); setContentView(R.layout.bili_webview); init(); initComponent(); biliWebView.getSettings().setJavaScriptEnabled(true); biliWebView.setWebViewClient(new WebViewClient(){ @Override public boolean shouldOverrideUrlLoading(WebView view, String url) { // TODO Auto-generated method stub view.loadUrl(url); return true; } }); biliWebView.loadUrl(url); } // 初始化 private void init() { url = getIntent().getExtras().getString("bannerLink"); filename = url.substring(url.lastIndexOf("/") + 1); System.out.println("filename--->" + filename); } // 初始化组件 private void initComponent() { biliWebView = (WebView)findViewById(R.id.BiliWebView); progressBar = (ProgressBar) findViewById(R.id.blogContentPro); reLoadImageView = (ImageView) findViewById(R.id.reLoadImage); reLoadImageView.setOnClickListener(new OnClickListener() { @Override public void onClick(View view) { reLoadImageView.setVisibility(View.INVISIBLE); progressBar.setVisibility(View.VISIBLE); } }); backBtn = (ImageView) findViewById(R.id.backBtn); backBtn.setOnClickListener(new OnClickListener() { @Override public void onClick(View arg0) { finish(); } }); commentBtn = (ImageView) findViewById(R.id.comment); } } ================================================ FILE: app/src/main/java/com/cjj/bb/activity/DonghuaActivity.java ================================================ package com.cjj.bb.activity; import android.os.Bundle; import android.support.v4.app.FragmentActivity; import android.support.v4.app.FragmentPagerAdapter; import android.support.v4.view.ViewPager; import android.support.v7.app.ActionBarActivity; import android.util.Log; import android.view.View; import android.view.View.OnClickListener; import android.view.Window; import android.widget.ImageButton; import android.widget.TextView; import com.cjj.bb.R; import com.cjj.bb.adapter.BankumiTabAdapter; import com.cjj.bb.adapter.DianyingTabAdapter; import com.cjj.bb.adapter.DonghuaTabAdapter; import com.cjj.bb.adapter.KejiTabAdapter; import com.cjj.bb.adapter.MusicTabAdapter; import com.cjj.bb.adapter.RankAdapter; import com.cjj.bb.adapter.YouxiTabAdapter; import com.cjj.bb.adapter.YuleTabAdapter; import viewpagerindicator.PageIndicator; /** * 动画界面 * * @author wwj_748 * @date 2014/8/9 */ public class DonghuaActivity extends ActionBarActivity { public int mAreaType; private View backButton; private TextView titleText; @Override public void onCreate(Bundle savedInstanceState) { requestWindowFeature(Window.FEATURE_NO_TITLE); // 无标题 super.onCreate(savedInstanceState); setContentView(R.layout.donghua_tab); backButton = findViewById(R.id.logobutton); titleText = (TextView) findViewById(R.id.textViewTitle); FragmentPagerAdapter adapter = null; mAreaType = getIntent().getIntExtra("AreaType", 1); Log.d("QAQ","----->"+mAreaType+titleText.getText()); switch (mAreaType){ case 1: titleText.setText("番剧"); adapter = new BankumiTabAdapter(getSupportFragmentManager()); break; case 2: titleText.setText("动画"); adapter = new DonghuaTabAdapter(getSupportFragmentManager()); break; case 3: titleText.setText("音乐"); adapter = new MusicTabAdapter(getSupportFragmentManager()); break; case 4: titleText.setText("游戏"); adapter = new YouxiTabAdapter(getSupportFragmentManager()); break; case 5: titleText.setText("科学·技术"); adapter = new KejiTabAdapter(getSupportFragmentManager()); break; case 6: titleText.setText("娱乐"); adapter = new YuleTabAdapter(getSupportFragmentManager()); break; case 7: titleText.setText("电影"); adapter = new DianyingTabAdapter(getSupportFragmentManager()); break; case 8: titleText.setText("排行榜"); adapter = new RankAdapter(getSupportFragmentManager()); break; default: titleText.setText("电影"); adapter = new DianyingTabAdapter(getSupportFragmentManager()); break; } // 视图切换器 ViewPager pager = (ViewPager) findViewById(R.id.pager); pager.setOffscreenPageLimit(1); pager.setAdapter(adapter); // 页面指示器 PageIndicator indicator = (PageIndicator) findViewById(R.id.indicator); indicator.setViewPager(pager); backButton.setOnClickListener(new OnClickListener() { @Override public void onClick(View arg0) { // TODO Auto-generated method stub finish(); } }); getSupportActionBar().hide(); } } ================================================ FILE: app/src/main/java/com/cjj/bb/activity/MainActivity.java ================================================ package com.cjj.bb.activity; import android.app.AlertDialog.Builder; import android.content.DialogInterface; import android.os.Bundle; import android.support.v4.app.FragmentPagerAdapter; import android.support.v4.view.ViewPager; import android.support.v7.app.ActionBarActivity; import android.util.Log; import android.view.KeyEvent; import android.view.Menu; import android.view.Window; import com.cjj.bb.R; import com.cjj.bb.adapter.MainTabAdapter; import viewpagerindicator.TabPageIndicator; import viewpagerindicator.TitlePageIndicator; public class MainActivity extends ActionBarActivity { @Override protected void onCreate(Bundle savedInstanceState) { requestWindowFeature(Window.FEATURE_NO_TITLE); // 无标题 super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); FragmentPagerAdapter adapter = new MainTabAdapter(getSupportFragmentManager()); // 视图切换器 ViewPager pager = (ViewPager) findViewById(R.id.pager); pager.setOffscreenPageLimit(3); pager.setAdapter(adapter); // // 页面指示器 // PageIndicator indicator = (PageIndicator) findViewById(R.id.indicator); // indicator.setViewPager(pager); TitlePageIndicator indicator = (TitlePageIndicator)findViewById(R.id.indicator); indicator.setViewPager(pager); indicator.setCurrentItem(1); /*if (savedInstanceState == null) { getSupportFragmentManager().beginTransaction() .add(R.id.container, new SubareaFragment()) .commit(); }*/ // AdManager.getInstance(this).init("118250e2aa39dea9", "bc5f4490f33da8e6", false); // SpotManager.getInstance(this).loadSpotAds(); // SpotManager.getInstance(this).setAnimationType(SpotManager.ANIM_ADVANCE); // SpotManager.getInstance(this).setSpotOrientation(SpotManager.ORIENTATION_PORTRAIT); // AdManager.getInstance(this).setUserDataCollect(true); getSupportActionBar().hide(); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.main, menu); return true; } /** * On key up. * * @param keyCode * the key code * @param event * the event * @return true, if successful */ public boolean onKeyUp(int keyCode, KeyEvent event) { if (keyCode == KeyEvent.KEYCODE_BACK) { // show_existDialog(); // 退出程序 finish(); return false; } else { return true; } } // private void show_existDialog() { // // 弹出退出对话框 // Builder dialog = new Builder(MainActivity.this) // .setMessage("您确定要退出吗?") // .setPositiveButton("确定", new DialogInterface.OnClickListener() { // // @Override // public void onClick(DialogInterface arg0, int arg1) { // // 退出程序 // finish(); // } // }) // .setNegativeButton("支持我", new DialogInterface.OnClickListener() { // // @Override // public void onClick(DialogInterface arg0, int arg1) { // SpotManager.getInstance(MainActivity.this).showSpotAds( // MainActivity.this, new SpotDialogListener() { // @Override // public void onShowSuccess() { // Log.i("YoumiAdDemo", "展示成功"); // } // // @Override // public void onShowFailed() { // Log.i("YoumiAdDemo", "展示失败"); // } // // @Override // public void onSpotClosed() { // Log.i("YoumiAdDemo", "展示关闭"); // } // // }); // } // }); // dialog.show(); // } // public void onBackPressed() { // // 如果有需要,可以点击后退关闭插播广告。 // if (!SpotManager.getInstance(this).disMiss()) { // // 弹出退出窗口,可以使用自定义退屏弹出和回退动画,参照demo,若不使用动画,传入-1 // super.onBackPressed(); // } } @Override protected void onStop() { // 如果不调用此方法,则按home键的时候会出现图标无法显示的情况。 // SpotManager.getInstance(this).onStop(); super.onStop(); } @Override protected void onDestroy() { // SpotManager.getInstance(this).onDestroy(); super.onDestroy(); } } ================================================ FILE: app/src/main/java/com/cjj/bb/activity/TVActivity.java ================================================ package com.cjj.bb.activity; import android.os.Bundle; import android.support.v7.app.ActionBarActivity; import android.view.Menu; import android.view.View; import android.view.Window; import android.view.View.OnClickListener; import android.widget.TextView; import com.cjj.bb.R; import com.cjj.bb.fragment.OnlineFragment; public class TVActivity extends ActionBarActivity{ private View backButton; private TextView titleText; private OnlineFragment online = new OnlineFragment(); @Override protected void onCreate(Bundle savedInstanceState) { requestWindowFeature(Window.FEATURE_NO_TITLE); // 无标题 super.onCreate(savedInstanceState); setContentView(R.layout.activity_video_info); if (savedInstanceState == null) { getSupportFragmentManager().beginTransaction() .add(R.id.container, online) .commit(); } backButton = findViewById(R.id.logobutton); titleText = (TextView) findViewById(R.id.textViewTitle); titleText.setText("网络电视"); backButton.setOnClickListener(new OnClickListener() { @Override public void onClick(View arg0) { // TODO Auto-generated method stub finish(); } }); getSupportActionBar().hide(); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.main, menu); return true; } @Override public void onBackPressed() { if (online.onBackPressed()) return; else super.onBackPressed(); } } ================================================ FILE: app/src/main/java/com/cjj/bb/activity/VideoInfoActivity.java ================================================ package com.cjj.bb.activity; import android.os.Bundle; import android.support.v7.app.ActionBarActivity; import android.view.Menu; import android.view.View; import android.view.Window; import android.view.View.OnClickListener; import android.widget.LinearLayout; import android.widget.TextView; import com.cjj.bb.R; import com.cjj.bb.fragment.VideoInfoFragment; public class VideoInfoActivity extends ActionBarActivity{ private View backButton; private TextView titleText; @Override protected void onCreate(Bundle savedInstanceState) { requestWindowFeature(Window.FEATURE_NO_TITLE); // 无标题 super.onCreate(savedInstanceState); setContentView(R.layout.activity_video_info); if (savedInstanceState == null) { getSupportFragmentManager().beginTransaction() .add(R.id.container, new VideoInfoFragment()) .commit(); } backButton = findViewById(R.id.logobutton); titleText = (TextView) findViewById(R.id.textViewTitle); titleText.setText("视频详情"); backButton.setOnClickListener(new OnClickListener() { @Override public void onClick(View arg0) { // TODO Auto-generated method stub finish(); } }); getSupportActionBar().hide(); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.main, menu); return true; } } ================================================ FILE: app/src/main/java/com/cjj/bb/activity/VideoViewActivity.java ================================================ /* * Copyright (C) 2012 YIXIA.COM * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.cjj.bb.activity; import io.vov.vitamio.utils.FileUtils; import io.vov.vitamio.utils.Log; import io.vov.vitamio.widget.OutlineTextView; import java.io.File; import java.nio.ByteBuffer; import java.text.SimpleDateFormat; import java.util.Date; import java.util.concurrent.atomic.AtomicBoolean; import android.annotation.SuppressLint; import android.app.Activity; import android.app.KeyguardManager; import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.ServiceConnection; import android.content.res.Configuration; import android.graphics.Bitmap; import android.media.AudioManager; import android.net.Uri; import android.os.BatteryManager; import android.os.Build; import android.os.Bundle; import android.os.Environment; import android.os.Handler; import android.os.IBinder; import android.os.Message; import android.text.TextUtils; import android.view.SurfaceHolder; import android.view.View; import android.view.ViewGroup.MarginLayoutParams; import android.view.WindowManager; import android.widget.ImageView; import android.widget.TextView; import com.cjj.bb.R; import com.cjj.bb.utils.DeviceUtils; import com.cjj.bb.utils.ImageUtils; import com.cjj.bb.utils.IntentHelper; import com.cjj.bb.utils.MediaUtils; import com.cjj.bb.utils.PreferenceUtils; import com.cjj.bb.utils.StringUtils; import com.cjj.bb.utils.ToastUtils; import com.cjj.bb.view.ApplicationUtils; import com.cjj.bb.view.MediaController; import com.cjj.bb.view.PlayerService; import com.cjj.bb.view.VP; import com.cjj.bb.view.VideoView; @SuppressLint("HandlerLeak") public class VideoViewActivity extends Activity implements MediaController.MediaPlayerControl, VideoView.SurfaceCallback { public static final int RESULT_FAILED = -7; private static final IntentFilter USER_PRESENT_FILTER = new IntentFilter( Intent.ACTION_USER_PRESENT); private static final IntentFilter SCREEN_FILTER = new IntentFilter( Intent.ACTION_SCREEN_ON); private static final IntentFilter HEADSET_FILTER = new IntentFilter( Intent.ACTION_HEADSET_PLUG); private static final IntentFilter BATTERY_FILTER = new IntentFilter( Intent.ACTION_BATTERY_CHANGED); private boolean mCreated = false; private boolean mNeedLock; private String mDisplayName; private String mBatteryLevel; private boolean mFromStart; private int mLoopCount; private boolean mSaveUri; private int mParentId; private float mStartPos; private boolean mEnd = false; private String mSubPath; private boolean mSubShown; private View mViewRoot; private VideoView mVideoView; private View mVideoLoadingLayout; private TextView mVideoLoadingText; private View mSubtitleContainer; private OutlineTextView mSubtitleText; private ImageView mSubtitleImage; private Uri mUri; private ScreenReceiver mScreenReceiver; private HeadsetPlugReceiver mHeadsetPlugReceiver; private UserPresentReceiver mUserPresentReceiver; private BatteryReceiver mBatteryReceiver; private boolean mReceiverRegistered = false; private boolean mHeadsetPlaying = false; private boolean mCloseComplete = false; private boolean mIsHWCodec = false; private MediaController mMediaController; private PlayerService vPlayer; private ServiceConnection vPlayerServiceConnection; // private Animation mLoadingAnimation; // private View mLoadingProgressView; static { SCREEN_FILTER.addAction(Intent.ACTION_SCREEN_OFF); } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); if (!io.vov.vitamio.LibsChecker.checkVitamioLibs(this)) return; vPlayerServiceConnection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { vPlayer = ((PlayerService.LocalBinder) service).getService(); mServiceConnected = true; if (mSurfaceCreated) vPlayerHandler.sendEmptyMessage(OPEN_FILE); } @Override public void onServiceDisconnected(ComponentName name) { vPlayer = null; mServiceConnected = false; } }; setVolumeControlStream(AudioManager.STREAM_MUSIC); parseIntent(getIntent()); loadView(R.layout.activity_video); manageReceivers(); mCreated = true; } private void attachMediaController() { if (mMediaController != null) { mNeedLock = mMediaController.isLocked(); mMediaController.release(); } mMediaController = new MediaController(this, mNeedLock); mMediaController.setMediaPlayer(this); mMediaController.setAnchorView(mVideoView.getRootView()); mMediaController.setDanmakuVisible(false); setFileName(); setBatteryLevel(); } @Override public void onStart() { super.onStart(); if (!mCreated) return; Intent serviceIntent = new Intent(this, PlayerService.class); serviceIntent.putExtra("isHWCodec", mIsHWCodec); bindService(serviceIntent, vPlayerServiceConnection, Context.BIND_AUTO_CREATE); } @Override public void onResume() { super.onResume(); if (!mCreated) return; if (isInitialized()) { KeyguardManager keyguardManager = (KeyguardManager) getSystemService(KEYGUARD_SERVICE); if (!keyguardManager.inKeyguardRestrictedInputMode()) { startPlayer(); } } else { if (mCloseComplete) { reOpen(); } } } @Override public void onPause() { super.onPause(); if (!mCreated) return; if (isInitialized()) { savePosition(); if (vPlayer != null && vPlayer.isPlaying()) { stopPlayer(); } } } @Override public void onStop() { super.onStop(); if (!mCreated) return; if (isInitialized()) { vPlayer.releaseSurface(); } if (mServiceConnected) { unbindService(vPlayerServiceConnection); mServiceConnected = false; } } @Override public void onDestroy() { super.onDestroy(); if (!mCreated) return; manageReceivers(); if (isInitialized() && !vPlayer.isPlaying()) release(); if (mMediaController != null) mMediaController.release(); } @Override public void onConfigurationChanged(Configuration newConfig) { if (isInitialized()) { setVideoLayout(); attachMediaController(); } super.onConfigurationChanged(newConfig); } @Override public void onBackPressed() { super.onBackPressed(); } @Override protected void onSaveInstanceState(Bundle outState) { // http://code.google.com/p/android/issues/detail?id=19917 outState.putString("WORKAROUND_FOR_BUG_19917_KEY", "WORKAROUND_FOR_BUG_19917_VALUE"); super.onSaveInstanceState(outState); } @Override public void showMenu() { } private void loadView(int id) { setContentView(id); getWindow().setBackgroundDrawable(null); mViewRoot = findViewById(R.id.video_root); mVideoView = (VideoView) findViewById(R.id.video); mVideoView.initialize(this, this, mIsHWCodec); mSubtitleContainer = findViewById(R.id.subtitle_container); mSubtitleText = (OutlineTextView) findViewById(R.id.subtitle_text); mSubtitleImage = (ImageView) findViewById(R.id.subtitle_image); mVideoLoadingText = (TextView) findViewById(R.id.video_loading_text); mVideoLoadingLayout = findViewById(R.id.video_loading); // mLoadingProgressView = // mVideoLoadingLayout.findViewById(R.id.video_loading_progress); // mLoadingAnimation = AnimationUtils.loadAnimation(VideoActivity.this, // R.anim.loading_rotate); getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); } private void parseIntent(Intent i) { Uri dat = IntentHelper.getIntentUri(i); if (dat == null) resultFinish(RESULT_FAILED); String datString = dat.toString(); if (!datString.equals(dat.toString())) dat = Uri.parse(datString); mUri = dat; mNeedLock = i.getBooleanExtra("lockScreen", false); mDisplayName = i.getStringExtra("displayName"); mFromStart = i.getBooleanExtra("fromStart", false); mSaveUri = i.getBooleanExtra("saveUri", true); mStartPos = i.getFloatExtra("startPosition", -1.0f); mLoopCount = i.getIntExtra("loopCount", 1); mParentId = i.getIntExtra("parentId", 0); mSubPath = i.getStringExtra("subPath"); mSubShown = i.getBooleanExtra("subShown", true); mIsHWCodec = i.getBooleanExtra("hwCodec", false); Log.i("L: %b, N: %s, S: %b, P: %f, LP: %d", mNeedLock, mDisplayName, mFromStart, mStartPos, mLoopCount); } private void manageReceivers() { if (!mReceiverRegistered) { mScreenReceiver = new ScreenReceiver(); registerReceiver(mScreenReceiver, SCREEN_FILTER); mUserPresentReceiver = new UserPresentReceiver(); registerReceiver(mUserPresentReceiver, USER_PRESENT_FILTER); mBatteryReceiver = new BatteryReceiver(); registerReceiver(mBatteryReceiver, BATTERY_FILTER); mHeadsetPlugReceiver = new HeadsetPlugReceiver(); registerReceiver(mHeadsetPlugReceiver, HEADSET_FILTER); mReceiverRegistered = true; } else { try { if (mScreenReceiver != null) unregisterReceiver(mScreenReceiver); if (mUserPresentReceiver != null) unregisterReceiver(mUserPresentReceiver); if (mHeadsetPlugReceiver != null) unregisterReceiver(mHeadsetPlugReceiver); if (mBatteryReceiver != null) unregisterReceiver(mBatteryReceiver); } catch (IllegalArgumentException e) { } mReceiverRegistered = false; } } private void setFileName() { if (mUri != null) { String name = null; if (mUri.getScheme() == null || mUri.getScheme().equals("file")) name = FileUtils.getName(mUri.toString()); else name = mUri.getLastPathSegment(); if (name == null) name = "null"; if (mDisplayName == null) mDisplayName = name; mMediaController.setFileName(mDisplayName); } } private void applyResult(int resultCode) { vPlayerHandler.removeMessages(BUFFER_PROGRESS); Intent i = new Intent(); i.putExtra("filePath", mUri.toString()); if (isInitialized()) { i.putExtra("position", (double) vPlayer.getCurrentPosition() / vPlayer.getDuration()); i.putExtra("duration", vPlayer.getDuration()); savePosition(); } switch (resultCode) { case RESULT_FAILED: ToastUtils.showLongToast(R.string.video_cannot_play); break; case RESULT_CANCELED: case RESULT_OK: break; } setResult(resultCode, i); } private void resultFinish(int resultCode) { applyResult(resultCode); if (DeviceUtils.hasICS() && resultCode != RESULT_FAILED) { android.os.Process.killProcess(android.os.Process.myPid()); } else { finish(); } } private void release() { if (vPlayer != null) { if (DeviceUtils.hasICS()) { android.os.Process.killProcess(android.os.Process.myPid()); } else { vPlayer.release(); vPlayer.releaseContext(); } } } private void reOpen(Uri path, String name, boolean fromStart) { if (isInitialized()) { savePosition(); vPlayer.release(); vPlayer.releaseContext(); } Intent i = getIntent(); if (mMediaController != null) i.putExtra("lockScreen", mMediaController.isLocked()); i.putExtra("startPosition", PreferenceUtils.getFloat(mUri + VP.SESSION_LAST_POSITION_SUFIX, 7.7f)); i.putExtra("fromStart", fromStart); i.putExtra("displayName", name); i.setData(path); parseIntent(i); mUri = path; if (mViewRoot != null) mViewRoot.invalidate(); if (mOpened != null) mOpened.set(false); } public void reOpen() { reOpen(mUri, mDisplayName, false); } protected void startPlayer() { if (isInitialized() && mScreenReceiver.screenOn && !vPlayer.isBuffering()) { Log.i("VideoActivity#startPlayer"); if (!vPlayer.isPlaying()) { vPlayer.start(); } } } protected void stopPlayer() { if (isInitialized()) { vPlayer.stop(); } } private void setBatteryLevel() { if (mMediaController != null) mMediaController.setBatteryLevel(mBatteryLevel); } private class BatteryReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { int level = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, 0); int scale = intent.getIntExtra(BatteryManager.EXTRA_SCALE, 100); int percent = scale > 0 ? level * 100 / scale : 0; if (percent > 100) percent = 100; mBatteryLevel = String.valueOf(percent) + "%"; setBatteryLevel(); } } private class UserPresentReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { if (isRootActivity()) { startPlayer(); } } } private boolean isRootActivity() { return ApplicationUtils.isTopActivity(getApplicationContext(), getClass().getName()); // ActivityManager activity = (ActivityManager) // getSystemService(Context.ACTIVITY_SERVICE); // return // activity.getRunningTasks(1).get(0).topActivity.flattenToString().endsWith("io.vov.vitamio.activity.VideoActivity"); } public class HeadsetPlugReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { if (intent != null && intent.hasExtra("state")) { int state = intent.getIntExtra("state", -1); if (state == 0) { mHeadsetPlaying = isPlaying(); stopPlayer(); } else if (state == 1) { if (mHeadsetPlaying) startPlayer(); } } }; } private class ScreenReceiver extends BroadcastReceiver { private boolean screenOn = true; @Override public void onReceive(Context context, Intent intent) { if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) { screenOn = false; stopPlayer(); } else if (intent.getAction().equals(Intent.ACTION_SCREEN_ON)) { screenOn = true; } } } private void loadVPlayerPrefs() { if (!isInitialized()) return; vPlayer.setBuffer(VP.DEFAULT_BUF_SIZE); vPlayer.setVideoQuality(VP.DEFAULT_VIDEO_QUALITY); vPlayer.setDeinterlace(VP.DEFAULT_DEINTERLACE); vPlayer.setVolume(VP.DEFAULT_STEREO_VOLUME, VP.DEFAULT_STEREO_VOLUME); vPlayer.setSubEncoding(VP.DEFAULT_SUB_ENCODING); MarginLayoutParams lp = (MarginLayoutParams) mSubtitleContainer .getLayoutParams(); lp.bottomMargin = (int) VP.DEFAULT_SUB_POS; mSubtitleContainer.setLayoutParams(lp); vPlayer.setSubShown(mSubShown); setTextViewStyle(mSubtitleText); if (!TextUtils.isEmpty(mSubPath)) vPlayer.setSubPath(mSubPath); if (mVideoView != null && isInitialized()) setVideoLayout(); } private void setTextViewStyle(OutlineTextView v) { v.setTextColor(VP.DEFAULT_SUB_COLOR); v.setTypeface(VP.getTypeface(VP.DEFAULT_TYPEFACE_INT), VP.DEFAULT_SUB_STYLE); v.setShadowLayer(VP.DEFAULT_SUB_SHADOWRADIUS, 0, 0, VP.DEFAULT_SUB_SHADOWCOLOR); } private boolean isInitialized() { return (mCreated && vPlayer != null && vPlayer.isInitialized()); } private Handler mSubHandler = new Handler() { Bundle data; String text; byte[] pixels; int width = 0, height = 0; Bitmap bm = null; int oldType = SUBTITLE_TEXT; @Override public void handleMessage(Message msg) { data = msg.getData(); switch (msg.what) { case SUBTITLE_TEXT: if (oldType != SUBTITLE_TEXT) { mSubtitleImage.setVisibility(View.GONE); mSubtitleText.setVisibility(View.VISIBLE); oldType = SUBTITLE_TEXT; } text = data.getString(VP.SUB_TEXT_KEY); mSubtitleText.setText(text == null ? "" : text.trim()); break; case SUBTITLE_BITMAP: if (oldType != SUBTITLE_BITMAP) { mSubtitleText.setVisibility(View.GONE); mSubtitleImage.setVisibility(View.VISIBLE); oldType = SUBTITLE_BITMAP; } pixels = data.getByteArray(VP.SUB_PIXELS_KEY); if (bm == null || width != data.getInt(VP.SUB_WIDTH_KEY) || height != data.getInt(VP.SUB_HEIGHT_KEY)) { width = data.getInt(VP.SUB_WIDTH_KEY); height = data.getInt(VP.SUB_HEIGHT_KEY); bm = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); } if (pixels != null) bm.copyPixelsFromBuffer(ByteBuffer.wrap(pixels)); mSubtitleImage.setImageBitmap(bm); break; } } }; private AtomicBoolean mOpened = new AtomicBoolean(Boolean.FALSE); private boolean mSurfaceCreated = false; private boolean mServiceConnected = false; private Object mOpenLock = new Object(); private static final int OPEN_FILE = 0; private static final int OPEN_START = 1; private static final int OPEN_SUCCESS = 2; private static final int OPEN_FAILED = 3; private static final int HW_FAILED = 4; private static final int LOAD_PREFS = 5; private static final int BUFFER_START = 11; private static final int BUFFER_PROGRESS = 12; private static final int BUFFER_COMPLETE = 13; private static final int CLOSE_START = 21; private static final int CLOSE_COMPLETE = 22; private static final int SUBTITLE_TEXT = 0; private static final int SUBTITLE_BITMAP = 1; private Handler vPlayerHandler = new Handler() { @Override public void handleMessage(Message msg) { switch (msg.what) { case OPEN_FILE: synchronized (mOpenLock) { if (!mOpened.get() && vPlayer != null) { mOpened.set(true); vPlayer.setVPlayerListener(vPlayerListener); if (vPlayer.isInitialized()) mUri = vPlayer.getUri(); if (mVideoView != null) vPlayer.setDisplay(mVideoView.getHolder()); if (mUri != null) vPlayer.initialize(mUri, mDisplayName, mSaveUri, getStartPosition(), vPlayerListener, mParentId, mIsHWCodec); } } break; case OPEN_START: mVideoLoadingText.setText(R.string.video_layout_loading); setVideoLoadingLayoutVisibility(View.VISIBLE); break; case OPEN_SUCCESS: loadVPlayerPrefs(); setVideoLoadingLayoutVisibility(View.GONE); setVideoLayout(); vPlayer.start(); attachMediaController(); break; case OPEN_FAILED: resultFinish(RESULT_FAILED); break; case BUFFER_START: setVideoLoadingLayoutVisibility(View.VISIBLE); vPlayerHandler.sendEmptyMessageDelayed(BUFFER_PROGRESS, 1000); break; case BUFFER_PROGRESS: if (vPlayer.getBufferProgress() >= 100) { setVideoLoadingLayoutVisibility(View.GONE); } else { mVideoLoadingText.setText(getString( R.string.video_layout_buffering_progress, vPlayer.getBufferProgress())); vPlayerHandler.sendEmptyMessageDelayed(BUFFER_PROGRESS, 1000); stopPlayer(); } break; case BUFFER_COMPLETE: setVideoLoadingLayoutVisibility(View.GONE); vPlayerHandler.removeMessages(BUFFER_PROGRESS); break; case CLOSE_START: mVideoLoadingText.setText(R.string.closing_file); setVideoLoadingLayoutVisibility(View.VISIBLE); break; case CLOSE_COMPLETE: mCloseComplete = true; break; case HW_FAILED: if (mVideoView != null) { mVideoView.setVisibility(View.GONE); mVideoView.setVisibility(View.VISIBLE); mVideoView.initialize(VideoViewActivity.this, VideoViewActivity.this, false); } break; case LOAD_PREFS: loadVPlayerPrefs(); break; } } }; private void setVideoLoadingLayoutVisibility(int visibility) { if (mVideoLoadingLayout != null) { // if (visibility == View.VISIBLE) // mLoadingProgressView.startAnimation(mLoadingAnimation); mVideoLoadingLayout.setVisibility(visibility); } } private PlayerService.VPlayerListener vPlayerListener = new PlayerService.VPlayerListener() { @Override public void onHWRenderFailed() { if (Build.VERSION.SDK_INT < 11 && mIsHWCodec) { vPlayerHandler.sendEmptyMessage(HW_FAILED); vPlayerHandler.sendEmptyMessageDelayed(HW_FAILED, 200); } } @Override public void onSubChanged(String sub) { Message msg = new Message(); Bundle b = new Bundle(); b.putString(VP.SUB_TEXT_KEY, sub); msg.setData(b); msg.what = SUBTITLE_TEXT; mSubHandler.sendMessage(msg); } @Override public void onSubChanged(byte[] pixels, int width, int height) { Message msg = new Message(); Bundle b = new Bundle(); b.putByteArray(VP.SUB_PIXELS_KEY, pixels); b.putInt(VP.SUB_WIDTH_KEY, width); b.putInt(VP.SUB_HEIGHT_KEY, height); msg.setData(b); msg.what = SUBTITLE_BITMAP; mSubHandler.sendMessage(msg); } @Override public void onOpenStart() { vPlayerHandler.sendEmptyMessage(OPEN_START); } @Override public void onOpenSuccess() { vPlayerHandler.sendEmptyMessage(OPEN_SUCCESS); } @Override public void onOpenFailed() { vPlayerHandler.sendEmptyMessage(OPEN_FAILED); } @Override public void onBufferStart() { vPlayerHandler.sendEmptyMessage(BUFFER_START); stopPlayer(); } @Override public void onBufferComplete() { Log.i("VideoActivity#onBufferComplete " + vPlayer.needResume()); vPlayerHandler.sendEmptyMessage(BUFFER_COMPLETE); if (vPlayer != null && !vPlayer.needResume()) startPlayer(); } @Override public void onPlaybackComplete() { mEnd = true; if (mLoopCount == 0 || mLoopCount-- > 1) { vPlayer.start(); vPlayer.seekTo(0); } else { resultFinish(RESULT_OK); } } @Override public void onCloseStart() { vPlayerHandler.sendEmptyMessage(CLOSE_START); } @Override public void onCloseComplete() { vPlayerHandler.sendEmptyMessage(CLOSE_COMPLETE); } @Override public void onVideoSizeChanged(int width, int height) { if (mVideoView != null) { setVideoLayout(); } } @Override public void onDownloadRateChanged(int kbPerSec) { if (!MediaUtils.isNative(mUri.toString()) && mMediaController != null) { mMediaController.setDownloadRate(String.format("%dKB/s", kbPerSec)); } } }; private int mVideoMode = VideoView.VIDEO_LAYOUT_SCALE; private void setVideoLayout() { mVideoView.setVideoLayout(mVideoMode, VP.DEFAULT_ASPECT_RATIO, vPlayer.getVideoWidth(), vPlayer.getVideoHeight(), vPlayer.getVideoAspectRatio()); } private void savePosition() { if (vPlayer != null && mUri != null) { PreferenceUtils.put( mUri.toString(), StringUtils.generateTime((int) (0.5 + vPlayer .getCurrentPosition())) + " / " + StringUtils.generateTime(vPlayer.getDuration())); if (mEnd) PreferenceUtils .put(mUri + VP.SESSION_LAST_POSITION_SUFIX, 1.0f); else PreferenceUtils .put(mUri + VP.SESSION_LAST_POSITION_SUFIX, (float) (vPlayer.getCurrentPosition() / (double) vPlayer .getDuration())); } } private float getStartPosition() { if (mFromStart) return 1.1f; if (mStartPos <= 0.0f || mStartPos >= 1.0f) return PreferenceUtils.getFloat(mUri + VP.SESSION_LAST_POSITION_SUFIX, 7.7f); return mStartPos; } @Override public int getBufferPercentage() { if (isInitialized()) return (int) (vPlayer.getBufferProgress() * 100); return 0; } @Override public long getCurrentPosition() { if (isInitialized()) return vPlayer.getCurrentPosition(); return (long) (getStartPosition() * vPlayer.getDuration()); } @Override public long getDuration() { if (isInitialized()) return vPlayer.getDuration(); return 0; } @Override public boolean isPlaying() { if (isInitialized()) return vPlayer.isPlaying(); return false; } @Override public void pause() { if (isInitialized()) vPlayer.stop(); } @Override public void seekTo(long arg0) { if (isInitialized()) vPlayer.seekTo((float) ((double) arg0 / vPlayer.getDuration())); } @Override public void start() { if (isInitialized()) vPlayer.start(); } @Override public void previous() { } @Override public void next() { } private static final int VIDEO_MAXIMUM_HEIGHT = 2048; private static final int VIDEO_MAXIMUM_WIDTH = 2048; @Override public float scale(float scaleFactor) { float userRatio = VP.DEFAULT_ASPECT_RATIO; int videoWidth = vPlayer.getVideoWidth(); int videoHeight = vPlayer.getVideoHeight(); float videoRatio = vPlayer.getVideoAspectRatio(); float currentRatio = mVideoView.mVideoHeight / (float) videoHeight; currentRatio += (scaleFactor - 1); if (videoWidth * currentRatio >= VIDEO_MAXIMUM_WIDTH) currentRatio = VIDEO_MAXIMUM_WIDTH / (float) videoWidth; if (videoHeight * currentRatio >= VIDEO_MAXIMUM_HEIGHT) currentRatio = VIDEO_MAXIMUM_HEIGHT / (float) videoHeight; if (currentRatio < 0.5f) currentRatio = 0.5f; mVideoView.mVideoHeight = (int) (videoHeight * currentRatio); mVideoView.setVideoLayout(mVideoMode, userRatio, videoWidth, videoHeight, videoRatio); return currentRatio; } @SuppressLint("SimpleDateFormat") @Override public void snapshot() { if (!com.cjj.bb.utils.FileUtils.sdAvailable()) { ToastUtils.showToast(R.string.file_explorer_sdcard_not_available); } else { Uri imgUri = null; Bitmap bitmap = vPlayer.getCurrentFrame(); if (bitmap != null) { File screenshotsDirectory = new File( Environment .getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES) + VP.SNAP_SHOT_PATH); if (!screenshotsDirectory.exists()) { screenshotsDirectory.mkdirs(); } File savePath = new File( screenshotsDirectory.getPath() + "/" + new SimpleDateFormat("yyyyMMddHHmmss") .format(new Date()) + ".jpg"); if (ImageUtils.saveBitmap(savePath.getPath(), bitmap)) { imgUri = Uri.fromFile(savePath); } } if (imgUri != null) { sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, imgUri)); ToastUtils.showLongToast(getString( R.string.video_screenshot_save_in, imgUri.getPath())); } else { ToastUtils.showToast(R.string.video_screenshot_failed); } } } @Override public void toggleVideoMode(int mode) { mVideoMode = mode; setVideoLayout(); } @Override public void stop() { onBackPressed(); } @Override public long goForward() { return 0; } @Override public long goBack() { return 0; } @Override public void removeLoadingView() { mVideoLoadingLayout.setVisibility(View.GONE); } @Override public void onSurfaceCreated(SurfaceHolder holder) { Log.i("onSurfaceCreated"); mSurfaceCreated = true; if (mServiceConnected) vPlayerHandler.sendEmptyMessage(OPEN_FILE); if (vPlayer != null) vPlayer.setDisplay(holder); } @Override public void onSurfaceChanged(SurfaceHolder holder, int format, int width, int height) { if (vPlayer != null) { setVideoLayout(); } } @Override public void onSurfaceDestroyed(SurfaceHolder holder) { Log.i("onSurfaceDestroyed"); if (vPlayer != null && vPlayer.isInitialized()) { if (vPlayer.isPlaying()) { vPlayer.stop(); vPlayer.setState(PlayerService.STATE_NEED_RESUME); } vPlayer.releaseSurface(); if (vPlayer.needResume()) vPlayer.start(); } } @Override public void setDanmakushow(boolean isShow) { // TODO Auto-generated method stub } } ================================================ FILE: app/src/main/java/com/cjj/bb/adapter/AreaGridAdapter.java ================================================ package com.cjj.bb.adapter; import java.util.List; import android.app.Activity; import android.content.Context; import android.content.Intent; import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; import android.view.View.OnClickListener; import android.view.ViewGroup; import android.widget.BaseAdapter; import android.widget.ImageView; import android.widget.TextView; import com.cjj.bb.R; import com.cjj.bb.activity.DonghuaActivity; import com.cjj.bb.activity.TVActivity; import com.cjj.bb.model.AreaItem; public class AreaGridAdapter extends BaseAdapter{ private Context mContext; private List mList; public AreaGridAdapter(Context mContext,List mList){ this.mContext = mContext; this.mList = mList; } @Override public int getCount() { return mList.size(); } @Override public AreaItem getItem(int position) { return mList == null ? null : mList.get(position); } @Override public long getItemId(int position) { return position; } @Override public View getView(final int position, View convertView, ViewGroup parent) { AreaItem areaItem = getItem(position); convertView = LayoutInflater.from(mContext).inflate(R.layout.area_item, null); ImageView areaImageView = (ImageView) convertView.findViewById(R.id.areaImageView); TextView areaTextView = (TextView) convertView.findViewById(R.id.areaTextView); areaImageView.setImageResource(areaItem.getImg()); areaTextView.setText(areaItem.getText()); convertView.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { // 处理跳转逻辑 Intent i = new Intent(); i.putExtra("AreaType",position+1); if(position == 7){ i.setClass(mContext, TVActivity.class); }else{ i.setClass(mContext, DonghuaActivity.class); } mContext.startActivity(i); // 动画过渡 ((Activity) mContext).overridePendingTransition(R.anim.push_left_in, R.anim.push_no); } }); return convertView; } } ================================================ FILE: app/src/main/java/com/cjj/bb/adapter/ArrayAdapter.java ================================================ package com.cjj.bb.adapter; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.List; import android.content.Context; import android.view.LayoutInflater; import android.widget.BaseAdapter; public abstract class ArrayAdapter extends BaseAdapter { // 数据 protected ArrayList mObjects; protected LayoutInflater mInflater; protected final Object mLock = new Object(); public ArrayAdapter(final Context ctx, final ArrayList l) { mObjects = l == null ? new ArrayList() : l; mInflater = (LayoutInflater) ctx.getSystemService(Context.LAYOUT_INFLATER_SERVICE); } public ArrayAdapter(final Context ctx, final T... l) { mObjects = new ArrayList(); mObjects.addAll(Arrays.asList(l)); mInflater = (LayoutInflater) ctx.getSystemService(Context.LAYOUT_INFLATER_SERVICE); } public ArrayAdapter(final Context ctx, final List l) { mObjects = new ArrayList(); if (l != null) mObjects.addAll(l); mInflater = (LayoutInflater) ctx.getSystemService(Context.LAYOUT_INFLATER_SERVICE); } public ArrayAdapter(final Context ctx, final Collection l) { mObjects = new ArrayList(); if (l != null) mObjects.addAll(l); mInflater = (LayoutInflater) ctx.getSystemService(Context.LAYOUT_INFLATER_SERVICE); } @Override public int getCount() { return mObjects.size(); } @Override public T getItem(int position) { return mObjects.get(position); } @Override public long getItemId(int position) { return 0; } public void add(T item) { this.mObjects.add(item); } public void replace(ArrayList newObjects) { if (newObjects == null) newObjects = new ArrayList(); this.mObjects = newObjects; } /** * Adds the specified items at the end of the array. * * @param items The items to add at the end of the array. */ public void addAll(T... items) { ArrayList values = this.mObjects; for (T item : items) { values.add(item); } this.mObjects = values; } /** * * @param collection */ public void addAll(Collection collection) { mObjects.addAll(collection); } /** * Remove all elements from the list. */ public void clear() { mObjects.clear(); } /** * 获取所有数据 * * @return */ public final ArrayList getAll() { return mObjects; } } ================================================ FILE: app/src/main/java/com/cjj/bb/adapter/BankumiTabAdapter.java ================================================ package com.cjj.bb.adapter; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentManager; import android.support.v4.app.FragmentPagerAdapter; import com.cjj.bb.fragment.DonghuaFragment; /** * FragmentPager适配器 * * @author wwj_748 * @2014/8/9 */ public class BankumiTabAdapter extends FragmentPagerAdapter { // 内容标题 public static final String[] DONG_HUA_TITLE = new String[] { "连载动画", "完结动画", "动画资讯", "官方延伸", "国产动画" }; public BankumiTabAdapter(FragmentManager fm) { super(fm); // TODO Auto-generated constructor stub } // 获取项 @Override public Fragment getItem(int position) { System.out.println("Fragment position:" + position); switch (position) { case 0: return new DonghuaFragment(33); case 1: return new DonghuaFragment(32); case 2: return new DonghuaFragment(51); case 3: return new DonghuaFragment(152); case 4: return new DonghuaFragment(153); default: return new DonghuaFragment(33); } // MainFragment fragment = new MainFragment(position); // return fragment; } @Override public CharSequence getPageTitle(int position) { // 返回页面标题 return DONG_HUA_TITLE[position % DONG_HUA_TITLE.length].toUpperCase(); } @Override public int getCount() { // 页面个数 return DONG_HUA_TITLE.length; } } ================================================ FILE: app/src/main/java/com/cjj/bb/adapter/DianyingTabAdapter.java ================================================ package com.cjj.bb.adapter; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentManager; import android.support.v4.app.FragmentPagerAdapter; import com.cjj.bb.fragment.DonghuaFragment; /** * FragmentPager适配器 * * @author wwj_748 * @2014/8/9 */ public class DianyingTabAdapter extends FragmentPagerAdapter { // 内容标题 public static final String[] DONG_HUA_TITLE = new String[] { "全区动态", "欧美电影", "日本电影", "国产电影", "电影相关" }; public DianyingTabAdapter(FragmentManager fm) { super(fm); // TODO Auto-generated constructor stub } // 获取项 @Override public Fragment getItem(int position) { System.out.println("Fragment position:" + position); switch (position) { case 0: return new DonghuaFragment(23); case 1: return new DonghuaFragment(145); case 2: return new DonghuaFragment(146); case 3: return new DonghuaFragment(147); case 4: return new DonghuaFragment(82); default: return new DonghuaFragment(23); } // MainFragment fragment = new MainFragment(position); // return fragment; } @Override public CharSequence getPageTitle(int position) { // 返回页面标题 return DONG_HUA_TITLE[position % DONG_HUA_TITLE.length].toUpperCase(); } @Override public int getCount() { // 页面个数 return DONG_HUA_TITLE.length; } } ================================================ FILE: app/src/main/java/com/cjj/bb/adapter/DonghuaTabAdapter.java ================================================ package com.cjj.bb.adapter; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentManager; import android.support.v4.app.FragmentPagerAdapter; import com.cjj.bb.fragment.DonghuaFragment; /** * FragmentPager适配器 * * @author wwj_748 * @2014/8/9 */ public class DonghuaTabAdapter extends FragmentPagerAdapter { // 内容标题 public static final String[] DONG_HUA_TITLE = new String[] { "全区动态", "MAD·AMV", "MMD·3D", "动画短片", "综合" }; public DonghuaTabAdapter(FragmentManager fm) { super(fm); // TODO Auto-generated constructor stub } // 获取项 @Override public Fragment getItem(int position) { System.out.println("Fragment position:" + position); switch (position) { case 0: return new DonghuaFragment(1); case 1: return new DonghuaFragment(24); case 2: return new DonghuaFragment(25); case 3: return new DonghuaFragment(47); case 4: return new DonghuaFragment(27); default: return new DonghuaFragment(1); } // MainFragment fragment = new MainFragment(position); // return fragment; } @Override public CharSequence getPageTitle(int position) { // 返回页面标题 return DONG_HUA_TITLE[position % DONG_HUA_TITLE.length].toUpperCase(); } @Override public int getCount() { // 页面个数 return DONG_HUA_TITLE.length; } } ================================================ FILE: app/src/main/java/com/cjj/bb/adapter/GameListAdapter.java ================================================ package com.cjj.bb.adapter; import java.util.List; import android.app.Activity; import android.content.Context; import android.content.Intent; import android.net.Uri; import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; import android.view.View.OnClickListener; import android.view.ViewGroup; import android.widget.BaseAdapter; import android.widget.Button; import android.widget.ImageView; import android.widget.TextView; import com.cjj.bb.R; import com.cjj.bb.model.GameItem; import com.cjj.bb.utils.ToastUtils; public class GameListAdapter extends BaseAdapter{ private Context mContext; private List mList; GameItem gameItem; public GameListAdapter(Context mContext,List mList){ this.mContext = mContext; this.mList = mList; } @Override public int getCount() { return mList.size(); } @Override public GameItem getItem(int position) { return mList == null ? null : mList.get(position); } @Override public long getItemId(int position) { return position; } @Override public View getView(final int position, View convertView, ViewGroup parent) { gameItem = getItem(position); convertView = LayoutInflater.from(mContext).inflate(R.layout.game_list_item, null); ImageView gameImageView = (ImageView) convertView.findViewById(R.id.game_item_image); TextView gameTextView = (TextView) convertView.findViewById(R.id.game_item_title); Button gameButton = (Button) convertView.findViewById(R.id.GameButton); gameImageView.setImageResource(gameItem.getImg()); gameTextView.setText(gameItem.getText()); gameButton.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { // 处理跳转逻辑 Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(mList.get(position).getPath())); ToastUtils.showToast("(`・ω・´)转跳到" + mList.get(position).getText() + "官网"); //i.setClass(mContext, DonghuaActivity.class); mContext.startActivity(intent); // 动画过渡 ((Activity) mContext).overridePendingTransition(R.anim.push_left_in,R.anim.push_no); } }); return convertView; } } ================================================ FILE: app/src/main/java/com/cjj/bb/adapter/GridAdapter.java ================================================ package com.cjj.bb.adapter; import java.util.List; import com.cjj.bb.R; import com.cjj.bb.activity.VideoInfoActivity; import com.cjj.bb.model.VideoItem; import com.nostra13.universalimageloader.core.ImageLoader; import android.app.Activity; import android.content.Context; import android.content.Intent; import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; import android.view.View.OnClickListener; import android.view.ViewGroup; import android.widget.BaseAdapter; import android.widget.ImageView; import android.widget.TextView; public class GridAdapter extends BaseAdapter{ private Context mContext; private List mList; private ImageLoader mImageLoader; public GridAdapter(Context mContext,List mList,ImageLoader mImageLoader){ this.mContext = mContext; this.mList = mList; this.mImageLoader = mImageLoader; } @Override public int getCount() { return mList.size(); } @Override public VideoItem getItem(int position) { return mList == null ? null : mList.get(position); } @Override public long getItemId(int position) { return position; } @Override public View getView(final int position, View convertView, ViewGroup parent) { ViewHolder mHolder; VideoItem videoitem = getItem(position); if(convertView == null){ convertView = LayoutInflater.from(mContext).inflate(R.layout.homepage_item, null); mHolder = new ViewHolder(); mHolder.icon = (ImageView) convertView.findViewById(R.id.list_item_image); mHolder.msg = (TextView) convertView.findViewById(R.id.list_item_title); mHolder.bofang = (TextView) convertView.findViewById(R.id.BangumiImageView_baofang); mHolder.danmagu = (TextView) convertView.findViewById(R.id.BangumiImageView_danmugu); convertView.setTag(mHolder); }else{ mHolder = (ViewHolder) convertView.getTag(); } mImageLoader.displayImage(videoitem.getPic(), mHolder.icon); mHolder.msg.setText(videoitem.getTitle()); mHolder.bofang.setText(videoitem.getPlay()); mHolder.danmagu.setText(videoitem.getVideo_review()); convertView.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { // 处理跳转逻辑 VideoItem item = (VideoItem) mList.get(position); Intent i = new Intent(); Bundle bundle = new Bundle(); bundle.putSerializable("videoItemdata", item); i.setClass(mContext, VideoInfoActivity.class); i.putExtras(bundle); mContext.startActivity(i); // 动画过渡 ((Activity) mContext).overridePendingTransition(R.anim.push_left_in, R.anim.push_no); } }); return convertView; } private class ViewHolder{ private ImageView icon; private TextView msg; private TextView bofang; private TextView danmagu; } } ================================================ FILE: app/src/main/java/com/cjj/bb/adapter/ItemsAdapter.java ================================================ package com.cjj.bb.adapter; import android.app.Activity; import android.content.Context; import android.content.res.Resources; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.util.DisplayMetrics; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ArrayAdapter; import android.widget.FrameLayout; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.TextView; import com.cjj.bb.R; public class ItemsAdapter extends ArrayAdapter{ Context context; LayoutInflater inflater; String[] texts; int layoutResourceId; float imageWidth; public ItemsAdapter(Context context, int layoutResourceId, Integer[] items,String[] texts) { super(context, layoutResourceId, items); this.context = context; this.layoutResourceId = layoutResourceId; this.texts = texts; float width = ((Activity)context).getWindowManager().getDefaultDisplay().getWidth(); float margin = (int)convertDpToPixel(10f, (Activity)context); // two images, three margins of 10dips imageWidth = ((width - (3 * margin)) / 2); } @Override public View getView(int position, View convertView, ViewGroup parent) { LinearLayout row = (LinearLayout) convertView; ItemHolder holder; Integer item = getItem(position); if (row == null) { holder = new ItemHolder(); inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); row = (LinearLayout) inflater.inflate(layoutResourceId, parent, false); ImageView itemImage = (ImageView)row.findViewById(R.id.item_image); TextView itemText = (TextView)row.findViewById(R.id.bankumi_item_title); holder.itemImage = itemImage; holder.itemText = itemText; } else { holder = (ItemHolder) row.getTag(); } row.setTag(holder); setImageBitmap(item, holder.itemImage); holder.itemText.setText(texts[position]); return row; } public static class ItemHolder { ImageView itemImage; TextView itemText; } // resize the image proportionately so it fits the entire space private void setImageBitmap(Integer item, ImageView imageView){ Bitmap bitmap = BitmapFactory.decodeResource(getContext().getResources(), item); float i = ((float) imageWidth) / ((float) bitmap.getWidth()); float imageHeight = i * (bitmap.getHeight()); LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) imageView.getLayoutParams(); params.height = (int) imageHeight; params.width = (int) imageWidth; imageView.setLayoutParams(params); imageView.setImageResource(item); } public static float convertDpToPixel(float dp, Context context){ Resources resources = context.getResources(); DisplayMetrics metrics = resources.getDisplayMetrics(); float px = dp * (metrics.densityDpi/160f); return px; } } ================================================ FILE: app/src/main/java/com/cjj/bb/adapter/KejiTabAdapter.java ================================================ package com.cjj.bb.adapter; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentManager; import android.support.v4.app.FragmentPagerAdapter; import com.cjj.bb.fragment.DonghuaFragment; /** * FragmentPager适配器 * * @author wwj_748 * @2014/8/9 */ public class KejiTabAdapter extends FragmentPagerAdapter { // 内容标题 public static final String[] DONG_HUA_TITLE = new String[] { "全区动态", "纪录片", "科普人文", "野生技术", "公开课" , "军事", "数码"}; public KejiTabAdapter(FragmentManager fm) { super(fm); // TODO Auto-generated constructor stub } // 获取项 @Override public Fragment getItem(int position) { System.out.println("Fragment position:" + position); switch (position) { case 0: return new DonghuaFragment(36); case 1: return new DonghuaFragment(37); case 2: return new DonghuaFragment(124); case 3: return new DonghuaFragment(122); case 4: return new DonghuaFragment(39); case 5: return new DonghuaFragment(96); case 6: return new DonghuaFragment(95); default: return new DonghuaFragment(36); } // MainFragment fragment = new MainFragment(position); // return fragment; } @Override public CharSequence getPageTitle(int position) { // 返回页面标题 return DONG_HUA_TITLE[position % DONG_HUA_TITLE.length].toUpperCase(); } @Override public int getCount() { // 页面个数 return DONG_HUA_TITLE.length; } } ================================================ FILE: app/src/main/java/com/cjj/bb/adapter/MainTabAdapter.java ================================================ package com.cjj.bb.adapter; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentManager; import android.support.v4.app.FragmentPagerAdapter; import com.cjj.bb.fragment.BangumiFragment; import com.cjj.bb.fragment.DonghuaFragment; import com.cjj.bb.fragment.FragmentLogin; import com.cjj.bb.fragment.FramentTime; import com.cjj.bb.fragment.GamesCenterFragment; import com.cjj.bb.fragment.HomePageFragment2; import com.cjj.bb.fragment.SubareaFragment; /** * FragmentPager适配器 * * @author wwj_748 * @2014/8/9 */ public class MainTabAdapter extends FragmentPagerAdapter { // 内容标题 public static final String[] DONG_HUA_TITLE = new String[] { "个人中心","首页", "分区导航", "新番专题", "游戏中心","放松时间表" }; public HomePageFragment2 homepage = new HomePageFragment2(); public SubareaFragment subarea = new SubareaFragment(); public MainTabAdapter(FragmentManager fm) { super(fm); // TODO Auto-generated constructor stub } // 获取项 @Override public Fragment getItem(int position) { System.out.println("Fragment position:" + position); switch (position) { case 0: return new FragmentLogin(); case 1: return homepage; case 2: return subarea; case 3: return new BangumiFragment(); case 4: return new GamesCenterFragment(); case 5: return new FramentTime(); default: return new DonghuaFragment(33); } // MainFragment fragment = new MainFragment(position); // return fragment; } @Override public CharSequence getPageTitle(int position) { // 返回页面标题 return DONG_HUA_TITLE[position % DONG_HUA_TITLE.length].toUpperCase(); } @Override public int getCount() { // 页面个数 return DONG_HUA_TITLE.length; } } ================================================ FILE: app/src/main/java/com/cjj/bb/adapter/MusicTabAdapter.java ================================================ package com.cjj.bb.adapter; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentManager; import android.support.v4.app.FragmentPagerAdapter; import com.cjj.bb.fragment.DonghuaFragment; /** * FragmentPager适配器 * * @author wwj_748 * @2014/8/9 */ public class MusicTabAdapter extends FragmentPagerAdapter { // 内容标题 public static final String[] DONG_HUA_TITLE = new String[] { "全区动态", "翻唱", "VOCALOID", "演奏", "音乐选集"}; public MusicTabAdapter(FragmentManager fm) { super(fm); // TODO Auto-generated constructor stub } // 获取项 @Override public Fragment getItem(int position) { System.out.println("Fragment position:" + position); switch (position) { case 0: return new DonghuaFragment(3); case 1: return new DonghuaFragment(31); case 2: return new DonghuaFragment(30); case 3: return new DonghuaFragment(59); case 4: return new DonghuaFragment(130); default: return new DonghuaFragment(3); } // MainFragment fragment = new MainFragment(position); // return fragment; } @Override public CharSequence getPageTitle(int position) { // 返回页面标题 return DONG_HUA_TITLE[position % DONG_HUA_TITLE.length].toUpperCase(); } @Override public int getCount() { // 页面个数 return DONG_HUA_TITLE.length; } } ================================================ FILE: app/src/main/java/com/cjj/bb/adapter/RankAdapter.java ================================================ package com.cjj.bb.adapter; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentManager; import android.support.v4.app.FragmentPagerAdapter; import com.cjj.bb.fragment.RankFragment; /** * FragmentPager适配器 * * @author wwj_748 * @2014/8/9 */ public class RankAdapter extends FragmentPagerAdapter { // 内容标题 public static final String[] DONG_HUA_TITLE = new String[] { "全区", "新番", "动画", "音乐", "游戏", "科学", "娱乐", "电影" }; public RankAdapter(FragmentManager fm) { super(fm); // TODO Auto-generated constructor stub } // 获取项 @Override public Fragment getItem(int position) { System.out.println("Fragment position:" + position); switch (position) { case 0: return new RankFragment(10070); case 1: return new RankFragment(100733); case 2: return new RankFragment(10071); case 3: return new RankFragment(10073); case 4: return new RankFragment(10074); case 5: return new RankFragment(100736); case 6: return new RankFragment(10075); case 7: return new RankFragment(100723); default: return new RankFragment(1); } // MainFragment fragment = new MainFragment(position); // return fragment; } @Override public CharSequence getPageTitle(int position) { // 返回页面标题 return DONG_HUA_TITLE[position % DONG_HUA_TITLE.length].toUpperCase(); } @Override public int getCount() { // 页面个数 return DONG_HUA_TITLE.length; } } ================================================ FILE: app/src/main/java/com/cjj/bb/adapter/VideoInfoListAdapter.java ================================================ package com.cjj.bb.adapter; import java.util.List; import android.app.Activity; import android.content.Context; import android.content.Intent; import android.view.LayoutInflater; import android.view.View; import android.view.View.OnClickListener; import android.view.ViewGroup; import android.widget.BaseAdapter; import android.widget.TextView; import com.cjj.bb.R; import com.cjj.bb.activity.BiliVideoViewActivity; public class VideoInfoListAdapter extends BaseAdapter{ private Context mContext; private List mList; String videoItem; String av; String page; public VideoInfoListAdapter(Context mContext,List mList,String av){ this.mContext = mContext; this.mList = mList; this.av = av; } @Override public int getCount() { return mList.size(); } @Override public String getItem(int position) { return mList == null ? null : mList.get(position); } @Override public long getItemId(int position) { return position; } @Override public View getView(final int position, View convertView, ViewGroup parent) { videoItem = getItem(position); convertView = LayoutInflater.from(mContext).inflate(R.layout.video_info_list_item, null); TextView titleTextView = (TextView) convertView.findViewById(R.id.title); View itemView = convertView.findViewById(R.id.linearlayout_row); titleTextView.setText(mList.get(position)); itemView.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { // 处理跳转逻辑 //ToastUtils.showToast("(`・ω・´) "+mList.get(position)); page = String.valueOf(position+1); //i.setClass(mContext, DonghuaActivity.class); //mContext.startActivity(intent); // 动画过渡 //((Activity) mContext).overridePendingTransition(R.anim.push_left_in,R.anim.push_no); Intent intent = new Intent(mContext, BiliVideoViewActivity.class); intent.putExtra("displayName",mList.get(position)); intent.putExtra("av",av); intent.putExtra("page",page); mContext.startActivity(intent); ((Activity) mContext).overridePendingTransition(R.anim.push_left_in,R.anim.push_no); } }); return convertView; } } ================================================ FILE: app/src/main/java/com/cjj/bb/adapter/VideoListAdapter.java ================================================ package com.cjj.bb.adapter; import java.util.ArrayList; import java.util.List; import android.content.Context; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; import android.widget.ImageView; import android.widget.TextView; import com.cjj.bb.R; import com.cjj.bb.model.VideoItem; import com.nostra13.universalimageloader.core.DisplayImageOptions; import com.nostra13.universalimageloader.core.ImageLoader; import com.nostra13.universalimageloader.core.ImageLoaderConfiguration; import com.nostra13.universalimageloader.core.display.RoundedBitmapDisplayer; /** * 视频列表适配器 * * @author wwj_748 * @date 2012/8/9 */ public class VideoListAdapter extends BaseAdapter { private ViewHolder holder; // 视图容器 private LayoutInflater layoutInflater; // 布局加载器 private Context context; // 上下文对象 private List list; // 博客列表 private ImageLoader imageLoader = ImageLoader.getInstance();// 得到图片加载器 private DisplayImageOptions options; // 显示图像设置 public VideoListAdapter(Context context) { super(); this.context = context; layoutInflater = LayoutInflater.from(context); list = new ArrayList(); // 图片加载器初始化 imageLoader.init(ImageLoaderConfiguration.createDefault(context)); // 使用DisplayImageOptions.Builder()创建DisplayImageOptions options = new DisplayImageOptions.Builder() .showStubImage(R.drawable.bili_default_image_tv_with_bg) // 设置图片下载期间显示的图片 .showImageForEmptyUri(R.drawable.bili_default_image_tv_with_bg) // 设置图片Uri为空或是错误的时候显示的图片 .showImageOnFail(R.drawable.bili_default_image_tv_with_bg) // 设置图片加载或解码过程中发生错误显示的图片 .cacheInMemory() // 设置下载的图片是否缓存在内存中 .cacheOnDisc() // 设置下载的图片是否缓存在SD卡中 .displayer(new RoundedBitmapDisplayer(1)) // 设置成圆角图片 .build(); // 创建配置过得DisplayImageOption对象 } public void setList(List list) { this.list = list; } public void addList(List list) { this.list.addAll(list); } public void clearList() { this.list.clear(); } public List getList() { return list; } public void removeItem(int position) { if (list.size() > 0) { list.remove(position); } } @Override public int getCount() { return list.size(); } @Override public Object getItem(int position) { return list.get(position); } @Override public long getItemId(int position) { return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { if (convertView == null ) { // 装载布局文件blog_list_item.xml convertView = layoutInflater.inflate(R.layout.video_list_item, null); holder = new ViewHolder(); // holder.id = (TextView) convertView.findViewById(R.id.id); holder.title = (TextView) convertView.findViewById(R.id.list_item_title); holder.uptext = (TextView) convertView.findViewById(R.id.TextView_up); holder.bofangtext = (TextView) convertView.findViewById(R.id.TextView_bofang); holder.img = (ImageView) convertView.findViewById(R.id.list_item_image); convertView.setTag(holder); // 表示给View添加一个格外的数据, } else { holder = (ViewHolder) convertView.getTag();// 通过getTag的方法将数据取出来 } VideoItem item = list.get(position); // 获取当前数据 if (item != null) { // 显示标题内容 holder.title.setText(item.getTitle()); holder.uptext.setText("UP主:"+item.getAuthor()); holder.bofangtext.setText("播放:"+item.getPlay()); if (item.getPic() != null) { holder.img.setVisibility(View.VISIBLE); // 异步加载图片 imageLoader .displayImage(item.getPic(), holder.img, options); } else { // holder.img.setVisibility(View.VISIBLE); } } return convertView; } private class ViewHolder { TextView title; ImageView img; TextView uptext; TextView bofangtext; } } ================================================ FILE: app/src/main/java/com/cjj/bb/adapter/YouxiTabAdapter.java ================================================ package com.cjj.bb.adapter; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentManager; import android.support.v4.app.FragmentPagerAdapter; import com.cjj.bb.fragment.DonghuaFragment; /** * FragmentPager适配器 * * @author wwj_748 * @2014/8/9 */ public class YouxiTabAdapter extends FragmentPagerAdapter { // 内容标题 public static final String[] DONG_HUA_TITLE = new String[] { "全区动态", "单机联机", "网络游戏", "电子竞技" }; public YouxiTabAdapter(FragmentManager fm) { super(fm); // TODO Auto-generated constructor stub } // 获取项 @Override public Fragment getItem(int position) { System.out.println("Fragment position:" + position); switch (position) { case 0: return new DonghuaFragment(4); case 1: return new DonghuaFragment(17); case 2: return new DonghuaFragment(65); case 3: return new DonghuaFragment(60); default: return new DonghuaFragment(4); } // MainFragment fragment = new MainFragment(position); // return fragment; } @Override public CharSequence getPageTitle(int position) { // 返回页面标题 return DONG_HUA_TITLE[position % DONG_HUA_TITLE.length].toUpperCase(); } @Override public int getCount() { // 页面个数 return DONG_HUA_TITLE.length; } } ================================================ FILE: app/src/main/java/com/cjj/bb/adapter/YuleTabAdapter.java ================================================ package com.cjj.bb.adapter; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentManager; import android.support.v4.app.FragmentPagerAdapter; import com.cjj.bb.fragment.DonghuaFragment; /** * FragmentPager适配器 * * @author wwj_748 * @2014/8/9 */ public class YuleTabAdapter extends FragmentPagerAdapter { // 内容标题 public static final String[] DONG_HUA_TITLE = new String[] { "全区动态", "搞笑", "生活", "综艺"}; public YuleTabAdapter(FragmentManager fm) { super(fm); // TODO Auto-generated constructor stub } // 获取项 @Override public Fragment getItem(int position) { System.out.println("Fragment position:" + position); switch (position) { case 0: return new DonghuaFragment(5); case 1: return new DonghuaFragment(138); case 2: return new DonghuaFragment(21); case 3: return new DonghuaFragment(71); default: return new DonghuaFragment(5); } // MainFragment fragment = new MainFragment(position); // return fragment; } @Override public CharSequence getPageTitle(int position) { // 返回页面标题 return DONG_HUA_TITLE[position % DONG_HUA_TITLE.length].toUpperCase(); } @Override public int getCount() { // 页面个数 return DONG_HUA_TITLE.length; } } ================================================ FILE: app/src/main/java/com/cjj/bb/fragment/BangumiFragment.java ================================================ package com.cjj.bb.fragment; import android.os.Bundle; import android.support.annotation.Nullable; import android.support.v4.app.Fragment; import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; import android.view.View.OnTouchListener; import android.widget.AbsListView; import android.widget.ListView; import android.widget.AbsListView.OnScrollListener; import com.cjj.bb.R; import com.cjj.bb.adapter.ItemsAdapter; public class BangumiFragment extends Fragment{ private ListView listViewLeft; private ListView listViewRight; private ItemsAdapter leftAdapter; private ItemsAdapter rightAdapter; int[] leftViewsHeights; int[] rightViewsHeights; @Override public void onCreate(Bundle savedInstanceState) { // TODO Auto-generated method stub super.onCreate(savedInstanceState); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View rootView = inflater.inflate(R.layout.items_list, container, false); listViewLeft = (ListView) rootView.findViewById(R.id.list_view_left); listViewRight = (ListView) rootView.findViewById(R.id.list_view_right); loadItems(); listViewLeft.setOnTouchListener(touchListener); listViewRight.setOnTouchListener(touchListener); listViewLeft.setOnScrollListener(scrollListener); listViewRight.setOnScrollListener(scrollListener); return rootView; } // Passing the touch event to the opposite list OnTouchListener touchListener = new OnTouchListener() { boolean dispatched = false; @Override public boolean onTouch(View v, MotionEvent event) { if (v.equals(listViewLeft) && !dispatched) { dispatched = true; listViewRight.dispatchTouchEvent(event); } else if (v.equals(listViewRight) && !dispatched) { dispatched = true; listViewLeft.dispatchTouchEvent(event); } dispatched = false; return false; } }; /** * Synchronizing scrolling * Distance from the top of the first visible element opposite list: * sum_heights(opposite invisible screens) - sum_heights(invisible screens) + distance from top of the first visible child */ OnScrollListener scrollListener = new OnScrollListener() { @Override public void onScrollStateChanged(AbsListView v, int scrollState) { } @Override public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { if (view.getChildAt(0) != null) { if (view.equals(listViewLeft) ){ leftViewsHeights[view.getFirstVisiblePosition()] = view.getChildAt(0).getHeight(); int h = 0; for (int i = 0; i < listViewRight.getFirstVisiblePosition(); i++) { h += rightViewsHeights[i]; } int hi = 0; for (int i = 0; i < listViewLeft.getFirstVisiblePosition(); i++) { hi += leftViewsHeights[i]; } int top = h - hi + view.getChildAt(0).getTop(); listViewRight.setSelectionFromTop(listViewRight.getFirstVisiblePosition(), top); } else if (view.equals(listViewRight)) { rightViewsHeights[view.getFirstVisiblePosition()] = view.getChildAt(0).getHeight(); int h = 0; for (int i = 0; i < listViewLeft.getFirstVisiblePosition(); i++) { h += leftViewsHeights[i]; } int hi = 0; for (int i = 0; i < listViewRight.getFirstVisiblePosition(); i++) { hi += rightViewsHeights[i]; } int top = h - hi + view.getChildAt(0).getTop(); listViewLeft.setSelectionFromTop(listViewLeft.getFirstVisiblePosition(), top); } } } }; private void loadItems(){ Integer[] leftItems = new Integer[]{R.drawable.c1, R.drawable.c2, R.drawable.c3, R.drawable.c4, R.drawable.c5}; Integer[] rightItems = new Integer[]{R.drawable.c6, R.drawable.c7, R.drawable.c8, R.drawable.c9, R.drawable.c10}; String[] lefttexts = new String[]{"御神乐学园组曲","摸索吧!部活剧 第三季","怪盗JOKER 第二季","SHOW BY ROCK!!","雨色可可"}; String[] righttexts = new String[]{"攻壳机动队ARISE ALTERNATIVE ARCHITECTURE","亚尔斯兰战记","JOJO的奇妙冒险", "黑子的篮球 第三季","可塑性记忆"}; leftAdapter = new ItemsAdapter(getActivity(), R.layout.item, leftItems,lefttexts); rightAdapter = new ItemsAdapter(getActivity(), R.layout.item, rightItems,righttexts); listViewLeft.setAdapter(leftAdapter); listViewRight.setAdapter(rightAdapter); leftViewsHeights = new int[leftItems.length]; rightViewsHeights = new int[rightItems.length]; } } ================================================ FILE: app/src/main/java/com/cjj/bb/fragment/BroadcastTimetableFragment.java ================================================ package com.cjj.bb.fragment; import android.support.v4.app.Fragment; public class BroadcastTimetableFragment extends Fragment{ } ================================================ FILE: app/src/main/java/com/cjj/bb/fragment/DonghuaFragment.java ================================================ package com.cjj.bb.fragment; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.List; import java.util.Locale; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import android.content.Intent; import android.os.AsyncTask; import android.os.Bundle; import android.support.v4.app.Fragment; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.AbsListView; import android.widget.AdapterView; import android.widget.AdapterView.OnItemClickListener; import android.widget.LinearLayout; import android.widget.ListView; import android.widget.Toast; import com.cjj.bb.R; import com.cjj.bb.activity.VideoInfoActivity; import com.cjj.bb.adapter.VideoListAdapter; import com.cjj.bb.model.Page; import com.cjj.bb.model.VideoItem; import com.cjj.bb.utils.Constants; import com.cjj.bb.utils.HttpUtil; import com.cjj.bb.utils.URLUtil; /** * Fragment页面 * * @author wwj_748 * @date 2014/8/9 */ public class DonghuaFragment extends Fragment implements AbsListView.OnScrollListener { private ListView videoListView;// 视频列表 private View noBlogView; // 无数据时显示 private VideoListAdapter adapter;// 列表适配器 private List templist; private boolean isLoad = false; // 是否加载 private int videoType = 1; // 视频类别 private Page page; // 页面引用 private LinearLayout ll_loading; private String refreshDate = ""; // 刷新日期 public DonghuaFragment(int videoType) { this.videoType = videoType; } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); init(); } // @Override public void onActivityCreated(Bundle savedInstanceState) { templist = new ArrayList(); VideoItem tempItem = new VideoItem(); // tempItem.setAid("7"); // tempItem.setTitle("[示例数据]童年动画主题曲"); // tempItem.setPic("http://i0.hdslb.com/320_180/u_user/53cb3e2f7f3efd6464b82c91ea9a1236.jpg"); // tempItem.setAuthor("根号⑨"); // tempItem.setPlay("23333"); // templist.add(tempItem); initComponent(); if (isLoad == false) { isLoad = true; // 加载数据库中的数据 List list = templist; adapter.setList(list); adapter.notifyDataSetChanged(); // videoListView.startRefresh(); // 开始刷新 new MainTask().execute(URLUtil.getRefreshBlogListURL(videoType), "refresh"); } else { // videoListView.NotRefreshAtBegin(); // 不开始刷新 } super.onActivityCreated(savedInstanceState); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { Log.e("NewsFrag", "onCreateView"); return inflater.inflate(R.layout.fragment_donghua, null); } // 初始化 private void init() { adapter = new VideoListAdapter(getActivity()); page = new Page(); page.setPageStart(); } // 初始化组件 private void initComponent() { ll_loading = (LinearLayout) getView().findViewById(R.id.ll_loading); videoListView = (ListView) getView().findViewById(R.id.videoListView); videoListView.setAdapter(adapter);// 设置适配器 videoListView.setOnScrollListener(this); // videoListView.setPullRefreshEnable(this);// 设置可下拉刷新 // videoListView.setPullLoadEnable(this);// 设置可上拉加载 // 设置列表项点击事件 videoListView.setOnItemClickListener(new OnItemClickListener() { @Override public void onItemClick(AdapterView parent, View view, int position, long id) { // 获得博客列表项 VideoItem item = (VideoItem) adapter.getItem(position - 1); Intent i = new Intent(); Bundle bundle = new Bundle(); bundle.putSerializable("videoItemdata", item); i.setClass(getActivity(), VideoInfoActivity.class); i.putExtras(bundle); startActivity(i); // 动画过渡 getActivity().overridePendingTransition(R.anim.push_left_in, R.anim.push_no); } }); noBlogView = getView().findViewById(R.id.noBlogLayout); } @Override public void onScrollStateChanged(AbsListView view, int scrollState) { } /** * 处理listView加载更多 * @param view * @param firstVisibleItem * @param visibleItemCount * @param totalItemCount */ private int mListViewPreLast = 0; @Override public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { final int lastItem = firstVisibleItem + visibleItemCount; if (lastItem == totalItemCount) { if (mListViewPreLast != lastItem) { /**防止多次调用*/ new MainTask() .execute( URLUtil.getVideoListURL(videoType), "load"); mListViewPreLast = lastItem; } } } private class MainTask extends AsyncTask { @Override protected Integer doInBackground(String... params) { List list=new ArrayList(); try { JSONObject donghuajson = new JSONObject(HttpUtil.getHtmlString(params[0])); //动画数据解析 JSONArray dougaarray=donghuajson.getJSONArray("list"); for (int i=0;i", "--->"+item.getTitle()); } } catch (JSONException e) { // TODO Auto-generated catch block e.printStackTrace(); return Constants.DEF_RESULT_CODE.ERROR; } // // 获取网页json数据 // String temp = HttpUtil.httpGet(params[0]); // if (temp == null) { // return Constants.DEF_RESULT_CODE.ERROR; // } // // 解析json获取列表 // List list = JsoupUtil.getBlogItemList(blogType, temp); if (list.size() == 0) { return Constants.DEF_RESULT_CODE.NO_DATA; } // 刷新动作 if (params[1].equals("refresh")) { adapter.setList(list); return Constants.DEF_RESULT_CODE.REFRESH; } else {// 加载更多 adapter.addList(list); return Constants.DEF_RESULT_CODE.LOAD; } } @Override protected void onPostExecute(Integer result) { // 通知列表数据更新 adapter.notifyDataSetChanged(); switch (result) { case Constants.DEF_RESULT_CODE.ERROR: // 错误 Toast.makeText(getActivity(), "网络信号不佳", Toast.LENGTH_LONG).show(); // videoListView.stopRefresh(getDate()); // videoListView.stopLoadMore(); break; case Constants.DEF_RESULT_CODE.NO_DATA: // 无数据 // Toast.makeText(getActivity(), "无更多加载内容", Toast.LENGTH_LONG) // .show(); // videoListView.stopLoadMore(); // noBlogView.setVisibility(View.VISIBLE); // 显示无博客 break; case Constants.DEF_RESULT_CODE.REFRESH: // 刷新 // videoListView.stopRefresh(getDate()); ll_loading.setVisibility(View.GONE); if (adapter.getCount() == 0) { noBlogView.setVisibility(View.VISIBLE); // 显示无博客 } break; case Constants.DEF_RESULT_CODE.LOAD: // videoListView.stopLoadMore(); page.addPage(); if (adapter.getCount() == 0) { noBlogView.setVisibility(View.VISIBLE); // 显示无博客 } break; default: break; } super.onPostExecute(result); } } // // 加载更多时调用 // @Override // public void onLoadMore() { // System.out.println("loadmore"); // new MainTask() // .execute( // URLUtil.getVideoListURL(videoType), // "load"); // } // // @Override // public void onRefresh() { // System.out.println("refresh"); // page.setPageStart(); // new MainTask().execute(URLUtil.getRefreshBlogListURL(videoType), // "refresh"); // } public String getDate() { SimpleDateFormat sdf = new SimpleDateFormat("MM月dd日 HH:mm", Locale.CHINA); return sdf.format(new java.util.Date()); } } ================================================ FILE: app/src/main/java/com/cjj/bb/fragment/FragmentLogin.java ================================================ package com.cjj.bb.fragment; import android.os.Bundle; import android.support.annotation.Nullable; import android.support.v4.app.Fragment; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ImageView; import com.cjj.bb.R; /** * Created by Administrator on 2015/5/26. */ public class FragmentLogin extends Fragment { @Nullable @Override public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { ImageView iv = new ImageView(getActivity()); iv.setImageResource(R.drawable.login); return iv; } } ================================================ FILE: app/src/main/java/com/cjj/bb/fragment/FramentTime.java ================================================ package com.cjj.bb.fragment; import android.os.Bundle; import android.support.annotation.Nullable; import android.support.v4.app.Fragment; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ImageView; import com.cjj.bb.R; /** * Created by Administrator on 2015/5/26. */ public class FramentTime extends Fragment { @Nullable @Override public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { ImageView iv = new ImageView(getActivity()); iv.setImageResource(R.drawable.time); return iv; } } ================================================ FILE: app/src/main/java/com/cjj/bb/fragment/GamesCenterFragment.java ================================================ package com.cjj.bb.fragment; import android.os.Bundle; import android.support.v4.app.Fragment; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.GridView; import android.widget.ListView; import com.cjj.bb.R; import com.cjj.bb.adapter.GameListAdapter; import com.cjj.bb.model.GameItem; import java.util.ArrayList; public class GamesCenterFragment extends Fragment{ private ListView gameListView; private ArrayList gameList = new ArrayList(); private int[] gameimages = new int[]{R.drawable.hxzj_gamecenter_smallbanner,R.drawable.wcat_list, R.drawable.xwy_list,R.drawable.mlk,R.drawable.img_bh2, R.drawable.w}; private String[] gametexts = new String[]{"幻想战姬","白猫计划","侠物语","梅露可物语","崩坏学院2","世界2"}; private String[] gamepaths = new String[]{"http://hxzj.biligame.com/","http://bmjh.biligame.com/", "http://xwy.biligame.com/","http://mlk.biligame.com/","http://teos2.biligame.com/", "http://sj2.biligame.com/"}; @Override public void onCreate(Bundle savedInstanceState) { // TODO Auto-generated method stub super.onCreate(savedInstanceState); for (int i = 0; i < gameimages.length; i++) { GameItem item = new GameItem(); item.setImg(gameimages[i]); item.setText(gametexts[i]); item.setPath(gamepaths[i]); gameList.add(item); } } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View rootView = inflater.inflate(R.layout.fragment_gamecenter, container, false); gameListView = (ListView)rootView.findViewById(R.id.GameListView); gameListView.setAdapter(new GameListAdapter(getActivity(), gameList)); return rootView; } } ================================================ FILE: app/src/main/java/com/cjj/bb/fragment/HomePageFragment.java ================================================ package com.cjj.bb.fragment; import java.io.File; import java.util.ArrayList; import java.util.List; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import com.cjj.bb.R; import com.cjj.bb.activity.BiliWebviewActivity; import com.cjj.bb.model.BannerItem; import com.cjj.bb.model.VideoItem; import com.cjj.bb.utils.HttpUtil; import com.nostra13.universalimageloader.cache.disc.impl.UnlimitedDiscCache; import com.nostra13.universalimageloader.cache.memory.impl.LruMemoryCache; import com.nostra13.universalimageloader.core.DisplayImageOptions; import com.nostra13.universalimageloader.core.ImageLoader; import com.nostra13.universalimageloader.core.ImageLoaderConfiguration; import com.nostra13.universalimageloader.core.assist.ImageScaleType; import com.nostra13.universalimageloader.core.assist.QueueProcessingType; import android.content.Intent; import android.graphics.Bitmap; import android.os.AsyncTask; import android.os.Bundle; import android.os.Handler; import android.os.Parcelable; import android.support.v4.app.Fragment; import android.support.v4.view.PagerAdapter; import android.support.v4.view.ViewPager; import android.support.v4.view.ViewPager.OnPageChangeListener; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.view.View.OnClickListener; import android.widget.ImageView; import android.widget.TextView; import android.widget.ImageView.ScaleType; public class HomePageFragment extends Fragment{ public static String IMAGE_CACHE_PATH = "imageloader/Cache"; // 图片缓存路径 public View rootView; private ViewPager adViewPager; private List imageViews;// 滑动的图片集合 private List dots; // 图片标题正文的那些点 private List dotList; private int currentItem = 0; // 当前图片的索引号 // 定义的五个指示点 private View dot0; private View dot1; private View dot2; private View dot3; private View dot4; private View dot5; //新番区控件 ImageView bangumiImageView01; TextView bagumiTextView_title01; TextView bagumiTextView01_baofang; TextView bagumiTextView01_danmugu; ImageView bangumiImageView02; TextView bagumiTextView_title02; TextView bagumiTextView02_baofang; TextView bagumiTextView02_danmugu; ImageView bangumiImageView03; TextView bagumiTextView_title03; TextView bagumiTextView03_baofang; TextView bagumiTextView03_danmugu; ImageView bangumiImageView04; TextView bagumiTextView_title04; TextView bagumiTextView04_baofang; TextView bagumiTextView04_danmugu; private List videoItemList; private ScheduledExecutorService scheduledExecutorService; // 异步加载图片 private ImageLoader mImageLoader; private DisplayImageOptions options; // 轮播banner的数据 private List adList; private Handler handler = new Handler() { public void handleMessage(android.os.Message msg) { adViewPager.setCurrentItem(currentItem); }; }; public HomePageFragment() { } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); initImageLoader(); // 获取图片加载实例 mImageLoader = ImageLoader.getInstance(); options = new DisplayImageOptions.Builder() .showStubImage(R.drawable.top_banner_android) .showImageForEmptyUri(R.drawable.top_banner_android) .showImageOnFail(R.drawable.top_banner_android) .cacheInMemory(true).cacheOnDisc(true) .bitmapConfig(Bitmap.Config.RGB_565) .imageScaleType(ImageScaleType.EXACTLY).build(); } private void initImageLoader() { File cacheDir = com.nostra13.universalimageloader.utils.StorageUtils .getOwnCacheDirectory(this.getActivity().getApplicationContext(), IMAGE_CACHE_PATH); DisplayImageOptions defaultOptions = new DisplayImageOptions.Builder() .cacheInMemory(true).cacheOnDisc(true).build(); ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder( this.getActivity()).defaultDisplayImageOptions(defaultOptions) .memoryCache(new LruMemoryCache(12 * 1024 * 1024)) .memoryCacheSize(12 * 1024 * 1024) .discCacheSize(32 * 1024 * 1024).discCacheFileCount(100) .discCache(new UnlimitedDiscCache(cacheDir)) .threadPriority(Thread.NORM_PRIORITY - 2) .tasksProcessingOrder(QueueProcessingType.LIFO).build(); ImageLoader.getInstance().init(config); } private void initAdData() { // 广告数据 //adList = getBannerAd(); imageViews = new ArrayList(); // 点 dots = new ArrayList(); dotList = new ArrayList(); dot0 = rootView.findViewById(R.id.v_dot0); dot1 = rootView.findViewById(R.id.v_dot1); dot2 = rootView.findViewById(R.id.v_dot2); dot3 = rootView.findViewById(R.id.v_dot3); dot4 = rootView.findViewById(R.id.v_dot4); dot5 = rootView.findViewById(R.id.v_dot5); dots.add(dot0); dots.add(dot1); dots.add(dot2); dots.add(dot3); dots.add(dot4); dots.add(dot5); addDynamicView(); adViewPager = (ViewPager) rootView.findViewById(R.id.vp); adViewPager.setAdapter(new HomePageADAdapter());// 设置填充ViewPager页面的适配器 // 设置一个监听器,当ViewPager中的页面改变时调用 adViewPager.setOnPageChangeListener(new HomePageADChangeListener()); } private void initBangumiData() { bangumiImageView01 = (ImageView) rootView.findViewById(R.id.BangumiImageView01); bagumiTextView_title01 = (TextView) rootView.findViewById(R.id.BangumiTextView01); bagumiTextView01_baofang = (TextView) rootView.findViewById(R.id.BangumiImageView01_baofang); bagumiTextView01_danmugu = (TextView) rootView.findViewById(R.id.BangumiImageView01_danmugu); bangumiImageView02 = (ImageView) rootView.findViewById(R.id.BangumiImageView02); bagumiTextView_title02 = (TextView) rootView.findViewById(R.id.BangumiTextView02); bagumiTextView02_baofang = (TextView) rootView.findViewById(R.id.BangumiImageView02_baofang); bagumiTextView02_danmugu = (TextView) rootView.findViewById(R.id.BangumiImageView02_danmugu); bangumiImageView03 = (ImageView) rootView.findViewById(R.id.BangumiImageView03); bagumiTextView_title03 = (TextView) rootView.findViewById(R.id.BangumiTextView03); bagumiTextView03_baofang = (TextView) rootView.findViewById(R.id.BangumiImageView03_baofang); bagumiTextView03_danmugu = (TextView) rootView.findViewById(R.id.BangumiImageView03_danmugu); bangumiImageView04 = (ImageView) rootView.findViewById(R.id.BangumiImageView04); bagumiTextView_title04 = (TextView) rootView.findViewById(R.id.BangumiTextView04); bagumiTextView04_baofang = (TextView) rootView.findViewById(R.id.BangumiImageView04_baofang); bagumiTextView04_danmugu = (TextView) rootView.findViewById(R.id.BangumiImageView04_danmugu); mImageLoader.displayImage(videoItemList.get(0).getPic(), bangumiImageView01,options); bagumiTextView_title01.setText(videoItemList.get(0).getTitle().toString()); bagumiTextView01_baofang.setText(videoItemList.get(0).getPlay().toString()); bagumiTextView01_danmugu.setText(videoItemList.get(0).getVideo_review().toString()); mImageLoader.displayImage(videoItemList.get(1).getPic(), bangumiImageView02,options); bagumiTextView_title02.setText(videoItemList.get(1).getTitle().toString()); bagumiTextView02_baofang.setText(videoItemList.get(1).getPlay().toString()); bagumiTextView02_danmugu.setText(videoItemList.get(1).getVideo_review().toString()); mImageLoader.displayImage(videoItemList.get(2).getPic(), bangumiImageView03,options); bagumiTextView_title03.setText(videoItemList.get(2).getTitle().toString()); bagumiTextView03_baofang.setText(videoItemList.get(2).getPlay().toString()); bagumiTextView03_danmugu.setText(videoItemList.get(2).getVideo_review().toString()); mImageLoader.displayImage(videoItemList.get(3).getPic(), bangumiImageView04,options); bagumiTextView_title04.setText(videoItemList.get(3).getTitle().toString()); bagumiTextView04_baofang.setText(videoItemList.get(3).getPlay().toString()); bagumiTextView04_danmugu.setText(videoItemList.get(3).getVideo_review().toString()); } private void addDynamicView() { // 动态添加图片和下面指示的圆点 // 初始化图片资源 for (int i = 0; i < adList.size(); i++) { ImageView imageView = new ImageView(this.getActivity()); // 异步加载图片 mImageLoader.displayImage(adList.get(i).getImg(), imageView, options); imageView.setScaleType(ScaleType.CENTER_CROP); imageViews.add(imageView); dots.get(i).setVisibility(View.VISIBLE); dotList.add(dots.get(i)); } } private void startAd() { scheduledExecutorService = Executors.newSingleThreadScheduledExecutor(); // 当Activity显示出来后,每两秒切换一次图片显示 scheduledExecutorService.scheduleAtFixedRate(new ScrollTask(), 1, 2, TimeUnit.SECONDS); } private class ScrollTask implements Runnable { @Override public void run() { synchronized (adViewPager) { currentItem = (currentItem + 1) % imageViews.size(); handler.obtainMessage().sendToTarget(); } } } @Override public void onStop() { super.onStop(); // 当Activity不可见的时候停止切换 scheduledExecutorService.shutdown(); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { rootView = inflater.inflate(R.layout.fragment_main, container, false); Log.d("win","hhhhhhhhhhhh"); new MainTask().execute("0"); return rootView; } private class HomePageADAdapter extends PagerAdapter{ @Override public int getCount() { return adList.size(); } @Override public Object instantiateItem(ViewGroup container, final int position) { ImageView iv = imageViews.get(position); ((ViewPager) container).addView(iv); // 在这个方法里面设置图片的点击事件 iv.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { // 处理跳转逻辑 BannerItem item = (BannerItem) adList.get(position); Intent i = new Intent(); i.setClass(getActivity(), BiliWebviewActivity.class); i.putExtra("bannerLink", item.getLink()); startActivity(i); // 动画过渡 getActivity().overridePendingTransition(R.anim.push_left_in, R.anim.push_no); Log.e("position", "" + position); } }); return iv; } @Override public void destroyItem(View arg0, int arg1, Object arg2) { ((ViewPager) arg0).removeView((View) arg2); } @Override public boolean isViewFromObject(View arg0, Object arg1) { return arg0 == arg1; } @Override public void restoreState(Parcelable arg0, ClassLoader arg1) { } @Override public Parcelable saveState() { return null; } @Override public void startUpdate(View arg0) { } @Override public void finishUpdate(View arg0) { } } private class HomePageADChangeListener implements OnPageChangeListener { private int oldPosition = 0; @Override public void onPageScrollStateChanged(int arg0) { } @Override public void onPageScrolled(int arg0, float arg1, int arg2) { } @Override public void onPageSelected(int position) { currentItem = position; dots.get(oldPosition).setBackgroundResource(R.drawable.dot_normal); dots.get(position).setBackgroundResource(R.drawable.dot_focused); oldPosition = position; } } private class MainTask extends AsyncTask { ArrayList Listtemp = new ArrayList(); ArrayList bangumiListtemp = new ArrayList(); @Override protected Integer doInBackground(String... params) { JSONObject bannerjson; JSONObject bangumijson; try { bannerjson = new JSONObject(HttpUtil.getHtmlString("http://www.bilibili.com/index/slideshow.json")); JSONArray array=bannerjson.getJSONArray("list"); for (int i=0;i imageViews;// 滑动的图片集合 private List dots; // 图片标题正文的那些点 private List dotList; private int currentItem = 0; // 当前图片的索引号 // 定义的六个指示点 private View dot0; private View dot1; private View dot2; private View dot3; private View dot4; private View dot5; private List videoItemList; private List dougaItemList; private List musicItemList; private List danceItemList; private List entItemList; private List movieItemList; private List kejiItemList; private ScheduledExecutorService scheduledExecutorService; // 异步加载图片 private ImageLoader mImageLoader; private DisplayImageOptions options; // 轮播banner的数据 private List adList; private Handler handler = new Handler() { public void handleMessage(android.os.Message msg) { adViewPager.setCurrentItem(currentItem); }; }; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); initImageLoader(); // 获取图片加载实例 mImageLoader = ImageLoader.getInstance(); options = new DisplayImageOptions.Builder() .showStubImage(R.drawable.top_banner_android) .showImageForEmptyUri(R.drawable.top_banner_android) .showImageOnFail(R.drawable.top_banner_android) .cacheInMemory(true).cacheOnDisc(true) .bitmapConfig(Bitmap.Config.ARGB_8888) .imageScaleType(ImageScaleType.EXACTLY).build(); initTestData(); MainTask homePageTask = new MainTask(); homePageTask.execute("0"); } private void initTestData() { videoItemList = new ArrayList(); for (int i = 0; i < 4; i++) { VideoItem tempItem = new VideoItem(); tempItem.setAid("7"); tempItem.setTitle("[示例数据]童年动画主题曲"); tempItem.setPic("http://i0.hdslb.com/320_180/u_user/53cb3e2f7f3efd6464b82c91ea9a1236.jpg"); tempItem.setAuthor("根号⑨"); tempItem.setPlay("23333"); tempItem.setVideo_review("23333"); videoItemList.add(tempItem); } dougaItemList = videoItemList; musicItemList = videoItemList; danceItemList = videoItemList; entItemList = videoItemList; movieItemList = videoItemList; kejiItemList = videoItemList; ArrayList Listtemp = new ArrayList(); for (int i = 0; i < 6; i++) { BannerItem tempItem = new BannerItem(); tempItem.setAd(false); tempItem.setImg("http://i0.hdslb.com/promote/1f451b6b07a1984be5619f865edd5449.jpg"); tempItem.setLink("http://www.bilibili.com"); tempItem.setTitle("[示例数据]"); Listtemp.add(tempItem); } Listtemp.get(0).setAd(true); adList = Listtemp; } private void initImageLoader() { File cacheDir = com.nostra13.universalimageloader.utils.StorageUtils .getOwnCacheDirectory(this.getActivity().getApplicationContext(), IMAGE_CACHE_PATH); DisplayImageOptions defaultOptions = new DisplayImageOptions.Builder() .cacheInMemory(true).cacheOnDisc(true).build(); ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder( this.getActivity()).defaultDisplayImageOptions(defaultOptions) .memoryCache(new LruMemoryCache(12 * 1024 * 1024)) .memoryCacheSize(12 * 1024 * 1024) .discCacheSize(32 * 1024 * 1024).discCacheFileCount(100) .discCache(new UnlimitedDiscCache(cacheDir)) .threadPriority(Thread.NORM_PRIORITY - 2) .tasksProcessingOrder(QueueProcessingType.LIFO).build(); ImageLoader.getInstance().init(config); } private void initAdData() { // 广告数据 //adList = getBannerAd(); imageViews = new ArrayList(); // 点 dots = new ArrayList(); dotList = new ArrayList(); dot0 = rootView.findViewById(R.id.v_dot0); dot1 = rootView.findViewById(R.id.v_dot1); dot2 = rootView.findViewById(R.id.v_dot2); dot3 = rootView.findViewById(R.id.v_dot3); dot4 = rootView.findViewById(R.id.v_dot4); dot5 = rootView.findViewById(R.id.v_dot5); dots.add(dot0); dots.add(dot1); dots.add(dot2); dots.add(dot3); dots.add(dot4); dots.add(dot5); adViewPager = (ViewPager) rootView.findViewById(R.id.vp); bangumiGridView = (GridView)rootView.findViewById(R.id.BangumiGridView); dougaGridView = (GridView)rootView.findViewById(R.id.DonghuaGridView); kejiGridView = (GridView)rootView.findViewById(R.id.KejiGridView); movieGridView = (GridView)rootView.findViewById(R.id.MovieGridView); entGridView = (GridView)rootView.findViewById(R.id.EntGridView); danceGridView = (GridView)rootView.findViewById(R.id.DanceGridView); musicGridView = (GridView)rootView.findViewById(R.id.MusicGridView); addDynamicView(); adViewPager.setAdapter(new HomePageADAdapter());// 设置填充ViewPager页面的适配器 // 设置一个监听器,当ViewPager中的页面改变时调用 adViewPager.setOnPageChangeListener(new HomePageADChangeListener()); GridAdapter bangumiAdapter = new GridAdapter(getActivity(), videoItemList, mImageLoader); bangumiGridView.setAdapter(bangumiAdapter); dougaGridView.setAdapter(new GridAdapter(getActivity(), dougaItemList, mImageLoader)); musicGridView.setAdapter(new GridAdapter(getActivity(), musicItemList, mImageLoader)); danceGridView.setAdapter(new GridAdapter(getActivity(), danceItemList, mImageLoader)); entGridView.setAdapter(new GridAdapter(getActivity(), entItemList, mImageLoader)); movieGridView.setAdapter(new GridAdapter(getActivity(), movieItemList, mImageLoader)); kejiGridView.setAdapter(new GridAdapter(getActivity(), kejiItemList, mImageLoader)); donghuaView = rootView.findViewById(R.id.DonghuaView); donghuaView.setOnClickListener(mDonghuaViewListener); bankumiView = rootView.findViewById(R.id.BangumiView); bankumiView.setOnClickListener(mBankumiViewListener); musicView = rootView.findViewById(R.id.MusicView); musicView.setOnClickListener(mMusicViewListener); gameView = rootView.findViewById(R.id.DanceView); gameView.setOnClickListener(mGameViewListener); yuleView = rootView.findViewById(R.id.EntView); yuleView.setOnClickListener(mYuleViewListener); dianyingView = rootView.findViewById(R.id.MovieView); dianyingView.setOnClickListener(mDianyingViewListener); kejiView = rootView.findViewById(R.id.KejiView); kejiView.setOnClickListener(mKejiViewListener); } private void addDynamicView() { // 动态添加图片和下面指示的圆点 // 初始化图片资源 for (int i = 0; i < adList.size(); i++) { ImageView imageView = new ImageView(this.getActivity()); // 异步加载图片 mImageLoader.displayImage(adList.get(i).getImg(), imageView, options); imageView.setScaleType(ScaleType.CENTER_CROP); imageViews.add(imageView); dots.get(i).setVisibility(View.VISIBLE); dotList.add(dots.get(i)); } } private void startAd() { scheduledExecutorService = Executors.newSingleThreadScheduledExecutor(); // 当Activity显示出来后,每两秒切换一次图片显示 scheduledExecutorService.scheduleAtFixedRate(new ScrollTask(), 1, 2, TimeUnit.SECONDS); } private class ScrollTask implements Runnable { @Override public void run() { synchronized (adViewPager) { currentItem = (currentItem + 1) % imageViews.size(); handler.obtainMessage().sendToTarget(); } } } @Override public void onStop() { super.onStop(); // 当Activity不可见的时候停止切换 //scheduledExecutorService.shutdown(); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { rootView = inflater.inflate(R.layout.fragment_homepage, container, false); Log.d("win","hhhhhhhhhhhh"); initAdData(); return rootView; } private class HomePageADAdapter extends PagerAdapter{ @Override public int getCount() { return adList.size(); } @Override public Object instantiateItem(ViewGroup container, final int position) { ImageView iv = imageViews.get(position); ((ViewPager) container).addView(iv); // 在这个方法里面设置图片的点击事件 iv.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { // 处理跳转逻辑 BannerItem item = (BannerItem) adList.get(position); Intent i = new Intent(); i.setClass(getActivity(), BiliWebviewActivity.class); i.putExtra("bannerLink", item.getLink()); startActivity(i); // 动画过渡 getActivity().overridePendingTransition(R.anim.push_left_in, R.anim.push_no); Log.e("position", "" + position); } }); return iv; } @Override public void destroyItem(View arg0, int arg1, Object arg2) { ((ViewPager) arg0).removeView((View) arg2); } @Override public boolean isViewFromObject(View arg0, Object arg1) { return arg0 == arg1; } @Override public void restoreState(Parcelable arg0, ClassLoader arg1) { } @Override public Parcelable saveState() { return null; } @Override public void startUpdate(View arg0) { } @Override public void finishUpdate(View arg0) { } } private class HomePageADChangeListener implements OnPageChangeListener { private int oldPosition = 0; @Override public void onPageScrollStateChanged(int arg0) { } @Override public void onPageScrolled(int arg0, float arg1, int arg2) { } @Override public void onPageSelected(int position) { currentItem = position; dots.get(oldPosition).setBackgroundResource(R.drawable.dot_normal); dots.get(position).setBackgroundResource(R.drawable.dot_focused); oldPosition = position; } } private class MainTask extends AsyncTask { ArrayList Listtemp = new ArrayList(); ArrayList bangumiListtemp = new ArrayList(); ArrayList dougaListtemp = new ArrayList(); ArrayList musicListtemp = new ArrayList(); ArrayList danceListtemp = new ArrayList(); ArrayList entListtemp = new ArrayList(); ArrayList movieListtemp = new ArrayList(); ArrayList kejiListtemp = new ArrayList(); public MainTask() { // TODO Auto-generated constructor stub Log.d("T^T","----->MainTask"); } @Override protected Integer doInBackground(String... params) { Log.d("T^T","----->doinbackgroud"); JSONObject bannerjson; JSONObject bangumijson; try { bannerjson = new JSONObject(HttpUtil.getHtmlString("http://www.bilibili.com/index/slideshow.json")); JSONArray array=bannerjson.getJSONArray("list"); for (int i=0;ionpostexcute"); adList = Listtemp; videoItemList = bangumiListtemp; dougaItemList = dougaListtemp; musicItemList = musicListtemp; danceItemList = danceListtemp; entItemList = entListtemp; movieItemList = movieListtemp; kejiItemList = kejiListtemp; initAdData(); // initBangumiData(); startAd(); // adViewPager.notifyAll(); } } @Override public void onDestroy() { // TODO Auto-generated method stub mImageLoader.destroy(); super.onDestroy(); } private OnClickListener mDonghuaViewListener = new OnClickListener() { @Override public void onClick(View v) { // 处理跳转逻辑 Intent i = new Intent(); i.putExtra("AreaType",2); i.setClass(getActivity(), DonghuaActivity.class); startActivity(i); // 动画过渡 getActivity().overridePendingTransition(R.anim.push_left_in, R.anim.push_no); } }; private OnClickListener mBankumiViewListener = new OnClickListener() { @Override public void onClick(View v) { // 处理跳转逻辑 Intent i = new Intent(); i.putExtra("AreaType",1); i.setClass(getActivity(), DonghuaActivity.class); startActivity(i); // 动画过渡 getActivity().overridePendingTransition(R.anim.push_left_in, R.anim.push_no); } }; private OnClickListener mMusicViewListener = new OnClickListener() { @Override public void onClick(View v) { // 处理跳转逻辑 Intent i = new Intent(); i.putExtra("AreaType",3); i.setClass(getActivity(), DonghuaActivity.class); startActivity(i); // 动画过渡 getActivity().overridePendingTransition(R.anim.push_left_in, R.anim.push_no); } }; private OnClickListener mKejiViewListener = new OnClickListener() { @Override public void onClick(View v) { // 处理跳转逻辑 Intent i = new Intent(); i.putExtra("AreaType",5); i.setClass(getActivity(), DonghuaActivity.class); startActivity(i); // 动画过渡 getActivity().overridePendingTransition(R.anim.push_left_in, R.anim.push_no); } }; private OnClickListener mYuleViewListener = new OnClickListener() { @Override public void onClick(View v) { // 处理跳转逻辑 Intent i = new Intent(); i.putExtra("AreaType",6); i.setClass(getActivity(), DonghuaActivity.class); startActivity(i); // 动画过渡 getActivity().overridePendingTransition(R.anim.push_left_in, R.anim.push_no); } }; private OnClickListener mDianyingViewListener = new OnClickListener() { @Override public void onClick(View v) { // 处理跳转逻辑 Intent i = new Intent(); i.putExtra("AreaType",7); i.setClass(getActivity(), DonghuaActivity.class); startActivity(i); // 动画过渡 getActivity().overridePendingTransition(R.anim.push_left_in, R.anim.push_no); } }; private OnClickListener mGameViewListener = new OnClickListener() { @Override public void onClick(View v) { // 处理跳转逻辑 Intent i = new Intent(); i.putExtra("AreaType",4); i.setClass(getActivity(), DonghuaActivity.class); startActivity(i); // 动画过渡 getActivity().overridePendingTransition(R.anim.push_left_in, R.anim.push_no); } }; } ================================================ FILE: app/src/main/java/com/cjj/bb/fragment/OnlineFragment.java ================================================ package com.cjj.bb.fragment; import java.util.ArrayList; import java.util.List; import com.cjj.bb.R; import com.cjj.bb.activity.VideoViewActivity; import com.cjj.bb.adapter.ArrayAdapter; import com.cjj.bb.model.OnlineVideo; import com.cjj.bb.utils.XmlReaderHelper; import com.nostra13.universalimageloader.core.DisplayImageOptions; import com.nostra13.universalimageloader.core.ImageLoader; import com.nostra13.universalimageloader.core.ImageLoaderConfiguration; import android.content.Context; import android.content.Intent; import android.net.Uri; import android.os.Bundle; import android.support.v4.app.Fragment; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.AdapterView; import android.widget.AdapterView.OnItemClickListener; import android.widget.ImageView; import android.widget.ListView; import android.widget.TextView; public class OnlineFragment extends Fragment implements OnItemClickListener { /** 缓存视频列表 */ private static ArrayList mOnlineList = new ArrayList(); /** 缓存视频LOGO列表 */ private static ArrayList mOnlineLogoList = new ArrayList(); private ListView mListView; /** 历史记录 */ private List mHistory = new ArrayList(); /** 显示当前正在加载的url */ private TextView mUrl; private String mTitle; private ArrayList tvs; private int level = 1; private DataAdapter mAdapter; @Override public void onCreate(Bundle savedInstanceState) { // TODO Auto-generated method stub super.onCreate(savedInstanceState); tvs = XmlReaderHelper.getAllCategory(getActivity()); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View mView = inflater.inflate(R.layout.fragment_online, container,false); mListView = (ListView) mView.findViewById(android.R.id.list); mListView.setOnItemClickListener(this); mAdapter = new DataAdapter(getActivity(),tvs); mListView.setAdapter(mAdapter); return mView; } @Override public void onItemClick(AdapterView parent, View view, int position, long id) { final OnlineVideo item = mAdapter.getItem(position); switch (level) { case 1:// 顶级 level = 2; mAdapter.replace(XmlReaderHelper.getVideos(getActivity(),item.id)); mListView.setAdapter(mAdapter); break; case 2: // clearAndLoad(item.url); Intent intent = new Intent(getActivity(), VideoViewActivity.class); intent.setData(Uri.parse(item.url)); //intent.putExtra("path", item.url); intent.putExtra("displayName",item.title); startActivity(intent); break; } } public boolean onBackPressed() { switch (level) { case 1: return false; case 2:// level = 1; mAdapter.replace(tvs); break; } mListView.setAdapter(mAdapter); return true; } /** 数据适配 */ private class DataAdapter extends ArrayAdapter { private ImageLoader imageLoader = ImageLoader.getInstance();// 得到图片加载器 private DisplayImageOptions options; // 显示图像设置 public DataAdapter(Context ctx,ArrayList root) { super(ctx, root); // 图片加载器初始化 imageLoader.init(ImageLoaderConfiguration.createDefault(getActivity())); // 使用DisplayImageOptions.Builder()创建DisplayImageOptions options = new DisplayImageOptions.Builder() .showStubImage(R.drawable.ica_light_ic_action_important) // 设置图片下载期间显示的图片 .showImageForEmptyUri(R.drawable.ica_light_ic_action_important) // 设置图片Uri为空或是错误的时候显示的图片 .showImageOnFail(R.drawable.ica_light_ic_action_important) // 设置图片加载或解码过程中发生错误显示的图片 .cacheInMemory() // 设置下载的图片是否缓存在内存中 .cacheOnDisc() // 设置下载的图片是否缓存在SD卡中 .build(); // 创建配置过得DisplayImageOption对象 } @Override public View getView(int position, View convertView, ViewGroup parent) { final OnlineVideo item = getItem(position); if (convertView == null) { final LayoutInflater mInflater = getActivity() .getLayoutInflater(); convertView = mInflater.inflate(R.layout.fragment_online_item, null); } ImageView thumbnail = (ImageView) convertView.findViewById(R.id.thumbnail); if (item.iconId > 0) thumbnail.setImageResource(item.iconId); else { thumbnail.setImageDrawable(null); // 异步加载图片 imageLoader.displayImage(item.icon_url, thumbnail, options); } ((TextView) convertView.findViewById(R.id.title)) .setText(item.title); return convertView; } } @Override public void onPause() { super.onPause(); } @Override public void onResume() { super.onResume(); } } /* * private boolean loadVideo(final String url) { if (StringUtils.isEmpty(url)) * return false; * * mCurrentUrl = url; * * new AsyncTask() { * * @Override protected OnlineVideo doInBackground(Void... params) { * Log.d("Youku", url); if (url.startsWith("http://m.youku.com")) { return * VideoHelper.getYoukuVideo(url); } return null; } * * @Override protected void onPostExecute(OnlineVideo result) { * super.onPostExecute(result); if (result != null) { Intent intent = new * Intent(getActivity(), VideoPlayerActivity.class); intent.putExtra("path", * result.url); intent.putExtra("title", result.title); startActivity(intent); } * else { mWebView.loadUrl(url); } } }.execute(); return true; } */ ================================================ FILE: app/src/main/java/com/cjj/bb/fragment/PersonCenterFragment.java ================================================ package com.cjj.bb.fragment; import android.support.v4.app.Fragment; public class PersonCenterFragment extends Fragment{ } ================================================ FILE: app/src/main/java/com/cjj/bb/fragment/RankFragment.java ================================================ package com.cjj.bb.fragment; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.List; import java.util.Locale; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import android.content.Intent; import android.os.AsyncTask; import android.os.Bundle; import android.support.v4.app.Fragment; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.AdapterView; import android.widget.AdapterView.OnItemClickListener; import android.widget.Toast; /** * Fragment页面 * * @author wwj_748 * @date 2014/8/9 */ public class RankFragment extends Fragment { // private XListView videoListView;// 视频列表 // private View noBlogView; // 无数据时显示 // private VideoListAdapter adapter;// 列表适配器 // private List templist; // // private boolean isLoad = false; // 是否加载 private int videoType = 1; // 视频类别 // private Page page; // 页面引用 // // private String refreshDate = ""; // 刷新日期 // public RankFragment(int videoType) { this.videoType = videoType; } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // init(); } // @Override // public void onActivityCreated(Bundle savedInstanceState) { // templist = new ArrayList(); // VideoItem tempItem = new VideoItem(); // tempItem.setAid("7"); // tempItem.setTitle("[示例数据]童年动画主题曲"); // tempItem.setPic("http://i0.hdslb.com/320_180/u_user/53cb3e2f7f3efd6464b82c91ea9a1236.jpg"); // tempItem.setAuthor("根号⑨"); // tempItem.setPlay("23333"); // templist.add(tempItem); // initComponent(); // if (isLoad == false) { // isLoad = true; // // 加载数据库中的数据 // List list = templist; // adapter.setList(list); // adapter.notifyDataSetChanged(); // // videoListView.startRefresh(); // 开始刷新 // // } else { // videoListView.NotRefreshAtBegin(); // 不开始刷新 // } // super.onActivityCreated(savedInstanceState); // } // // @Override // public View onCreateView(LayoutInflater inflater, ViewGroup container, // Bundle savedInstanceState) { // Log.e("NewsFrag", "onCreateView"); // return inflater.inflate(R.layout.fragment_donghua, null); // } // // // 初始化 // private void init() { // // adapter = new VideoListAdapter(getActivity()); // page = new Page(); // page.setPageStart(); // } // // // 初始化组件 // private void initComponent() { // videoListView = (XListView) getView().findViewById(R.id.videoListView); // videoListView.setAdapter(adapter);// 设置适配器 // videoListView.setPullRefreshEnable(this);// 设置可下拉刷新 // //videoListView.setPullLoadEnable(this);// 设置可上拉加载 // // 设置列表项点击事件 // videoListView.setOnItemClickListener(new OnItemClickListener() { // // @Override // public void onItemClick(AdapterView parent, View view, // int position, long id) { // // 获得博客列表项 // VideoItem item = (VideoItem) adapter.getItem(position - 1); // Intent i = new Intent(); // Bundle bundle = new Bundle(); // bundle.putSerializable("videoItemdata", item); // i.setClass(getActivity(), VideoInfoActivity.class); // i.putExtras(bundle); // startActivity(i); // // 动画过渡 // getActivity().overridePendingTransition(R.anim.push_left_in, // R.anim.push_no); // } // }); // // noBlogView = getView().findViewById(R.id.noBlogLayout); // } // // private class MainTask extends AsyncTask { // // @Override // protected Integer doInBackground(String... params) { // List list=new ArrayList(); // try { // JSONObject donghuajson = new JSONObject(HttpUtil.getHtmlString(params[0])); // //动画数据解析 // donghuajson =donghuajson.getJSONObject("rank"); // JSONArray dougaarray=donghuajson.getJSONArray("list"); // for (int i=0;i<20;i++) { // VideoItem item = new VideoItem(); // item.setAid(dougaarray.getJSONObject(i).getString("aid").toString()); // item.setTitle(dougaarray.getJSONObject(i).getString("title").toString()); // item.setPlay(dougaarray.getJSONObject(i).getString("play").toString()); // item.setVideo_review(dougaarray.getJSONObject(i).getString("video_review").toString()); // item.setMid(dougaarray.getJSONObject(i).getString("mid").toString()); // item.setAuthor(dougaarray.getJSONObject(i).getString("author").toString()); // item.setDescription(dougaarray.getJSONObject(i).getString("description").toString()); // item.setCreate(dougaarray.getJSONObject(i).getString("create").toString()); // item.setPic(dougaarray.getJSONObject(i).getString("pic").toString()); // item.setCoins(dougaarray.getJSONObject(i).getString("coins").toString()); // list.add(item); // //Log.d("TAG--->", "--->"+item.getTitle()); // } // // } catch (JSONException e) { // // TODO Auto-generated catch block // e.printStackTrace(); // return Constants.DEF_RESULT_CODE.ERROR; // } //// // 获取网页json数据 //// String temp = HttpUtil.httpGet(params[0]); //// if (temp == null) { //// return Constants.DEF_RESULT_CODE.ERROR; //// } //// // 解析json获取列表 //// List list = JsoupUtil.getBlogItemList(blogType, temp); // // if (list.size() == 0) { // return Constants.DEF_RESULT_CODE.NO_DATA; // } // // 刷新动作 // if (params[1].equals("refresh")) { // adapter.setList(list); // return Constants.DEF_RESULT_CODE.REFRESH; // } else {// 加载更多 // adapter.addList(list); // return Constants.DEF_RESULT_CODE.LOAD; // } // // } // // @Override // protected void onPostExecute(Integer result) { // // 通知列表数据更新 // adapter.notifyDataSetChanged(); // switch (result) { // case Constants.DEF_RESULT_CODE.ERROR: // 错误 // Toast.makeText(getActivity(), "网络信号不佳", Toast.LENGTH_LONG).show(); // videoListView.stopRefresh(getDate()); // videoListView.stopLoadMore(); // break; // case Constants.DEF_RESULT_CODE.NO_DATA: // 无数据 // // Toast.makeText(getActivity(), "无更多加载内容", Toast.LENGTH_LONG) // // .show(); // videoListView.stopLoadMore(); // // noBlogView.setVisibility(View.VISIBLE); // 显示无博客 // break; // case Constants.DEF_RESULT_CODE.REFRESH: // 刷新 // videoListView.stopRefresh(getDate()); // if (adapter.getCount() == 0) { // noBlogView.setVisibility(View.VISIBLE); // 显示无博客 // } // break; // case Constants.DEF_RESULT_CODE.LOAD: // videoListView.stopLoadMore(); // page.addPage(); // if (adapter.getCount() == 0) { // noBlogView.setVisibility(View.VISIBLE); // 显示无博客 // } // break; // default: // break; // } // super.onPostExecute(result); // } // // } // // // 加载更多时调用 // @Override // public void onLoadMore() { // System.out.println("loadmore"); // // } // // @Override // public void onRefresh() { // System.out.println("refresh"); // page.setPageStart(); // new MainTask().execute(URLUtil.getRefreshBlogListURL(videoType), // "refresh"); // } // // public String getDate() { // SimpleDateFormat sdf = new SimpleDateFormat("MM月dd日 HH:mm", // Locale.CHINA); // return sdf.format(new java.util.Date()); // } } ================================================ FILE: app/src/main/java/com/cjj/bb/fragment/RelevantVideoFragment.java ================================================ package com.cjj.bb.fragment; import android.support.v4.app.Fragment; public class RelevantVideoFragment extends Fragment{ } ================================================ FILE: app/src/main/java/com/cjj/bb/fragment/SubareaFragment.java ================================================ package com.cjj.bb.fragment; import android.content.Intent; import android.os.Bundle; import android.support.v4.app.Fragment; import android.view.LayoutInflater; import android.view.View; import android.view.View.OnClickListener; import android.view.ViewGroup; import android.widget.GridView; import com.cjj.bb.R; import com.cjj.bb.activity.DonghuaActivity; import com.cjj.bb.adapter.AreaGridAdapter; import com.cjj.bb.model.AreaItem; import java.util.ArrayList; public class SubareaFragment extends Fragment{ private GridView areaGridView; private View rankView; private ArrayList areaList = new ArrayList(); private int[] areaimages = new int[]{R.drawable.ic_cate_bangumi,R.drawable.ic_cate_animation, R.drawable.ic_cate_music,R.drawable.ic_cate_game,R.drawable.ic_cate_science, R.drawable.ic_cate_entertainment,R.drawable.ic_cate_movie,R.drawable.ic_cate_tv}; private String[] areatexts = new String[]{"番剧","动画","音乐","游戏","科学","娱乐","电影","电视"}; @Override public void onCreate(Bundle savedInstanceState) { // TODO Auto-generated method stub super.onCreate(savedInstanceState); for (int i = 0; i < areaimages.length; i++) { AreaItem item = new AreaItem(); item.setImg(areaimages[i]); item.setText(areatexts[i]); areaList.add(item); } } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View rootView = inflater.inflate(R.layout.fragment_subarea, container, false); areaGridView = (GridView)rootView.findViewById(R.id.AreaGridView); areaGridView.setAdapter(new AreaGridAdapter(getActivity(), areaList)); rankView = rootView.findViewById(R.id.RankView); rankView.setOnClickListener(new OnClickListener() { @Override public void onClick(View arg0) { // TODO Auto-generated method stub // 处理跳转逻辑 Intent i = new Intent(); i.putExtra("AreaType",8); i.setClass(getActivity(), DonghuaActivity.class); getActivity().startActivity(i); // 动画过渡 getActivity().overridePendingTransition(R.anim.push_left_in,R.anim.push_no); } }); return rootView; } } ================================================ FILE: app/src/main/java/com/cjj/bb/fragment/VideoInfoFragment.java ================================================ package com.cjj.bb.fragment; import java.io.File; import java.util.ArrayList; import java.util.Iterator; import org.json.JSONException; import org.json.JSONObject; import org.jsoup.Jsoup; import org.jsoup.nodes.Document; import org.jsoup.nodes.Element; import org.jsoup.select.Elements; import com.cjj.bb.R; import com.cjj.bb.activity.BiliVideoViewActivity; import com.cjj.bb.adapter.VideoInfoListAdapter; import com.cjj.bb.model.VideoItem; import com.cjj.bb.utils.HttpUtil; import com.nostra13.universalimageloader.cache.disc.impl.UnlimitedDiscCache; import com.nostra13.universalimageloader.cache.memory.impl.LruMemoryCache; import com.nostra13.universalimageloader.core.DisplayImageOptions; import com.nostra13.universalimageloader.core.ImageLoader; import com.nostra13.universalimageloader.core.ImageLoaderConfiguration; import com.nostra13.universalimageloader.core.assist.ImageScaleType; import com.nostra13.universalimageloader.core.assist.QueueProcessingType; import android.content.Intent; import android.graphics.Bitmap; import android.net.Uri; import android.os.AsyncTask; import android.os.Bundle; import android.support.v4.app.Fragment; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.View.OnClickListener; import android.view.ViewGroup; import android.widget.Button; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.ListView; import android.widget.TextView; public class VideoInfoFragment extends Fragment{ public static String IMAGE_CACHE_PATH = "imageloader/Cache"; // 图片缓存路径 private String page = "1"; boolean isClickable = true; private View rootView; private VideoItem videoinfo; private ImageView videoImgaeView; private TextView titleTextView; private TextView upTextView; private TextView bofangTextView; private TextView danmaguTextView; private Button bofangButton; private TextView labelTextView; private TextView durationTextView; private ListView videoInfoListView; private ImageView arrowButton; private TextView videoNum; private ArrayList videoInfoList = new ArrayList(); private ImageLoader mImageLoader; private DisplayImageOptions options; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); videoinfo = (VideoItem) getActivity().getIntent().getSerializableExtra("videoItemdata"); initImageLoader(); // 获取图片加载实例 mImageLoader = ImageLoader.getInstance(); options = new DisplayImageOptions.Builder() .showStubImage(R.drawable.top_banner_android) .showImageForEmptyUri(R.drawable.top_banner_android) .showImageOnFail(R.drawable.top_banner_android) .cacheInMemory(true).cacheOnDisc(true) .bitmapConfig(Bitmap.Config.RGB_565) .imageScaleType(ImageScaleType.EXACTLY).build(); } private void initImageLoader() { File cacheDir = com.nostra13.universalimageloader.utils.StorageUtils .getOwnCacheDirectory(this.getActivity().getApplicationContext(), IMAGE_CACHE_PATH); DisplayImageOptions defaultOptions = new DisplayImageOptions.Builder() .cacheInMemory(true).cacheOnDisc(true).build(); ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder( this.getActivity()).defaultDisplayImageOptions(defaultOptions) .memoryCache(new LruMemoryCache(12 * 1024 * 1024)) .memoryCacheSize(12 * 1024 * 1024) .discCacheSize(32 * 1024 * 1024).discCacheFileCount(100) .discCache(new UnlimitedDiscCache(cacheDir)) .threadPriority(Thread.NORM_PRIORITY - 2) .tasksProcessingOrder(QueueProcessingType.LIFO).build(); ImageLoader.getInstance().init(config); } final class InJavaScriptLocalObj { public void showSource(String html) { System.out.println("====>html="+html); } } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { rootView = inflater.inflate(R.layout.fragment_videoinfo, container, false); initData(); Log.d("T^T","----->onCreateView"); new VideoInfoTask().execute(); return rootView; } private void initData() { videoImgaeView = (ImageView) rootView.findViewById(R.id.imageView); titleTextView = (TextView) rootView.findViewById(R.id.titleTextView); upTextView= (TextView) rootView.findViewById(R.id.authorTextView); bofangTextView= (TextView) rootView.findViewById(R.id.playTextView); danmaguTextView= (TextView) rootView.findViewById(R.id.video_reviewTextView); bofangButton = (Button) rootView.findViewById(R.id.playButton); labelTextView= (TextView) rootView.findViewById(R.id.labelTextView); durationTextView = (TextView) rootView.findViewById(R.id.durationTextView); videoInfoListView = (ListView) rootView.findViewById(R.id.video_info_list); arrowButton = (ImageView) rootView.findViewById(R.id.arrowButton); videoNum = (TextView) rootView.findViewById(R.id.videoNumTextView); mImageLoader.displayImage(videoinfo.getPic(), videoImgaeView,options); titleTextView.setText(videoinfo.getTitle()); upTextView.setText("Up主:"+videoinfo.getAuthor()); bofangTextView.setText("播放:"+videoinfo.getPlay()); danmaguTextView.setText("弹幕:"+videoinfo.getVideo_review()); //labelTextView.setText(videoinfo.getVideo_review()); durationTextView.setText(" "+videoinfo.getDescription()); bofangButton.setOnClickListener(new OnClickListener() { @Override public void onClick(View arg0) { // TODO Auto-generated method stub if(bofangButton.getText().equals("点击播放")){ Log.d("T^T","----->点击播放"); // 处理跳转逻辑 // Intent i = new Intent(); // i.setClass(getActivity(), VideoViewActivity.class); // i.putExtra("videoPath", videopath); // i.putExtra("title", videoinfo.getTitle()); // startActivity(i); Intent intent = new Intent(getActivity(), BiliVideoViewActivity.class); // intent.putExtra("path", item.url); intent.putExtra("displayName",videoinfo.getTitle()); intent.putExtra("av",videoinfo.getAid()); page = "1"; intent.putExtra("page",page); startActivity(intent); // 动画过渡 getActivity().overridePendingTransition(R.anim.push_left_in,R.anim.push_no); } } }); arrowButton.setOnClickListener(new OnClickListener() { @Override public void onClick(View arg0) { // TODO Auto-generated method stub if (isClickable) { durationTextView.setMaxLines(durationTextView.getLineCount()); isClickable = false; arrowButton.setImageResource(R.drawable.abcp__expander_close_holo_light); } else { durationTextView.setMaxLines(2); isClickable = true; arrowButton.setImageResource(R.drawable.abcp__expander_open_holo_light); } } }); } @Override public void onStop() { // TODO Auto-generated method stub super.onStop(); } private class VideoInfoTask extends AsyncTask { String label; @Override protected Integer doInBackground(String... arg0) { // String videoHTML = HttpUtil.sendPost("http://www.iippcc.com/bilibili/", "text=av"+videoinfo.getAid()+"&submit=搜索菌"); // // Document doc = Jsoup.parse(videoHTML); // Elements links = doc.select("a[href]"); // for (Element link : links) { // if(link.text().equals("分段1")){ // videopath = link.attr("href"); // } // } // // Elements labels = doc.getElementsByClass("col-md-7"); // labels = labels.select("button"); // //label = labels.get(3).text(); // cID = labels.get(6).text().substring(4); // // String listHTML = HttpUtil.getHtmlString("http://www.bilibili.com/mobile/video/av" + videoinfo.getAid() + ".html"); Log.d("QAQ--->","===>列表加载中"); Document listDoc = Jsoup.parse(listHTML); Elements listElements = listDoc.getElementsByClass("li-wrap-content"); for (int i = 0; i < listElements.size(); i++) { Log.d("QAQ--->","===>"+listElements.get(i).text()); videoInfoList.add(listElements.get(i).text()); } Elements labelElements = listDoc.select("[name=keywords]"); Log.d("QAQ--->","===>"+labelElements.attr("content")); label = labelElements.attr("content"); return null; } @Override protected void onPostExecute(Integer result) { // TODO Auto-generated method stubs super.onPostExecute(result); if(label != null){ bofangButton.setText("点击播放"); }else{ bofangButton.setText("加载失败"); } if(label != null){ label = label.substring(20); labelTextView.setText("标签:"+label); if(videoInfoList != null){ videoInfoListView.setAdapter(new VideoInfoListAdapter(getActivity(),videoInfoList,videoinfo.getAid())); videoNum.setText("共有"+videoInfoList.size()+"段视频"); } } if(durationTextView.getLineCount() > 2){ arrowButton.setVisibility(View.VISIBLE); } } } } ================================================ FILE: app/src/main/java/com/cjj/bb/model/AreaItem.java ================================================ package com.cjj.bb.model; public class AreaItem { private int img; //图标 private String text; //文字 public int getImg() { return img; } public void setImg(int img) { this.img = img; } public String getText() { return text; } public void setText(String text) { this.text = text; } } ================================================ FILE: app/src/main/java/com/cjj/bb/model/BannerItem.java ================================================ package com.cjj.bb.model; public class BannerItem { private String title; //广告条标题 private String link; //广告条链接 private String img; //广告条封面地址 private boolean isAd; public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public String getLink() { return link; } public void setLink(String link) { this.link = link; } public String getImg() { return img; } public void setImg(String img) { this.img = img; } public boolean isAd() { return isAd; } public void setAd(boolean isAd) { this.isAd = isAd; } } ================================================ FILE: app/src/main/java/com/cjj/bb/model/GameItem.java ================================================ package com.cjj.bb.model; public class GameItem { private int img; //图标 private String text; //文字 private String path; //网址 public int getImg() { return img; } public void setImg(int img) { this.img = img; } public String getText() { return text; } public void setText(String text) { this.text = text; } public String getPath() { return path; } public void setPath(String path) { this.path = path; } } ================================================ FILE: app/src/main/java/com/cjj/bb/model/OnlineVideo.java ================================================ package com.cjj.bb.model; import java.util.ArrayList; public class OnlineVideo { public String id; /** 标题 */ public String title; public String desc; /** LOGO */ public int iconId = 0; public String icon_url; /** 播放地址 */ public String url; /** 备用链接 */ public ArrayList backup_url; /** 是否目录 */ public boolean is_category = false; /** 0视频 1电视 */ public int category; /** */ public int level = 1; public OnlineVideo() { } public OnlineVideo(String title, int iconId, int category) { this.title = title; this.iconId = iconId; this.category = category; } public OnlineVideo(String title, int iconId, int category, String url) { this.title = title; this.iconId = iconId; this.category = category; this.url = url; } } ================================================ FILE: app/src/main/java/com/cjj/bb/model/Page.java ================================================ package com.cjj.bb.model; /** * 页面实体类 * * @author wwj_748 * @date 2014/8/9 */ public class Page { private int page = 1; // 记录页面数 public boolean contentFirstPage = true; // 内容第一页 // 设置开始页面 public void setPageStart() { page = 2; } // 设置页 public void setPage(int num) { page = num; } // 获取当前页 public String getCurrentPage() { return page + ""; } // 添加页面 public void addPage() { page++; } } ================================================ FILE: app/src/main/java/com/cjj/bb/model/User.java ================================================ package com.cjj.bb.model; public class User { private String mid; private String name; private Boolean isApprove = false; //是否是认证账号 private String spaceName; private String sex; private String rank; private String avatar; private String follow ; //关注好友数目 private String fans; //粉丝数目 private String article; //投稿数 private String place; //所在地 private String description; //认证用户为认证信息 普通用户为交友宣言 private String followlist; //关注的好友列表 public String getMid() { return mid; } public void setMid(String mid) { this.mid = mid; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Boolean getIsApprove() { return isApprove; } public void setIsApprove(Boolean isApprove) { this.isApprove = isApprove; } public String getSpaceName() { return spaceName; } public void setSpaceName(String spaceName) { this.spaceName = spaceName; } /** * @return the sex */ public String getSex() { return sex; } /** * @param sex the sex to set */ public void setSex(String sex) { this.sex = sex; } public String getRank() { return rank; } public void setRank(String rank) { this.rank = rank; } public String getAvatar() { return avatar; } public void setAvatar(String avatar) { this.avatar = avatar; } public String getFollow() { return follow; } public void setFollow(String follow) { this.follow = follow; } public String getArticle() { return article; } public void setArticle(String article) { this.article = article; } public String getFans() { return fans; } public void setFans(String fans) { this.fans = fans; } public String getPlace() { return place; } public void setPlace(String place) { this.place = place; } public String getDescription() { return description; } public void setDescription(String description) { this.description = description; } public String getFollowlist() { return followlist; } public void setFollowlist(String followlist) { this.followlist = followlist; } } ================================================ FILE: app/src/main/java/com/cjj/bb/model/Video.java ================================================ package com.cjj.bb.model; public class Video { private String aid; //视频av号 private String title; //视频标题 private String bofang; //视频播放数 private String shoucang; //视频收藏数 private String danmu; //视频弹幕数 private String date; //发布时间 private String cover; //视频封面地址 private String commentNumber; //视频评论数 private String description; //视频描述 private String tag; //视频TAG private String author; //up主 private String credit; //视频评分 private String coin; //视频硬币数 private String spid; //专题ID private String cid; //视频内部ID private String offsite; //Flash播放调用地址 private String duration; //视频长度 private String episode; //视频分段数 private String arcurl; //网页地址 private String src; //视频播放地址 public String getAid() { return aid; } public void setAid(String aid) { this.aid = aid; } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public String getBofang() { return bofang; } public void setBofang(String bofang) { this.bofang = bofang; } public String getShoucang() { return shoucang; } public void setShoucang(String shoucang) { this.shoucang = shoucang; } public String getDanmu() { return danmu; } public void setDanmu(String danmu) { this.danmu = danmu; } public String getDate() { return date; } public void setDate(String date) { this.date = date; } public String getCover() { return cover; } public void setCover(String cover) { this.cover = cover; } public String getCommentNumber() { return commentNumber; } public void setCommentNumber(String commentNumber) { this.commentNumber = commentNumber; } public String getDescription() { return description; } public void setDescription(String description) { this.description = description; } public String getTag() { return tag; } public void setTag(String tag) { this.tag = tag; } public String getAuthor() { return author; } public void setAuthor(String author) { this.author = author; } public String getCredit() { return credit; } public void setCredit(String credit) { this.credit = credit; } public String getCoin() { return coin; } public void setCoin(String coin) { this.coin = coin; } public String getSpid() { return spid; } public void setSpid(String spid) { this.spid = spid; } public String getCid() { return cid; } public void setCid(String cid) { this.cid = cid; } public String getOffsite() { return offsite; } public void setOffsite(String offsite) { this.offsite = offsite; } public String getDuration() { return duration; } public void setDuration(String duration) { this.duration = duration; } public String getEpisode() { return episode; } public void setEpisode(String episode) { this.episode = episode; } public String getArcurl() { return arcurl; } public void setArcurl(String arcurl) { this.arcurl = arcurl; } public String getSrc() { return src; } public void setSrc(String src) { this.src = src; } } ================================================ FILE: app/src/main/java/com/cjj/bb/model/VideoItem.java ================================================ package com.cjj.bb.model; import java.io.Serializable; public class VideoItem implements Serializable{ private String aid;//视频av号 private String typeid;//视频类型 private String title;//视频标题 private String sbutitle; private String play;//视频播放数 private String review;//评论数 private String video_review;//视频弹幕数 private String favorites;//视频收藏数 private String mid; private String author;//Up主 private String description;//视频简介 private String create;//视频发布时间 private String pic;//视频封面地址 private String credit; private String coins;//视频硬币数 private String duration;//视频长度 public String getAid() { return aid; } public void setAid(String aid) { this.aid = aid; } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public String getTypeid() { return typeid; } public void setTypeid(String typeid) { this.typeid = typeid; } public String getPlay() { return play; } public void setPlay(String play) { this.play = play; } public String getSbutitle() { return sbutitle; } public void setSbutitle(String sbutitle) { this.sbutitle = sbutitle; } public String getReview() { return review; } public void setReview(String review) { this.review = review; } public String getVideo_review() { return video_review; } public void setVideo_review(String video_review) { this.video_review = video_review; } public String getFavorites() { return favorites; } public void setFavorites(String favorites) { this.favorites = favorites; } public String getMid() { return mid; } public void setMid(String mid) { this.mid = mid; } public String getAuthor() { return author; } public void setAuthor(String author) { this.author = author; } public String getDescription() { return description; } public void setDescription(String description) { this.description = description; } public String getCreate() { return create; } public void setCreate(String create) { this.create = create; } public String getPic() { return pic; } public void setPic(String pic) { this.pic = pic; } public String getCredit() { return credit; } public void setCredit(String credit) { this.credit = credit; } public String getCoins() { return coins; } public void setCoins(String coins) { this.coins = coins; } public String getDuration() { return duration; } public void setDuration(String duration) { this.duration = duration; } } ================================================ FILE: app/src/main/java/com/cjj/bb/utils/ArrayUtils.java ================================================ /* * Copyright (C) 2012 YIXIA.COM * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.cjj.bb.utils; import java.lang.reflect.Array; public class ArrayUtils { public static T[] concat(T[] A, T[] B) { final Class typeofA = A.getClass().getComponentType(); @SuppressWarnings("unchecked") T[] C = (T[]) Array.newInstance(typeofA, A.length + B.length); System.arraycopy(A, 0, C, 0, A.length); System.arraycopy(B, 0, C, A.length, B.length); return C; } public static int indexOf(T[] array, T s) { for (int i = 0; i < array.length; i++) { if (array[i].equals(s)) { return i; } } return -1; } } ================================================ FILE: app/src/main/java/com/cjj/bb/utils/CompressionTools.java ================================================ package com.cjj.bb.utils; import java.util.zip.Deflater; import java.util.zip.Inflater; import java.util.zip.DataFormatException; import java.io.ByteArrayOutputStream; import java.io.IOException; public class CompressionTools { // Export only static methods private CompressionTools() {} public static byte[] compress(byte[] value, int offset, int length, int compressionLevel) { ByteArrayOutputStream bos = new ByteArrayOutputStream(length); Deflater compressor = new Deflater(); try { compressor.setLevel(compressionLevel); //将当前压缩级别设置为指定值。 compressor.setInput(value, offset, length); compressor.finish(); //调用时,指示压缩应当以输入缓冲区的当前内容结尾。 // Compress the data final byte[] buf = new byte[1024]; while (!compressor.finished()) { //如果已到达压缩数据输出流的结尾,则返回 true。 int count = compressor.deflate(buf); // 使用压缩数据填充指定缓冲区。 bos.write(buf, 0, count); } } finally { compressor.end(); //关闭解压缩器并放弃所有未处理的输入。 } return bos.toByteArray(); } public static byte[] compress(byte[] value, int offset, int length) { return compress(value, offset, length, Deflater.BEST_COMPRESSION); // 最佳压缩的压缩级别 } public static byte[] compress(byte[] value) { return compress(value, 0, value.length, Deflater.BEST_COMPRESSION); } public static byte[] decompress(byte[] value) throws DataFormatException { ByteArrayOutputStream bos = new ByteArrayOutputStream(value.length); Inflater decompressor = new Inflater(); try { decompressor.setInput(value); final byte[] buf = new byte[1024]; while (!decompressor.finished()) { int count = decompressor.inflate(buf); bos.write(buf, 0, count); } } finally { decompressor.end(); } return bos.toByteArray(); } public static byte[] decompressXML(byte[] data) throws DataFormatException { byte[] dest = new byte[data.length+2]; System.arraycopy(data, 0, dest, 2, data.length); dest[0] = 0x78; dest[1] = 0x01; data = dest; Inflater decompresser = new Inflater(); decompresser.setInput(data); byte[] bufferArray = new byte[1024]; ByteArrayOutputStream baos = new ByteArrayOutputStream(1024); try { int i = 1; while (i != 0) { i = decompresser.inflate(bufferArray); baos.write(bufferArray, 0, i); } data = baos.toByteArray(); } catch (Exception e) { e.printStackTrace(); } finally { try { baos.flush(); baos.close(); } catch (IOException e) { e.printStackTrace(); } } decompresser.end(); return data; } } ================================================ FILE: app/src/main/java/com/cjj/bb/utils/Constants.java ================================================ package com.cjj.bb.utils; /** * 常量类 * * @author wwj_748 * */ public class Constants { // 博客每一项的类型 public class DEF_BLOG_ITEM_TYPE { public static final int TITLE = 1; // 标题 public static final int SUMMARY = 2; // 摘要 public static final int CONTENT = 3; // 内容 public static final int IMG = 4; // 图片 public static final int BOLD_TITLE = 5; // 加粗标题 public static final int CODE = 6; // 代码 } public class DEF_NEWS_TYPE { public static final int YEJIE = 1; public static final int YIDONG = 2; public static final int YANFA = 3; public static final int ZAZHI = 4; public static final int YUNJISUAN = 5; } // 评论类型 public class DEF_COMMENT_TYPE { public static final int PARENT = 1; public static final int CHILD = 2; } // 操作结果类型 public class DEF_RESULT_CODE { public static final int ERROR = 1; // 错误 public static final int NO_DATA = 2;// 无数据 public static final int REFRESH = 3;// 刷新 public static final int LOAD = 4; // 加载 public static final int FIRST = 5;// 第一次加载 } // 任务类型 public class DEF_TASK_TYPE { public static final String FIRST = "first"; public static final String NOR_FIRST = "not_first"; public static final String REFRESH = "REFRESH"; public static final String LOAD = "LOAD"; } /** * 视频类型 */ public class DEF_VIDEO_TYPE { public static final int DONG_HUA = 1; // 动画区 public static final int MAD_AMV = 24; // MAD.AMV public static final int MMD_3D = 25; // MMD.3D public static final int DONG_HUA_DUAN_PIAN = 47; // 动画短片 public static final int DONG_HUA_ZONG_HE = 27; // 动画综合 public static final int LIAN_ZAI_DONG_HUA = 33; // 连载动画 public static final int WAN_JIE_DONG_HUA = 32; // 完结动画 public static final int ZHI_XUN = 51; // 资讯 public static final int GUAN_FANG_YAN_SHEN = 152; // 官方延伸 public static final int GUO_CHAN_DONG_HUA = 153; // 国产动画 public static final int YIN_YUE = 3; // 音乐区 public static final int FAN_CHANG = 31; // 翻唱 public static final int VOCALOID_UTAU = 30; // VOCALOID-UTAU public static final int YAN_ZOU = 59; // 演奏 public static final int YIN_YUE_XUAN_JI = 130; //音乐选集 public static final int KE_JI = 36; //科技-全区 public static final int JI_LU_PIAN = 37; //纪录片 public static final int KE_PU_REN_WEN = 124; //科普人文 public static final int YE_SHENG_JI_SHU = 122; //野生技术 public static final int YAN_JIANG = 39; //演讲·公开课 public static final int JUN_SHI = 96; //军事 public static final int SHU_MA = 95; //数码 public static final int YU_LE = 5; //娱乐 public static final int GAO_XIAO = 138; //搞笑 public static final int SHENG_HUO = 21; //生活 public static final int ZONG_YI = 71; //综艺 public static final int DIAN_YIN = 23; //电影 public static final int OU_MEI_DIAN_YIN = 145; //欧美电影 public static final int RI_BEN_DIAN_YIN = 146; //日本电影 public static final int GUO_CHAN_DIAN_YIN = 147; //国产电影 public static final int DIAN_YIN_XIANG_GUAN = 82; //电影相关 public static final int YOU_XI = 4; //游戏 public static final int DIAN_JI = 17; //单机联机 public static final int WANG_LUO_DIAN_YIN = 65; //网络游戏 public static final int DIAN_ZI_JING_JI = 60; //电子竞技 } /** * 分区类型 */ public class DEF_AREA_TYPE { public static final int DONG_HUA_QU = 1; // 动画区 public static final int FAN_JU_QU = 2; // 番剧区 public static final int YIN_YUE_QU = 3; // 音乐区 public static final int KE_JI_QU = 4; // 科技区 public static final int YU_LE_QU = 5; // 娱乐区 public static final int YOU_XI_QU = 6; // 游戏区 } } ================================================ FILE: app/src/main/java/com/cjj/bb/utils/DeviceUtils.java ================================================ package com.cjj.bb.utils; import java.io.BufferedReader; import java.io.File; import java.io.FileReader; import java.io.IOException; import java.util.List; import android.app.Activity; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; import android.content.pm.ResolveInfo; import android.content.res.Configuration; import android.os.Build; import android.os.Environment; import android.os.StatFs; import android.util.DisplayMetrics; import android.view.Display; import android.view.View; import android.view.WindowManager; import android.view.inputmethod.InputMethodManager; /** * 系统版本信息类 * * @author tangjun * */ public class DeviceUtils { /** >=2.2 */ public static boolean hasFroyo() { return Build.VERSION.SDK_INT >= Build.VERSION_CODES.FROYO; } /** >=2.3 */ public static boolean hasGingerbread() { return Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD; } /** >=3.0 LEVEL:11 */ public static boolean hasHoneycomb() { return Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB; } /** >=3.1 */ public static boolean hasHoneycombMR1() { return Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR1; } /** >=4.0 14 */ public static boolean hasICS() { return Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH; } public static int getSDKVersionInt() { return Build.VERSION.SDK_INT; } @SuppressWarnings("deprecation") public static String getSDKVersion() { return Build.VERSION.SDK; } /** * 判断是否是平板电脑 * * @param context * @return */ public static boolean isTablet(Context context) { return (context.getResources().getConfiguration().screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK) >= Configuration.SCREENLAYOUT_SIZE_LARGE; } public static boolean isHoneycombTablet(Context context) { return hasHoneycomb() && isTablet(context); } /** * 获得设备型号 * * @return */ public static String getDeviceModel() { return StringUtils.trim(Build.MODEL); } /** 检测是否魅族手机 */ public static boolean isMeizu() { return getDeviceModel().toLowerCase().indexOf("meizu") != -1; } /** 检测是否HTC手机 */ public static boolean isHTC() { return getDeviceModel().toLowerCase().indexOf("htc") != -1; } public static boolean isXiaomi() { return getDeviceModel().toLowerCase().indexOf("xiaomi") != -1; } /** * 获得设备制造商 * * @return */ public static String getManufacturer() { return StringUtils.trim(Build.MANUFACTURER); } @SuppressWarnings("deprecation") public static int getScreenHeight(Context context) { Display display = ((WindowManager) context .getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay(); return display.getHeight(); } /** 获取屏幕宽度 */ @SuppressWarnings("deprecation") public static int getScreenWidth(Context context) { Display display = ((WindowManager) context .getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay(); return display.getWidth(); } /** * 获得设备屏幕密度 */ public static float getScreenDensity(Context context) { DisplayMetrics metrics = context.getApplicationContext().getResources() .getDisplayMetrics(); return metrics.density; } public static int[] getScreenSize(int w, int h, Context context) { int phoneW = getScreenWidth(context); int phoneH = getScreenHeight(context); if (w * phoneH > phoneW * h) { phoneH = phoneW * h / w; } else if (w * phoneH < phoneW * h) { phoneW = phoneH * w / h; } return new int[] { phoneW, phoneH }; } public static int[] getScreenSize(int w, int h, int phoneW, int phoneH) { if (w * phoneH > phoneW * h) { phoneH = phoneW * h / w; } else if (w * phoneH < phoneW * h) { phoneW = phoneH * w / h; } return new int[] { phoneW, phoneH }; } /** 设置屏幕亮度 */ public static void setBrightness(final Activity context, float f) { WindowManager.LayoutParams lp = context.getWindow().getAttributes(); lp.screenBrightness = f; if (lp.screenBrightness > 1.0f) lp.screenBrightness = 1.0f; else if (lp.screenBrightness < 0.01f) lp.screenBrightness = 0.01f; context.getWindow().setAttributes(lp); } // private static final long NO_STORAGE_ERROR = -1L; private static final long CANNOT_STAT_ERROR = -2L; /** 检测磁盘状态 */ // public static int getStorageStatus(boolean mayHaveSd) { // long remaining = mayHaveSd ? getAvailableStorage() : NO_STORAGE_ERROR; // if (remaining == NO_STORAGE_ERROR) { // return CommonStatus.STORAGE_STATUS_NONE; // } // return remaining < CommonConstants.LOW_STORAGE_THRESHOLD ? // CommonStatus.STORAGE_STATUS_LOW : CommonStatus.STORAGE_STATUS_OK; // } public static long getAvailableStorage() { try { String storageDirectory = Environment.getExternalStorageDirectory() .toString(); StatFs stat = new StatFs(storageDirectory); return (long) stat.getAvailableBlocks() * (long) stat.getBlockSize(); } catch (RuntimeException ex) { // if we can't stat the filesystem then we don't know how many // free bytes exist. It might be zero but just leave it // blank since we really don't know. return CANNOT_STAT_ERROR; } } /** 隐藏软键盘 */ public static void hideSoftInput(Context ctx, View v) { InputMethodManager imm = (InputMethodManager) ctx .getSystemService(Context.INPUT_METHOD_SERVICE); // 这个方法可以实现输入法在窗口上切换显示,如果输入法在窗口上已经显示,则隐藏,如果隐藏,则显示输入法到窗口上 imm.hideSoftInputFromWindow(v.getApplicationWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS); } /** 显示软键盘 */ public static void showSoftInput(Context ctx) { InputMethodManager imm = (InputMethodManager) ctx .getSystemService(Context.INPUT_METHOD_SERVICE); imm.toggleSoftInput(0, InputMethodManager.SHOW_FORCED);// (v, // InputMethodManager.SHOW_FORCED); } /** * 软键盘是否已经打开 * * @return */ protected boolean isHardKeyboardOpen(Context ctx) { return ctx.getResources().getConfiguration().hardKeyboardHidden == Configuration.HARDKEYBOARDHIDDEN_NO; } public static String getCpuInfo() { String cpuInfo = ""; try { if (new File("/proc/cpuinfo").exists()) { FileReader fr = new FileReader("/proc/cpuinfo"); BufferedReader localBufferedReader = new BufferedReader(fr, 8192); cpuInfo = localBufferedReader.readLine(); localBufferedReader.close(); if (cpuInfo != null) { cpuInfo = cpuInfo.split(":")[1].trim().split(" ")[0]; } } } catch (IOException e) { } catch (Exception e) { } return cpuInfo; } public static void startApkActivity(final Context ctx, String packageName) { PackageManager pm = ctx.getPackageManager(); PackageInfo pi; try { pi = pm.getPackageInfo(packageName, 0); Intent intent = new Intent(Intent.ACTION_MAIN, null); intent.addCategory(Intent.CATEGORY_LAUNCHER); intent.setPackage(pi.packageName); List apps = pm.queryIntentActivities(intent, 0); ResolveInfo ri = apps.iterator().next(); if (ri != null) { String className = ri.activityInfo.name; intent.setComponent(new ComponentName(packageName, className)); ctx.startActivity(intent); } } catch (NameNotFoundException e) { Logger.e(e); } } } ================================================ FILE: app/src/main/java/com/cjj/bb/utils/DownUtil.java ================================================ /** * */ package com.cjj.bb.utils; import java.io.InputStream; import java.io.RandomAccessFile; import java.net.HttpURLConnection; import java.net.URL; /** * Description: *
网站: 疯狂Java联盟 *
Copyright (C), 2001-2014, Yeeku.H.Lee *
This program is protected by copyright laws. *
Program Name: *
Date: * @author Yeeku.H.Lee kongyeeku@163.com * @version 1.0 */ public class DownUtil { // 定义下载资源的路径 private String path; // 指定所下载的文件的保存位置 private String targetFile; // 定义需要使用多少线程下载资源 private int threadNum; // 定义下载的线程对象 private DownThread[] threads; // 定义下载的文件的总大小 private int fileSize; public DownUtil(String path, String targetFile, int threadNum) { this.path = path; this.threadNum = threadNum; // 初始化threads数组 threads = new DownThread[threadNum]; this.targetFile = targetFile; } public void download() throws Exception { URL url = new URL(path); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setConnectTimeout(5 * 1000); conn.setRequestMethod("GET"); conn.setRequestProperty( "Accept", "image/gif, image/jpeg, image/pjpeg, image/pjpeg, " + "application/x-shockwave-flash, application/xaml+xml, " + "application/vnd.ms-xpsdocument, application/x-ms-xbap, " + "application/x-ms-application, application/vnd.ms-excel, " + "application/vnd.ms-powerpoint, application/msword, */*"); conn.setRequestProperty("Accept-Language", "zh-CN"); conn.setRequestProperty("Charset", "UTF-8"); conn.setRequestProperty("Connection", "Keep-Alive"); // 得到文件大小 fileSize = conn.getContentLength(); conn.disconnect(); int currentPartSize = fileSize / threadNum + 1; RandomAccessFile file = new RandomAccessFile(targetFile, "rw"); // 设置本地文件的大小 file.setLength(fileSize); file.close(); for (int i = 0; i < threadNum; i++) { // 计算每条线程的下载的开始位置 int startPos = i * currentPartSize; // 每个线程使用一个RandomAccessFile进行下载 RandomAccessFile currentPart = new RandomAccessFile(targetFile, "rw"); // 定位该线程的下载位置 currentPart.seek(startPos); // 创建下载线程 threads[i] = new DownThread(startPos, currentPartSize, currentPart); // 启动下载线程 threads[i].start(); } } // 获取下载的完成百分比 public double getCompleteRate() { // 统计多条线程已经下载的总大小 int sumSize = 0; for (int i = 0; i < threadNum; i++) { sumSize += threads[i].length; } // 返回已经完成的百分比 return sumSize * 1.0 / fileSize; } private class DownThread extends Thread { // 当前线程的下载位置 private int startPos; // 定义当前线程负责下载的文件大小 private int currentPartSize; // 当前线程需要下载的文件块 private RandomAccessFile currentPart; // 定义已经该线程已下载的字节数 public int length; public DownThread(int startPos, int currentPartSize, RandomAccessFile currentPart) { this.startPos = startPos; this.currentPartSize = currentPartSize; this.currentPart = currentPart; } @Override public void run() { try { URL url = new URL(path); HttpURLConnection conn = (HttpURLConnection)url .openConnection(); conn.setConnectTimeout(5 * 1000); conn.setRequestMethod("GET"); conn.setRequestProperty( "Accept", "image/gif, image/jpeg, image/pjpeg, image/pjpeg, " + "application/x-shockwave-flash, application/xaml+xml, " + "application/vnd.ms-xpsdocument, application/x-ms-xbap, " + "application/x-ms-application, application/vnd.ms-excel, " + "application/vnd.ms-powerpoint, application/msword, */*"); conn.setRequestProperty("Accept-Language", "zh-CN"); conn.setRequestProperty("Charset", "UTF-8"); InputStream inStream = conn.getInputStream(); // 跳过startPos个字节,表明该线程只下载自己负责哪部分文件。 inStream.skip(this.startPos); byte[] buffer = new byte[1024]; int hasRead = 0; // 读取网络数据,并写入本地文件 while (length < currentPartSize && (hasRead = inStream.read(buffer)) > 0) { currentPart.write(buffer, 0, hasRead); // 累计该线程下载的总大小 length += hasRead; } currentPart.close(); inStream.close(); } catch (Exception e) { e.printStackTrace(); } } } } ================================================ FILE: app/src/main/java/com/cjj/bb/utils/FileUitl.java ================================================ package com.cjj.bb.utils; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.File; import java.io.FileOutputStream; import java.io.FileWriter; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import android.os.Environment; /** * 文件管理类 在以后的开发中也可以使用这个工具类,提高代码的利用性 * 只要是对SD卡的操作 * 1、获取SD卡路径 getSDPATH * 2、在SD卡上根据传入的目录名创建目录 createSDDir * 3、在创建上目录后可以在该目录上创建文件 createSDFile * 4、检测文件是否存在 isFileExist * 5、将一个InputStream写入到SD卡中 write2SDFromInput * 6、将一个字符流写入到SD卡 write2SDFromWrite * 注:如果要写入SD卡,只要调用write2SDFromInput函数即可 * @author Administrator * */ public class FileUitl { private static String SDPATH; public FileUitl(){ //得到当前设备外部存储设备的目录 SDPATH = Environment.getExternalStorageDirectory() + File.separator; } /** * 获取当前SD卡的根目录 * @return */ public String getSDPATH(){ return SDPATH; } /** * SD卡上创建目录 */ public File createSDDir(String dirName){ File dir = new File(SDPATH + dirName); System.out.println("createSDDir " + SDPATH + dirName); dir.mkdir(); return dir; } /** * SD卡上创建文件 */ public File createSDFile(String fileName)throws IOException{ File file = new File(SDPATH + fileName); System.out.println("createSDFile " + SDPATH + fileName); file.createNewFile(); return file; } /** * 判断SD卡上的文件是否存在 */ public boolean isFileExist(String fileName){ File file = new File(SDPATH + fileName); return file.exists(); } /** * 将一个InputStream字节流写入到SD卡中 */ public File write2SDFromInput(String Path, String FileName, InputStream input){ File file = null; OutputStream output = null; //创建一个写入字节流对象 try{ createSDDir(Path); //根据传入的路径创建目录 file = createSDFile(Path + FileName); //根据传入的文件名创建 output = new FileOutputStream(file); byte buffer[] = new byte[4 * 1024]; //每次读取4K int num = 0; //需要根据读取的字节大小写入文件 while((num = (input.read(buffer))) != -1){ output.write(buffer, 0, num); } output.flush(); //清空缓存 }catch (Exception e) { // TODO: handle exception e.printStackTrace(); } finally{ try{ output.close(); } catch (Exception e) { // TODO: handle exception e.printStackTrace(); } } return file; } /** * 把传入的字符流写入到SD卡中 * @param Path * @param FileName * @param input * @return */ public File write2SDFromWrite(String Path, String FileName, BufferedReader input){ File file = null; FileWriter output = null; //创建一个写入字符流对象 BufferedWriter bufw = null; try{ createSDDir(Path); //根据传入的路径创建目录 file = createSDFile(Path + FileName); //根据传入的文件名创建 output = new FileWriter(file); bufw = new BufferedWriter(output); String line = null; while((line = (input.readLine())) != null){ System.out.println("line = " + line); bufw.write(line); bufw.newLine(); } bufw.flush(); //清空缓存 }catch (Exception e) { // TODO: handle exception e.printStackTrace(); } finally{ try{ bufw.close(); } catch (Exception e) { // TODO: handle exception e.printStackTrace(); } } return file; } } ================================================ FILE: app/src/main/java/com/cjj/bb/utils/FileUtils.java ================================================ package com.cjj.bb.utils; import java.io.File; import java.io.IOException; import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import android.os.Environment; import android.os.StatFs; import android.util.Log; public class FileUtils { // http://www.fileinfo.com/filetypes/video , "dat" , "bin" , "rms" 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", "bix", "bmk", "box", "bs4", "bsf", "byu", "camre", "clpi", "cpi", "cvc", "d2v", "d3v", "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", "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" }; // http://www.fileinfo.com/filetypes/audio , "spx" , "mid" , "sf" 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", "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", "sf2", "sfk", "sfl", "shn", "sib", "sid", "sid", "smf", "smp", "snd", "snd", "snd", "sng", "sng", "sou", "sppack", "sprg", "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" }; private static final HashSet mHashVideo; private static final HashSet mHashAudio; private static final double KB = 1024.0; private static final double MB = KB * KB; private static final double GB = KB * KB * KB; static { mHashVideo = new HashSet(Arrays.asList(VIDEO_EXTENSIONS)); mHashAudio = new HashSet(Arrays.asList(AUDIO_EXTENSIONS)); } /** 是否是音频或者视频 */ public static boolean isVideoOrAudio(File f) { final String ext = getFileExtension(f); return mHashVideo.contains(ext) || mHashAudio.contains(ext); } public static boolean isVideoOrAudio(String f) { final String ext = getUrlExtension(f); return mHashVideo.contains(ext) || mHashAudio.contains(ext); } public static boolean isVideo(File f) { final String ext = getFileExtension(f); return mHashVideo.contains(ext); } /** 获取文件后缀 */ public static String getFileExtension(File f) { if (f != null) { String filename = f.getName(); int i = filename.lastIndexOf('.'); if (i > 0 && i < filename.length() - 1) { return filename.substring(i + 1).toLowerCase(); } } return null; } public static String getUrlFileName(String url) { int slashIndex = url.lastIndexOf('/'); int dotIndex = url.lastIndexOf('.'); String filenameWithoutExtension; if (dotIndex == -1) { filenameWithoutExtension = url.substring(slashIndex + 1); } else { filenameWithoutExtension = url.substring(slashIndex + 1, dotIndex); } return filenameWithoutExtension; } public static String getUrlExtension(String url) { if (!StringUtils.isEmpty(url)) { int i = url.lastIndexOf('.'); if (i > 0 && i < url.length() - 1) { return url.substring(i + 1).toLowerCase(); } } return ""; } public static String getFileNameNoEx(String filename) { if ((filename != null) && (filename.length() > 0)) { int dot = filename.lastIndexOf('.'); if ((dot > -1) && (dot < (filename.length()))) { return filename.substring(0, dot); } } return filename; } public static String showFileSize(long size) { String fileSize; if (size < KB) fileSize = size + "B"; else if (size < MB) fileSize = String.format("%.1f", size / KB) + "KB"; else if (size < GB) fileSize = String.format("%.1f", size / MB) + "MB"; else fileSize = String.format("%.1f", size / GB) + "GB"; return fileSize; } /** 显示SD卡剩余空间 */ public static String showFileAvailable() { String result = ""; if (Environment.MEDIA_MOUNTED.equals(Environment .getExternalStorageState())) { StatFs sf = new StatFs(Environment.getExternalStorageDirectory() .getPath()); long blockSize = sf.getBlockSize(); long blockCount = sf.getBlockCount(); long availCount = sf.getAvailableBlocks(); return showFileSize(availCount * blockSize) + " / " + showFileSize(blockSize * blockCount); } return result; } /** 如果不存在就创建 */ public static boolean createIfNoExists(String path) { File file = new File(path); boolean mk = false; if (!file.exists()) { mk = file.mkdirs(); } return mk; } private static HashMap mMimeType = new HashMap(); static { mMimeType.put("M1V", "video/mpeg"); mMimeType.put("MP2", "video/mpeg"); mMimeType.put("MPE", "video/mpeg"); mMimeType.put("MPG", "video/mpeg"); mMimeType.put("MPEG", "video/mpeg"); mMimeType.put("MP4", "video/mp4"); mMimeType.put("M4V", "video/mp4"); mMimeType.put("3GP", "video/3gpp"); mMimeType.put("3GPP", "video/3gpp"); mMimeType.put("3G2", "video/3gpp2"); mMimeType.put("3GPP2", "video/3gpp2"); mMimeType.put("MKV", "video/x-matroska"); mMimeType.put("WEBM", "video/x-matroska"); mMimeType.put("MTS", "video/mp2ts"); mMimeType.put("TS", "video/mp2ts"); mMimeType.put("TP", "video/mp2ts"); mMimeType.put("WMV", "video/x-ms-wmv"); mMimeType.put("ASF", "video/x-ms-asf"); mMimeType.put("ASX", "video/x-ms-asf"); mMimeType.put("FLV", "video/x-flv"); mMimeType.put("MOV", "video/quicktime"); mMimeType.put("QT", "video/quicktime"); mMimeType.put("RM", "video/x-pn-realvideo"); mMimeType.put("RMVB", "video/x-pn-realvideo"); mMimeType.put("VOB", "video/dvd"); mMimeType.put("DAT", "video/dvd"); mMimeType.put("AVI", "video/x-divx"); mMimeType.put("OGV", "video/ogg"); mMimeType.put("OGG", "video/ogg"); mMimeType.put("VIV", "video/vnd.vivo"); mMimeType.put("VIVO", "video/vnd.vivo"); mMimeType.put("WTV", "video/wtv"); mMimeType.put("AVS", "video/avs-video"); mMimeType.put("SWF", "video/x-shockwave-flash"); mMimeType.put("YUV", "video/x-raw-yuv"); } /** 获取MIME */ public static String getMimeType(String path) { int lastDot = path.lastIndexOf("."); if (lastDot < 0) return null; return mMimeType.get(path.substring(lastDot + 1).toUpperCase()); } /** 多个SD卡时 取外置SD卡 */ public static String getExternalStorageDirectory() { // 参考文章 // http://blog.csdn.net/bbmiku/article/details/7937745 Map map = System.getenv(); String[] values = new String[map.values().size()]; map.values().toArray(values); String path = values[values.length - 1]; Log.e("nmbb", "FileUtils.getExternalStorageDirectory : " + path); if (path.startsWith("/mnt/") && !Environment.getExternalStorageDirectory().getAbsolutePath() .equals(path)) return path; else return null; } public static String getCanonical(File f) { if (f == null) return null; try { return f.getCanonicalPath(); } catch (IOException e) { return f.getAbsolutePath(); } } public static boolean sdAvailable() { return Environment.MEDIA_MOUNTED_READ_ONLY.equals(Environment .getExternalStorageState()) || Environment.MEDIA_MOUNTED.equals(Environment .getExternalStorageState()); } } ================================================ FILE: app/src/main/java/com/cjj/bb/utils/FractionalTouchDelegate.java ================================================ /* * Copyright (C) 2012 YIXIA.COM * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.cjj.bb.utils; import android.graphics.Rect; import android.graphics.RectF; import android.view.MotionEvent; import android.view.TouchDelegate; import android.view.View; /** * {@link android.view.TouchDelegate} that gates {@link android.view.MotionEvent} instances by comparing * then against fractional dimensions of the source view. *

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

* One example is catching touches that occur in the top-right quadrant of * {@code sourceParent}, and relaying them to {@code targetChild}. This could be * done with: * FractionalTouchDelegate.setupDelegate(sourceParent, targetChild, new RectF(0.5f, 0f, 1f, 0.5f)); * */ public class FractionalTouchDelegate extends TouchDelegate { private View mSource; private View mTarget; private RectF mSourceFraction; private Rect mScrap = new Rect(); /** Cached full dimensions of {@link #mSource}. */ private Rect mSourceFull = new Rect(); /** Cached projection of {@link #mSourceFraction} onto {@link #mSource}. */ private Rect mSourcePartial = new Rect(); private boolean mDelegateTargeted; public FractionalTouchDelegate(View source, View target, RectF sourceFraction) { super(new Rect(0, 0, 0, 0), target); mSource = source; mTarget = target; mSourceFraction = sourceFraction; } /** * Helper to create and setup a {@link com.cjj.bb.utils.FractionalTouchDelegate} between the * given {@link android.view.View}. * * @param source Larger source {@link android.view.View}, usually a parent, that will be * assigned {@link android.view.View#setTouchDelegate(android.view.TouchDelegate)}. * @param target Smaller target {@link android.view.View} which will receive * {@link android.view.MotionEvent} that land in requested fractional area. * @param sourceFraction Fractional area projected onto source {@link android.view.View} * which determines when {@link android.view.MotionEvent} will be passed to * target {@link android.view.View}. */ public static void setupDelegate(View source, View target, RectF sourceFraction) { source.setTouchDelegate(new FractionalTouchDelegate(source, target, sourceFraction)); } /** * Consider updating {@link #mSourcePartial} when {@link #mSource} * dimensions have changed. */ private void updateSourcePartial() { mSource.getHitRect(mScrap); if (!mScrap.equals(mSourceFull)) { // Copy over and calculate fractional rectangle mSourceFull.set(mScrap); final int width = mSourceFull.width(); final int height = mSourceFull.height(); mSourcePartial.left = (int) (mSourceFraction.left * width); mSourcePartial.top = (int) (mSourceFraction.top * height); mSourcePartial.right = (int) (mSourceFraction.right * width); mSourcePartial.bottom = (int) (mSourceFraction.bottom * height); } } @Override public boolean onTouchEvent(MotionEvent event) { updateSourcePartial(); // The logic below is mostly copied from the parent class, since we // can't update private mBounds variable. // http://android.git.kernel.org/?p=platform/frameworks/base.git;a=blob; // f=core/java/android/view/TouchDelegate.java;hb=eclair#l98 final Rect sourcePartial = mSourcePartial; final View target = mTarget; int x = (int)event.getX(); int y = (int)event.getY(); boolean sendToDelegate = false; boolean hit = true; boolean handled = false; switch (event.getAction()) { case MotionEvent.ACTION_DOWN: if (sourcePartial.contains(x, y)) { mDelegateTargeted = true; sendToDelegate = true; } break; case MotionEvent.ACTION_UP: case MotionEvent.ACTION_MOVE: sendToDelegate = mDelegateTargeted; if (sendToDelegate) { if (!sourcePartial.contains(x, y)) { hit = false; } } break; case MotionEvent.ACTION_CANCEL: sendToDelegate = mDelegateTargeted; mDelegateTargeted = false; break; } if (sendToDelegate) { if (hit) { event.setLocation(target.getWidth() / 2, target.getHeight() / 2); } else { event.setLocation(-1, -1); } handled = target.dispatchTouchEvent(event); } return handled; } } ================================================ FILE: app/src/main/java/com/cjj/bb/utils/HttpDownloader.java ================================================ package com.cjj.bb.utils; import java.io.BufferedReader; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.UnsupportedEncodingException; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URL; import org.apache.http.util.EncodingUtils; import android.util.Log; import android.util.Xml.Encoding; public class HttpDownloader { private URL url = null; /** * 根据URL下载文件,前提是这个文件当中的内容是文本,函数的返回值就是文件当中的内容 * 1.创建一个URL对象 * 2.通过URL对象,创建一个HttpURLConnection对象 * 3.得到InputStram * 4.从InputStream当中读取数据 * * @param urlStr * @return */ public String download(String urlstr) { StringBuffer sb = new StringBuffer(); String line = null; BufferedReader buffer = null; String xmlString = ""; try { // 创建一个URL对象 url = new URL(urlstr); // 创建一个Http连接 HttpURLConnection urlConn = (HttpURLConnection) url .openConnection(); // 使用IO流读取数据 buffer = new BufferedReader(new InputStreamReader(urlConn.getInputStream(),"utf-8")); // 防止中文出现乱码 gb2312 utf-8 for(String temp = buffer.readLine(); temp != null;xmlString += temp ,temp = buffer.readLine()); // 去除字符串中的换行符,制表符,回车符。 xmlString = xmlString.replaceAll("/n|/t|/r", ""); // while ((line = buffer.readLine()) != null) { // sb.append(line); // } } catch (Exception e) { e.printStackTrace(); } finally { try { buffer.close(); } catch (Exception e) { e.printStackTrace(); } } return xmlString; } /** * 可以下载字节流文件到SD卡中 * * @param urlstr 要下载文件的URI地址 * @param Path 在SD卡上文件夹的路径 * @param FileName 在SD卡上文件的名称 * @return 该函数返回整型:-1代表下载失败,0代表下载成功,1代表文件已经存在 */ public int download(String urlstr, String Path, String FileName) { InputStream inputstream = null; BufferedReader buffer = null; try { FileUitl fileUitls = new FileUitl(); System.out.println(Path + FileName); if (fileUitls.isFileExist(Path + FileName)) { return 1; } else { // 获取URI中的字节流 inputstream = getInputStreamFromUrl(urlstr); // 把字节流转换成字符流 buffer = new BufferedReader(new InputStreamReader(inputstream, "gb2312")); // 防止中文出现乱码 UTF-8 File resultFile = fileUitls.write2SDFromWrite(Path, FileName, buffer); if (resultFile == null) { return -1; } } } catch (Exception e) { // TODO: handle exception e.printStackTrace(); return -1; } finally { try { if(buffer != null) buffer.close(); } catch (Exception e) { // TODO: handle exception e.printStackTrace(); } } return 0; } /** * 可以下载字符流和字节流文件到SD卡中 * * @param urlstr * @param Path * @param FileName * @return 该函数返回整型:-1代表下载失败,0代表下载成功,1代表文件已经存在 */ public int downFile(String urlstr, String Path, String FileName) { InputStream inputstream = null; try { FileUitl fileUitls = new FileUitl(); if (fileUitls.isFileExist(Path + FileName)) { return 1; } else { inputstream = getInputStreamFromUrl(urlstr); File resultFile = fileUitls.write2SDFromInput(Path, FileName, inputstream); if (resultFile == null) { return -1; } } } catch (Exception e) { // TODO: handle exception e.printStackTrace(); return -1; } finally { try { inputstream.close(); } catch (Exception e) { // TODO: handle exception e.printStackTrace(); } } return 0; } /** * 根据URL得到输入流 * * @param urlstr * @return * @throws java.net.MalformedURLException * @throws java.io.IOException */ private InputStream getInputStreamFromUrl(String urlstr) throws MalformedURLException, IOException { // TODO Auto-generated method stub url = new URL(urlstr); HttpURLConnection urlConn = (HttpURLConnection) url.openConnection(); InputStream inputStream = urlConn.getInputStream(); return inputStream; } // 以下是测试字符编码的 public static void testCharset(String datastr){ try { String temp = new String(datastr.getBytes(), "GBK"); Log.v("TestCharset","****** getBytes() -> GBK ******/n"+temp); temp = new String(datastr.getBytes("GBK"), "UTF-8"); Log.v("TestCharset","****** GBK -> UTF-8 *******/n"+temp); temp = new String(datastr.getBytes("GBK"), "ISO-8859-1"); Log.v("TestCharset","****** GBK -> ISO-8859-1 *******/n"+temp); temp = new String(datastr.getBytes("ISO-8859-1"), "UTF-8"); Log.v("TestCharset","****** ISO-8859-1 -> UTF-8 *******/n"+temp); temp = new String(datastr.getBytes("ISO-8859-1"), "GBK"); Log.v("TestCharset","****** ISO-8859-1 -> GBK *******/n"+temp); temp = new String(datastr.getBytes("UTF-8"), "GBK"); Log.v("TestCharset","****** UTF-8 -> GBK *******/n"+temp); temp = new String(datastr.getBytes("UTF-8"), "ISO-8859-1"); Log.v("TestCharset","****** UTF-8 -> ISO-8859-1 *******/n"+temp); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } } } ================================================ FILE: app/src/main/java/com/cjj/bb/utils/HttpUtil.java ================================================ package com.cjj.bb.utils; import java.io.BufferedInputStream; import java.io.BufferedReader; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.PrintWriter; import java.net.ConnectException; import java.net.HttpURLConnection; import java.net.URI; import java.net.URL; import java.net.URLConnection; import java.util.ArrayList; import java.util.List; import java.util.zip.DataFormatException; import java.util.zip.GZIPInputStream; import java.util.zip.ZipInputStream; import javax.xml.parsers.SAXParser; import javax.xml.parsers.SAXParserFactory; import org.apache.http.Header; import org.apache.http.HttpClientConnection; import org.apache.http.HttpResponse; import org.apache.http.NameValuePair; import org.apache.http.ProtocolException; import org.apache.http.client.ClientProtocolException; import org.apache.http.client.HttpClient; import org.apache.http.client.RedirectHandler; import org.apache.http.client.entity.UrlEncodedFormEntity; import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpPost; import org.apache.http.cookie.Cookie; import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.message.BasicNameValuePair; import org.apache.http.params.BasicHttpParams; import org.apache.http.params.HttpConnectionParams; import org.apache.http.protocol.HTTP; import org.apache.http.protocol.HttpContext; import org.apache.http.util.ByteArrayBuffer; import org.apache.http.util.EncodingUtils; import org.apache.http.util.EntityUtils; import org.jsoup.Jsoup; import org.jsoup.helper.HttpConnection.Response; import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.util.Log; import android.webkit.WebView; import android.webkit.WebViewClient; public class HttpUtil { public static String cookieName = ""; public static String cookieValue = ""; public static String hostBase = ""; public static String getHtmlString(String urlString) { try { URL url = new URL(urlString); URLConnection ucon = url.openConnection(); InputStream instr = ucon.getInputStream(); BufferedInputStream bis = new BufferedInputStream(instr); ByteArrayBuffer baf = new ByteArrayBuffer(500); int current = 0; while ((current = bis.read()) != -1) { baf.append((byte) current); } return EncodingUtils.getString(baf.toByteArray(), "utf-8"); } catch (Exception e) { Log.d("win","lllll"+e.toString()); return ""; } } public static String getXmlDecompress(String urlString) { Response rsp = null; String temp = ""; try { rsp = (Response) Jsoup.connect(urlString).execute(); temp = EncodingUtils.getString(CompressionTools.decompressXML(rsp.bodyAsBytes()), "utf-8"); Log.d("TAG","=======>Xml解压成功"); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); Log.d("TAG","=======>Xml解压失败:"+e.toString()); } catch (DataFormatException e) { // TODO Auto-generated catch block e.printStackTrace(); Log.d("TAG","=======>Xml解压失败:"+e.toString()); } return temp; } public static String sendPost(String url, String params) { PrintWriter out = null; BufferedReader in = null; String result = ""; try { URL realUrl = new URL(url); // 打开和URL之间的连接 URLConnection conn = realUrl.openConnection(); // 设置通用的请求属性 conn.setRequestProperty("accept", "*/*"); conn.setRequestProperty("connection", "Keep-Alive"); conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)"); // 发送POST请求必须设置如下两行 conn.setDoOutput(true); conn.setDoInput(true); // 获取URLConnection对象对应的输出流 out = new PrintWriter(conn.getOutputStream()); // 发送请求参数 out.print(params); //② // flush输出流的缓冲 out.flush(); // 定义BufferedReader输入流来读取URL的响应 in = new BufferedReader( new InputStreamReader(conn.getInputStream())); String line; while ((line = in.readLine()) != null) { result += "\n" + line; } } catch (Exception e) { System.out.println("发送POST请求出现异常!" + e); e.printStackTrace(); } // 使用finally块来关闭输出流、输入流 finally { try { if (out != null) { out.close(); } if (in != null) { in.close(); } } catch (IOException ex) { ex.printStackTrace(); } } return result; } public static String httpGetHost(String url) { HttpGet httpget = new HttpGet(url); String strResult = ""; BasicHttpParams httpParams = new BasicHttpParams(); HttpConnectionParams.setConnectionTimeout(httpParams, 5000); HttpConnectionParams.setSoTimeout(httpParams, 5000); HttpClient httpclient; try { httpclient = new DefaultHttpClient(httpParams); HttpResponse response = httpclient.execute(httpget); System.out.println(response.getStatusLine().getStatusCode()); if (response.getStatusLine().getStatusCode() == 200) { strResult = EntityUtils.toString(response.getEntity(), HTTP.UTF_8); } } catch (ConnectException e) { e.printStackTrace(); System.out.println("hosterror"); } catch (ClientProtocolException e) { System.out.println("Client"); e.printStackTrace(); } catch (IOException e) { System.out.println("IO"); e.printStackTrace(); } return strResult; } public static String httpGet(String url) { System.out.println("httpGet" + url); HttpGet httpget = new HttpGet(url); String strResult = null; BasicHttpParams httpParams = new BasicHttpParams(); HttpConnectionParams.setConnectionTimeout(httpParams, 10000); HttpConnectionParams.setSoTimeout(httpParams, 10000); HttpClient httpclient; try { httpclient = new DefaultHttpClient(httpParams); httpget.setHeader("Cookie", cookieName + "=" + cookieValue); HttpResponse response = httpclient.execute(httpget); System.out.println(response.getStatusLine().getStatusCode()); if (response.getStatusLine().getStatusCode() == 200) { strResult = EntityUtils.toString(response.getEntity(), HTTP.UTF_8); // System.out.println(strResult); System.out.println("getFinish"); } } catch (ConnectException e) { e.printStackTrace(); } catch (ClientProtocolException e) { System.out.println("Client"); e.printStackTrace(); } catch (IOException e) { System.out.println("IO"); e.printStackTrace(); } return strResult; } public static String httpGetNoResult(String url) { System.out.println("httpGetNo" + url); HttpGet httpget = new HttpGet(hostBase + url); String strResult = ""; BasicHttpParams httpParams = new BasicHttpParams(); HttpConnectionParams.setConnectionTimeout(httpParams, 10000); HttpConnectionParams.setSoTimeout(httpParams, 10000); HttpClient httpclient; try { httpclient = new DefaultHttpClient(httpParams); httpget.setHeader("Cookie", cookieName + "=" + cookieValue); HttpResponse response = httpclient.execute(httpget); System.out.println(response.getStatusLine().getStatusCode()); /* * if(response.getStatusLine().getStatusCode() == 200){ strResult = * EntityUtils.toString(response.getEntity(), HTTP.UTF_8); * System.out.println(strResult); System.out.println("getFinish"); } */ } catch (Exception e) { e.printStackTrace(); strResult = "error"; } return strResult; } public static Bitmap HttpGetBmp(String url) { HttpGet httpget = new HttpGet(url); BasicHttpParams httpParams = new BasicHttpParams(); HttpConnectionParams.setConnectionTimeout(httpParams, 10000); HttpConnectionParams.setSoTimeout(httpParams, 10000); Bitmap bitmap = null; try { HttpClient httpclient = new DefaultHttpClient(httpParams); HttpResponse response = httpclient.execute(httpget); InputStream is = response.getEntity().getContent(); byte[] bytes = new byte[1024]; ByteArrayOutputStream bos = new ByteArrayOutputStream(); int count = 0; while ((count = is.read(bytes)) != -1) { System.out.println("readBitmap"); bos.write(bytes, 0, count); } byte[] byteArray = bos.toByteArray(); bitmap = BitmapFactory.decodeByteArray(byteArray, 0, byteArray.length); is.close(); bos.close(); } catch (Exception e) { e.printStackTrace(); } return bitmap; } public static InputStream HttpGetBmpInputStream(String url) { HttpGet httpget = new HttpGet(url); BasicHttpParams httpParams = new BasicHttpParams(); HttpConnectionParams.setConnectionTimeout(httpParams, 10000); HttpConnectionParams.setSoTimeout(httpParams, 10000); InputStream is = null; try { HttpClient httpclient = new DefaultHttpClient(httpParams); HttpResponse response = httpclient.execute(httpget); is = response.getEntity().getContent(); } catch (Exception e) { e.printStackTrace(); } return is; } public static Integer GetCookie(String url, String number, String pw, String select, String host) { System.out.println("GetCookie"); int result = 4; HttpPost httpPost = new HttpPost(hostBase + url); List nvps = new ArrayList(); nvps.add(new BasicNameValuePair("number", number)); nvps.add(new BasicNameValuePair("passwd", pw)); nvps.add(new BasicNameValuePair("select", select)); BasicHttpParams httpParams = new BasicHttpParams(); HttpConnectionParams.setConnectionTimeout(httpParams, 10000); HttpConnectionParams.setSoTimeout(httpParams, 10000); try { DefaultHttpClient httpClient = new DefaultHttpClient(httpParams); httpClient.setRedirectHandler(new RedirectHandler() { @Override public boolean isRedirectRequested(HttpResponse response, HttpContext context) { return false; } @Override public URI getLocationURI(HttpResponse response, HttpContext context) throws ProtocolException { return null; } }); httpPost.setEntity(new UrlEncodedFormEntity(nvps, HTTP.UTF_8)); HttpResponse response = httpClient.execute(httpPost); System.out.println(response.getStatusLine().getStatusCode()); if (response.getStatusLine().getStatusCode() == 200) { return 2; } else if (response.getStatusLine().getStatusCode() == 302) { Header[] headers = response.getHeaders("Location"); if (headers != null && headers.length > 0) { List list = httpClient.getCookieStore() .getCookies(); for (Cookie c : list) { cookieName = c.getName(); cookieValue = c.getValue(); } System.out.println(cookieName + cookieValue); return 3; } } else if (response.getStatusLine().getStatusCode() == 404) { return -1; } } catch (Exception e) { e.printStackTrace(); } return result; } public static String httpGetCookie(String url) { System.out.println("httpGetCookie" + url); HttpGet httpget = new HttpGet(hostBase + url); String strResult = ""; BasicHttpParams httpParams = new BasicHttpParams(); HttpConnectionParams.setConnectionTimeout(httpParams, 15000); HttpConnectionParams.setSoTimeout(httpParams, 15000); try { DefaultHttpClient httpClient = new DefaultHttpClient(httpParams); httpClient.setRedirectHandler(new RedirectHandler() { @Override public boolean isRedirectRequested(HttpResponse response, HttpContext context) { return false; } @Override public URI getLocationURI(HttpResponse response, HttpContext context) throws ProtocolException { return null; } }); httpget.setHeader("Cookie", cookieName + "=" + cookieValue); HttpResponse response = httpClient.execute(httpget); if (response.getStatusLine().getStatusCode() == 200) { strResult = EntityUtils.toString(response.getEntity(), HTTP.UTF_8); } else if (response.getStatusLine().getStatusCode() == 302) { strResult = "302"; // cookieʧЧ�������ض����־�������µ�¼��ȡ } else if (response.getStatusLine().getStatusCode() == 404) { strResult = "-1"; } } catch (Exception e) { e.printStackTrace(); strResult = "4"; } return strResult; } public static String httpPostCookie(String url, String id, String data) { System.out.println("httpPostCookie" + url); String result = "4"; HttpPost httpPost = new HttpPost(hostBase + url); List nvps = new ArrayList(); nvps.add(new BasicNameValuePair("marc_no", id)); nvps.add(new BasicNameValuePair("r_content", data)); BasicHttpParams httpParams = new BasicHttpParams(); HttpConnectionParams.setConnectionTimeout(httpParams, 10000); HttpConnectionParams.setSoTimeout(httpParams, 10000); try { DefaultHttpClient httpClient = new DefaultHttpClient(httpParams); httpClient.setRedirectHandler(new RedirectHandler() { @Override public boolean isRedirectRequested(HttpResponse response, HttpContext context) { return false; } @Override public URI getLocationURI(HttpResponse response, HttpContext context) throws ProtocolException { return null; } }); httpPost.setHeader("Cookie", cookieName + "=" + cookieValue); httpPost.setEntity(new UrlEncodedFormEntity(nvps, HTTP.UTF_8)); HttpResponse response = httpClient.execute(httpPost); System.out.println(response.getStatusLine().getStatusCode()); System.out.println(EntityUtils.toString(response.getEntity(), HTTP.UTF_8) + "add"); if (response.getStatusLine().getStatusCode() == 200) { return "2"; } else if (response.getStatusLine().getStatusCode() == 302) { Header[] headers = response.getHeaders("Location"); if (headers != null && headers.length > 0) { System.out.println(headers[0].getValue()); return "3"; } } else if (response.getStatusLine().getStatusCode() == 404) { return "-1"; } } catch (Exception e) { e.printStackTrace(); } return result; } public static int getCookie(String url) { System.out.println("getCookie" + url); HttpGet httpGet = new HttpGet(hostBase + url); try { DefaultHttpClient httpClient = new DefaultHttpClient(); httpClient.setRedirectHandler(new RedirectHandler() { @Override public boolean isRedirectRequested(HttpResponse response, HttpContext context) { return false; } @Override public URI getLocationURI(HttpResponse response, HttpContext context) throws ProtocolException { return null; } }); HttpResponse response = httpClient.execute(httpGet); System.out.println(response.getStatusLine().getStatusCode()); System.out.println(EntityUtils.toString(response.getEntity(), HTTP.UTF_8) + "add"); if (response.getStatusLine().getStatusCode() == 200) { Header[] heads = response.getAllHeaders(); System.out.println(heads.length); for (Header header : heads) { System.out.println(header.getName() + " = " + header.getValue()); } return 2; } else if (response.getStatusLine().getStatusCode() == 302) { Header[] headers = response.getHeaders("Location"); if (headers != null && headers.length > 0) { System.out.println(headers[0].getValue()); return 3; } } else if (response.getStatusLine().getStatusCode() == 404) { return -1; } } catch (Exception e) { e.printStackTrace(); } return 1; } } ================================================ FILE: app/src/main/java/com/cjj/bb/utils/ImageUtils.java ================================================ package com.cjj.bb.utils; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import android.annotation.TargetApi; import android.content.Context; import android.graphics.Bitmap; import android.graphics.Bitmap.Config; import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.Matrix; import android.graphics.Paint; import android.graphics.PixelFormat; import android.graphics.PorterDuff.Mode; import android.graphics.PorterDuffXfermode; import android.graphics.Rect; import android.graphics.RectF; import android.graphics.drawable.Drawable; import android.net.Uri; import android.os.Build; public class ImageUtils { // http://zhuixinjian.javaeye.com/blog/743672 // 图片圆角 // 图片叠加 // 图片缩放 // 图片旋转 @TargetApi(Build.VERSION_CODES.HONEYCOMB_MR1) public static int getBitmapSize(Bitmap bitmap) { if (DeviceUtils.hasHoneycombMR1()) { return bitmap.getByteCount(); } // Pre HC-MR1 return bitmap.getRowBytes() * bitmap.getHeight(); } /** 旋转图片 */ public static Bitmap rotate(Bitmap b, int degrees) { if (degrees != 0 && b != null) { Matrix m = new Matrix(); m.setRotate(degrees, (float) b.getWidth() / 2, (float) b.getHeight() / 2); try { Bitmap b2 = Bitmap.createBitmap(b, 0, 0, b.getWidth(), b.getHeight(), m, true); if (b != b2) { b.recycle(); b = b2; } } catch (OutOfMemoryError ex) { Logger.e(ex); } catch (Exception ex) { Logger.e(ex); } } return b; } /** * Decode and sample down a bitmap from a file to the requested width and * height. * * @param filename * The full path of the file to decode * @param reqWidth * The requested width of the resulting bitmap * @param reqHeight * The requested height of the resulting bitmap * @return A bitmap sampled down from the original with the same aspect * ratio and dimensions that are equal to or greater than the * requested width and height */ public static synchronized Bitmap decodeSampledBitmapFromFile( String filename, int reqWidth, int reqHeight) { // First decode with inJustDecodeBounds=true to check dimensions final BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true; BitmapFactory.decodeFile(filename, options); // Calculate inSampleSize options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight); // Decode bitmap with inSampleSize set options.inJustDecodeBounds = false; return BitmapFactory.decodeFile(filename, options); } /** * Calculate an inSampleSize for use in a * {@link android.graphics.BitmapFactory.Options} object when decoding * bitmaps using the decode* methods from {@link android.graphics.BitmapFactory}. This * implementation calculates the closest inSampleSize that will result in * the final decoded bitmap having a width and height equal to or larger * than the requested width and height. This implementation does not ensure * a power of 2 is returned for inSampleSize which can be faster when * decoding but results in a larger bitmap which isn't as useful for caching * purposes. * * @param options * An options object with out* params already populated (run * through a decode* method with inJustDecodeBounds==true * @param reqWidth * The requested width of the resulting bitmap * @param reqHeight * The requested height of the resulting bitmap * @return The value to be used for inSampleSize */ public static int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) { // Raw height and width of image final int height = options.outHeight; final int width = options.outWidth; int inSampleSize = 1; if (height > reqHeight || width > reqWidth) { if (width > height) { inSampleSize = Math.round((float) height / (float) reqHeight); } else { inSampleSize = Math.round((float) width / (float) reqWidth); } // This offers some additional logic in case the image has a strange // aspect ratio. For example, a panorama may have a much larger // width than height. In these cases the total pixels might still // end up being too large to fit comfortably in memory, so we should // be more aggressive with sample down the image (=larger // inSampleSize). final float totalPixels = width * height; // Anything more than 2x the requested pixels we'll sample down // further. final float totalReqPixelsCap = reqWidth * reqHeight * 2; while (totalPixels / (inSampleSize * inSampleSize) > totalReqPixelsCap) { inSampleSize++; } } return inSampleSize; } public static boolean saveBitmap(String path, Bitmap bitmap) { return saveBitmap(new File(path), bitmap); } /** 保存图片到文件 */ public static boolean saveBitmap(File f, Bitmap bitmap) { if (bitmap == null || bitmap.isRecycled()) return false; FileOutputStream fOut = null; try { if (f.exists()) f.createNewFile(); fOut = new FileOutputStream(f); bitmap.compress(Bitmap.CompressFormat.PNG, 100, fOut); fOut.flush(); return true; } catch (FileNotFoundException e) { Logger.e(e); } catch (IOException e) { Logger.e(e); } catch (Exception e) { Logger.e(e); } finally { if (fOut != null) { try { fOut.close(); } catch (IOException e) { Logger.e(e); } } } return false; } public static Bitmap decodeUriAsBitmap(Context ctx, Uri uri) { Bitmap bitmap = null; try { final BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true; // options.outWidth = reqWidth; // options.outHeight = reqHeight; BitmapFactory.decodeStream(ctx.getContentResolver() .openInputStream(uri), null, options); Logger.i("orgi:" + options.outWidth + "x" + options.outHeight); int be = (int) (options.outHeight / (float) 350); if (be <= 0) be = 1; options.inSampleSize = be;// calculateInSampleSize(options, // reqWidth, reqHeight); Logger.i("inSampleSize:" + options.inSampleSize); options.inJustDecodeBounds = false; bitmap = BitmapFactory.decodeStream(ctx.getContentResolver() .openInputStream(uri), null, options); } catch (FileNotFoundException e) { Logger.e(e); } catch (OutOfMemoryError e) { Logger.e(e); } return bitmap; } public static Bitmap zoomBitmap(Bitmap bitmap, int w, int h) { int width = bitmap.getWidth(); int height = bitmap.getHeight(); Matrix matrix = new Matrix(); float scaleWidht = ((float) w / width); float scaleHeight = ((float) h / height); matrix.postScale(scaleWidht, scaleHeight); Bitmap newbmp = Bitmap.createBitmap(bitmap, 0, 0, width, height, matrix, true); return newbmp; } public static Bitmap drawableToBitmap(Drawable drawable) { int width = drawable.getIntrinsicWidth(); int height = drawable.getIntrinsicHeight(); Bitmap bitmap = Bitmap.createBitmap(width, height, drawable .getOpacity() != PixelFormat.OPAQUE ? Config.ARGB_8888 : Config.RGB_565); Canvas canvas = new Canvas(bitmap); drawable.setBounds(0, 0, width, height); drawable.draw(canvas); return bitmap; } /** * 获取图片圆角 * * @param bitmap * @param roundPx * 圆角度数 * @return */ public static Bitmap getRoundedCornerBitmap(Bitmap bitmap, float roundPx) { Bitmap output = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Config.ARGB_8888); Canvas canvas = new Canvas(output); final int color = 0xff424242; final Paint paint = new Paint(); final Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight()); final RectF rectF = new RectF(rect); paint.setAntiAlias(true); canvas.drawARGB(0, 0, 0, 0); paint.setColor(color); canvas.drawRoundRect(rectF, roundPx, roundPx, paint); paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN)); canvas.drawBitmap(bitmap, rect, rect, paint); return output; } /** * 转行Drawable为Bitmap对象 * * @param drawable * @return */ public static Bitmap toBitmap(Drawable drawable) { int width = drawable.getIntrinsicWidth(); int height = drawable.getIntrinsicHeight(); Bitmap bitmap = Bitmap.createBitmap(width, height, drawable .getOpacity() != PixelFormat.OPAQUE ? Config.ARGB_8888 : Config.RGB_565); Canvas canvas = new Canvas(bitmap); drawable.setBounds(0, 0, width, height); drawable.draw(canvas); return bitmap; } /** * 缩放图片 * * @param src * 缩放原图 * @param dstWidth * 缩放后宽 * @param dstHeight * 缩放后高 * @return */ public static Bitmap scaledBitmap(Bitmap src, int dstWidth, int dstHeight) { // 原图不能为空也不能已经被回收掉了 Bitmap result = null; if (src != null && !src.isRecycled()) { if (src.getWidth() == dstWidth && src.getHeight() == dstHeight) { result = src; } else { result = Bitmap.createScaledBitmap(src, dstWidth, dstHeight, true); } } // ThumbnailUtils.extractThumbnail(source, width, height) return result; } /** * 按比例缩放图片 * * @param src * @param scale * 例如2 就是二分之一 * @return */ public static Bitmap scaledBitmap(Bitmap src, int scale) { if (src == null || src.isRecycled()) { return null; } int dstWidth = src.getWidth() / scale; int dstHeight = src.getHeight() / scale; return Bitmap.createScaledBitmap(src, dstWidth, dstHeight, true); } /** * 将图片转换成字节数组 * * @param bitmap * @return */ public static byte[] toBytes(Bitmap bitmap) { ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); bitmap.compress(Bitmap.CompressFormat.PNG, 100, outputStream); return outputStream.toByteArray(); } } ================================================ FILE: app/src/main/java/com/cjj/bb/utils/IntentHelper.java ================================================ /* * Copyright (C) 2012 YIXIA.COM * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.cjj.bb.utils; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; import android.content.pm.ResolveInfo; import android.net.Uri; import android.os.Parcelable; import android.text.Html; import io.vov.vitamio.utils.Log; public final class IntentHelper { public static final String MEDIA_PATTERN = "(http[s]?://)+([\\w-]+\\.)+[\\w-]+([\\w-./?%&=]*)?"; private static final Pattern mMediaPattern; static { mMediaPattern = Pattern.compile(MEDIA_PATTERN); } public static Uri getIntentUri(Intent intent) { Uri result = null; if (intent != null) { result = intent.getData(); if (result == null) { final String type = intent.getType(); String sharedUrl = intent.getStringExtra(Intent.EXTRA_TEXT); if (!StringUtils.isEmpty(sharedUrl)) { if ("text/plain".equals(type) && sharedUrl != null) { result = getTextUri(sharedUrl); } else if ("text/html".equals(type) && sharedUrl != null) { result = getTextUri(Html.fromHtml(sharedUrl).toString()); } } else { Parcelable parce = intent.getParcelableExtra(Intent.EXTRA_STREAM); if (parce != null) result = (Uri) parce; } } } return result; } private static Uri getTextUri(String sharedUrl) { Matcher matcher = mMediaPattern.matcher(sharedUrl); if (matcher.find()) { sharedUrl = matcher.group(); if (!StringUtils.isEmpty(sharedUrl)) { return Uri.parse(sharedUrl); } } return null; } public static boolean existPackage(final Context ctx, String packageName) { if (!StringUtils.isEmpty(packageName)) { for (PackageInfo p : ctx.getPackageManager().getInstalledPackages(0)) { if (packageName.equals(p.packageName)) return true; } } return false; } public static void startApkActivity(final Context ctx, String packageName) { PackageManager pm = ctx.getPackageManager(); PackageInfo pi; try { pi = pm.getPackageInfo(packageName, 0); Intent intent = new Intent(Intent.ACTION_MAIN, null); intent.setPackage(pi.packageName); List apps = pm.queryIntentActivities(intent, 0); ResolveInfo ri = apps.iterator().next(); if (ri != null) { String className = ri.activityInfo.name; intent.setComponent(new ComponentName(packageName, className)); ctx.startActivity(intent); } } catch (NameNotFoundException e) { Log.e("startActivity", e); } } } ================================================ FILE: app/src/main/java/com/cjj/bb/utils/JsoupUtil.java ================================================ package com.cjj.bb.utils; import java.util.ArrayList; import java.util.List; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import org.jsoup.Jsoup; import org.jsoup.nodes.Document; import org.jsoup.nodes.Element; import org.jsoup.select.Elements; /** * * @author wwj_748 * @date 2014/8/10 */ public class JsoupUtil { public static boolean contentFirstPage = true; // 第一页 public static boolean contentLastPage = true; // 最后一页 public static boolean multiPages = false; // 多页 private static final String BILIBILI_HOMEPAGE_URL = "http://www.bilibili.com/mobile/index.html"; // bilibili首页地址 public static void resetPages() { contentFirstPage = true; contentLastPage = true; multiPages = false; } } ================================================ FILE: app/src/main/java/com/cjj/bb/utils/Logger.java ================================================ package com.cjj.bb.utils; import android.util.Log; public class Logger { private static boolean isLog = true; private static final String TAG = "ABPlayer"; public static void setLog(boolean isLog) { Logger.isLog = isLog; } public static boolean getIsLog() { return isLog; } public static void d(String tag, String msg) { if (isLog) { Log.d(tag, msg); } } public static void d(String msg) { Log.d(TAG, msg); } /** * Send a {@link #DEBUG} log message and log the exception. * * @param tag Used to identify the source of a log message. It usually * identifies the class or activity where the log call occurs. * @param msg The message you would like logged. * @param tr An exception to log */ public static void d(String tag, String msg, Throwable tr) { if (isLog) { Log.d(tag, msg, tr); } } public static void e(Throwable tr) { if (isLog) { Log.e(TAG, "", tr); } } public static void i(String msg) { if (isLog) { Log.i(TAG, msg); } } public static void i(String tag, String msg) { if (isLog) { Log.i(tag, msg); } } /** * Send a {@link #INFO} log message and log the exception. * * @param tag Used to identify the source of a log message. It usually * identifies the class or activity where the log call occurs. * @param msg The message you would like logged. * @param tr An exception to log */ public static void i(String tag, String msg, Throwable tr) { if (isLog) { Log.i(tag, msg, tr); } } /** * Send an {@link #ERROR} log message. * * @param tag Used to identify the source of a log message. It usually * identifies the class or activity where the log call occurs. * @param msg The message you would like logged. */ public static void e(String tag, String msg) { if (isLog) { Log.e(tag, msg); } } public static void e(String msg) { if (isLog) { Log.e(TAG, msg); } } /** * Send a {@link #ERROR} log message and log the exception. * * @param tag Used to identify the source of a log message. It usually * identifies the class or activity where the log call occurs. * @param msg The message you would like logged. * @param tr An exception to log */ public static void e(String tag, String msg, Throwable tr) { if (isLog) { Log.e(tag, msg, tr); } } public static void e(String msg, Throwable tr) { if (isLog) { Log.e(TAG, msg, tr); } } public static void systemErr(String msg) { // if (true) { if (isLog) { if (msg != null) { Log.e(TAG, msg); } } } } ================================================ FILE: app/src/main/java/com/cjj/bb/utils/MediaUtils.java ================================================ /* * Copyright (C) 2012 YIXIA.COM * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.cjj.bb.utils; import java.io.File; import java.util.regex.Pattern; import android.net.Uri; public final class MediaUtils { public static final String[] EXTENSIONS; // http://www.fileinfo.com/filetypes/video 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" }; // http://www.fileinfo.com/filetypes/audio 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" }; public static final String[] SUBTRACK_EXTENSIONS = { ".srt", ".ssa", ".smi", ".txt", ".sub", ".ass" }; public static final Pattern VIDEO_EXTENSIONS_PATTERN; public static final Pattern AUDIO_EXTENSIONS_PATTERN; public static final Pattern EXTENSIONS_PATTERN; public static final Pattern SUBTRACK_EXTENSIONS_PATTERN; static { EXTENSIONS = ArrayUtils.concat(VIDEO_EXTENSIONS, AUDIO_EXTENSIONS); EXTENSIONS_PATTERN = generatePattern(EXTENSIONS); VIDEO_EXTENSIONS_PATTERN = generatePattern(VIDEO_EXTENSIONS); AUDIO_EXTENSIONS_PATTERN = generatePattern(AUDIO_EXTENSIONS); SUBTRACK_EXTENSIONS_PATTERN = generatePattern(SUBTRACK_EXTENSIONS); } public static boolean isVideoOrAudio(String url) { return EXTENSIONS_PATTERN.matcher(url.trim()).find(); } public static boolean isVideoOrAudio(File file) { return EXTENSIONS_PATTERN.matcher(file.getName().trim()).find(); } public static boolean isVideo(String url) { return VIDEO_EXTENSIONS_PATTERN.matcher(url.trim()).find(); } public static boolean isVideo(File file) { return VIDEO_EXTENSIONS_PATTERN.matcher(file.getName().trim()).find(); } public static boolean isAudio(String url) { return AUDIO_EXTENSIONS_PATTERN.matcher(url.trim()).find(); } public static boolean isAudio(File file) { return AUDIO_EXTENSIONS_PATTERN.matcher(file.getName().trim()).find(); } public static boolean isSubTrack(File file) { return SUBTRACK_EXTENSIONS_PATTERN.matcher(file.getName().trim()).find(); } public static boolean isNative(String uri) { uri = Uri.decode(uri); return uri != null && (uri.startsWith("/") || uri.startsWith("content:") || uri.startsWith("file:")); } private static Pattern generatePattern(String[] args) { StringBuffer sb = new StringBuffer(); for (String ext : args) { if (sb.length() > 0) sb.append("|"); sb.append(ext); } return Pattern.compile("(" + sb.toString() + ")$", Pattern.CASE_INSENSITIVE); } } ================================================ FILE: app/src/main/java/com/cjj/bb/utils/MultiMemberGZIPInputStream.java ================================================ package com.cjj.bb.utils; import java.io.InputStream; import java.io.PushbackInputStream; import java.io.IOException; import java.util.zip.GZIPInputStream; public class MultiMemberGZIPInputStream extends GZIPInputStream { public MultiMemberGZIPInputStream(InputStream in, int size) throws IOException { // Wrap the stream in a PushbackInputStream… super(new PushbackInputStream(in, size), size); this.size=size; } public MultiMemberGZIPInputStream(InputStream in) throws IOException { // Wrap the stream in a PushbackInputStream… super(new PushbackInputStream(in, 1024)); this.size=-1; } private MultiMemberGZIPInputStream(MultiMemberGZIPInputStream parent) throws IOException { super(parent.in); this.size=-1; this.parent=parent.parent==null ? parent : parent.parent; this.parent.child=this; } private MultiMemberGZIPInputStream(MultiMemberGZIPInputStream parent, int size) throws IOException { super(parent.in, size); this.size=size; this.parent=parent.parent==null ? parent : parent.parent; this.parent.child=this; } private MultiMemberGZIPInputStream parent; private MultiMemberGZIPInputStream child; private int size; private boolean eos; public int read(byte[] inputBuffer, int inputBufferOffset, int inputBufferLen) throws IOException { if (eos) { return -1;} if (this.child!=null) return this.child.read(inputBuffer, inputBufferOffset, inputBufferLen); int charsRead=super.read(inputBuffer, inputBufferOffset, inputBufferLen); if (charsRead==-1) { // Push any remaining buffered data back onto the stream // If the stream is then not empty, use it to construct // a new instance of this class and delegate this and any // future calls to it… int n = inf.getRemaining()-8; if (n > 0) { // More than 8 bytes remaining in deflater // First 8 are gzip trailer. Add the rest to // any un-read data… ((PushbackInputStream)this.in).unread(buf, len-n, n); } else { // Nothing in the buffer. We need to know whether or not // there is unread data available in the underlying stream // since the base class will not handle an empty file. // Read a byte to see if there is data and if so, // push it back onto the stream… byte[] b=new byte[1]; int ret=in.read(b,0,1); if (ret==-1) { eos=true; return -1; } else ((PushbackInputStream)this.in).unread(b, 0, 1); } MultiMemberGZIPInputStream child; if (this.size==-1) child=new MultiMemberGZIPInputStream(this); else child=new MultiMemberGZIPInputStream(this, this.size); return child.read(inputBuffer, inputBufferOffset, inputBufferLen); } else return charsRead; } } ================================================ FILE: app/src/main/java/com/cjj/bb/utils/PreferenceUtils.java ================================================ package com.cjj.bb.utils; import android.content.Context; import android.content.SharedPreferences; import android.content.SharedPreferences.Editor; import android.preference.PreferenceManager; import com.cjj.bb.activity.ABPlayerApplication; public final class PreferenceUtils { /** 清空数据 */ public static void reset(final Context ctx) { Editor edit = PreferenceManager.getDefaultSharedPreferences(ctx).edit(); edit.clear(); edit.commit(); } public static String getString(String key, String defValue) { return PreferenceManager.getDefaultSharedPreferences(ABPlayerApplication.getContext()).getString(key, defValue); } public static long getLong(String key, long defValue) { return PreferenceManager.getDefaultSharedPreferences(ABPlayerApplication.getContext()).getLong(key, defValue); } public static float getFloat(String key, float defValue) { return PreferenceManager.getDefaultSharedPreferences(ABPlayerApplication.getContext()).getFloat(key, defValue); } public static void put(String key, String value) { putString(key, value); } public static void put(String key, int value) { putInt(key, value); } public static void put(String key, float value) { putFloat(key, value); } public static void put(String key, boolean value) { putBoolean(key, value); } public static void putFloat(String key, float value) { SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(ABPlayerApplication.getContext()); Editor editor = sharedPreferences.edit(); editor.putFloat(key, value); editor.commit(); } public static SharedPreferences getPreferences() { return PreferenceManager.getDefaultSharedPreferences(ABPlayerApplication.getContext()); } public static int getInt(String key, int defValue) { return PreferenceManager.getDefaultSharedPreferences(ABPlayerApplication.getContext()).getInt(key, defValue); } public static boolean getBoolean(String key, boolean defValue) { return PreferenceManager.getDefaultSharedPreferences(ABPlayerApplication.getContext()).getBoolean(key, defValue); } public static void putStringProcess(String key, String value) { SharedPreferences sharedPreferences = ABPlayerApplication.getContext().getSharedPreferences("preference_mu", Context.MODE_MULTI_PROCESS); Editor editor = sharedPreferences.edit(); editor.putString(key, value); editor.commit(); } public static String getStringProcess(String key, String defValue) { SharedPreferences sharedPreferences = ABPlayerApplication.getContext().getSharedPreferences("preference_mu", Context.MODE_MULTI_PROCESS); return sharedPreferences.getString(key, defValue); } public static boolean hasString(String key) { SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(ABPlayerApplication.getContext()); return sharedPreferences.contains(key); } public static void putString(String key, String value) { SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(ABPlayerApplication.getContext()); Editor editor = sharedPreferences.edit(); editor.putString(key, value); editor.commit(); } public static void putLong(String key, long value) { SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(ABPlayerApplication.getContext()); Editor editor = sharedPreferences.edit(); editor.putLong(key, value); editor.commit(); } public static void putBoolean(String key, boolean value) { SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(ABPlayerApplication.getContext()); Editor editor = sharedPreferences.edit(); editor.putBoolean(key, value); editor.commit(); } public static void putInt(String key, int value) { SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(ABPlayerApplication.getContext()); Editor editor = sharedPreferences.edit(); editor.putInt(key, value); editor.commit(); } public static void remove(String... keys) { if (keys != null) { SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(ABPlayerApplication.getContext()); Editor editor = sharedPreferences.edit(); for (String key : keys) { editor.remove(key); } editor.commit(); } } } ================================================ FILE: app/src/main/java/com/cjj/bb/utils/StringUtils.java ================================================ package com.cjj.bb.utils; import java.io.UnsupportedEncodingException; import java.net.URLEncoder; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Calendar; import java.util.Date; import java.util.Iterator; import java.util.TimeZone; import android.text.TextPaint; /** * 字符串工具类 * * @author tangjun * */ public class StringUtils { public static final String EMPTY = ""; private static final String DEFAULT_DATE_PATTERN = "yyyy-MM-dd"; private static final String DEFAULT_DATETIME_PATTERN = "yyyy-MM-dd hh:mm:ss"; /** 用于生成文件 */ private static final String DEFAULT_FILE_PATTERN = "yyyy-MM-dd-HH-mm-ss"; private static final double KB = 1024.0; private static final double MB = 1048576.0; private static final double GB = 1073741824.0; public static final SimpleDateFormat DATE_FORMAT_PART = new SimpleDateFormat( "HH:mm"); public static String currentTimeString() { return DATE_FORMAT_PART.format(Calendar.getInstance().getTime()); } public static char chatAt(String pinyin, int index) { if (pinyin != null && pinyin.length() > 0) return pinyin.charAt(index); return ' '; } /** 获取字符串宽度 */ public static float GetTextWidth(String Sentence, float Size) { if (isEmpty(Sentence)) return 0; TextPaint FontPaint = new TextPaint(); FontPaint.setTextSize(Size); return FontPaint.measureText(Sentence.trim()) + (int) (Size * 0.1); // 留点余地 } /** * 格式化日期字符串 * * @param date * @param pattern * @return */ public static String formatDate(Date date, String pattern) { SimpleDateFormat format = new SimpleDateFormat(pattern); return format.format(date); } /** * 格式化日期字符串 * * @param date * @return 例如2011-3-24 */ public static String formatDate(Date date) { return formatDate(date, DEFAULT_DATE_PATTERN); } public static String formatDate(long date) { return formatDate(new Date(date), DEFAULT_DATE_PATTERN); } /** * 获取当前时间 格式为yyyy-MM-dd 例如2011-07-08 * * @return */ public static String getDate() { return formatDate(new Date(), DEFAULT_DATE_PATTERN); } /** 生成一个文件名,不含后缀 */ public static String createFileName() { Date date = new Date(System.currentTimeMillis()); SimpleDateFormat format = new SimpleDateFormat(DEFAULT_FILE_PATTERN); return format.format(date); } /** * 获取当前时间 * * @return */ public static String getDateTime() { return formatDate(new Date(), DEFAULT_DATETIME_PATTERN); } /** * 格式化日期时间字符串 * * @param date * @return 例如2011-11-30 16:06:54 */ public static String formatDateTime(Date date) { return formatDate(date, DEFAULT_DATETIME_PATTERN); } public static String formatDateTime(long date) { return formatDate(new Date(date), DEFAULT_DATETIME_PATTERN); } /** * 格林威时间转换 * * @param gmt * @return */ public static String formatGMTDate(String gmt) { TimeZone timeZoneLondon = TimeZone.getTimeZone(gmt); return formatDate(Calendar.getInstance(timeZoneLondon) .getTimeInMillis()); } /** * 拼接数组 * * @param array * @param separator * @return */ public static String join(final ArrayList array, final String separator) { StringBuffer result = new StringBuffer(); if (array != null && array.size() > 0) { for (String str : array) { result.append(str); result.append(separator); } result.delete(result.length() - 1, result.length()); } return result.toString(); } public static String join(final Iterator iter, final String separator) { StringBuffer result = new StringBuffer(); if (iter != null) { while (iter.hasNext()) { String key = iter.next(); result.append(key); result.append(separator); } if (result.length() > 0) result.delete(result.length() - 1, result.length()); } return result.toString(); } /** * 判断字符串是否为空 * * @param str * @return */ public static boolean isEmpty(String str) { return str == null || str.length() == 0; } /** * * @param str * @return */ public static String trim(String str) { return str == null ? EMPTY : str.trim(); } /** * 转换时间显示 * * @param time * 毫秒 * @return */ public static String generateTime(long time) { int totalSeconds = (int) (time / 1000); int seconds = totalSeconds % 60; int minutes = (totalSeconds / 60) % 60; int hours = totalSeconds / 3600; return hours > 0 ? String.format("%02d:%02d:%02d", hours, minutes, seconds) : String.format("%02d:%02d", minutes, seconds); } /** 根据秒速获取时间格式 */ public static String gennerTime(int totalSeconds) { int seconds = totalSeconds % 60; int minutes = (totalSeconds / 60) % 60; return String.format("%02d:%02d", minutes, seconds); } /** * 转换文件大小 * * @param size * @return */ public static String generateFileSize(long size) { String fileSize; if (size < KB) fileSize = size + "B"; else if (size < MB) fileSize = String.format("%.1f", size / KB) + "KB"; else if (size < GB) fileSize = String.format("%.1f", size / MB) + "MB"; else fileSize = String.format("%.1f", size / GB) + "GB"; return fileSize; } public static String getTimeDiff(long time) { // Calendar cal = Calendar.getInstance(); long diff = 0; // Date dnow = cal.getTime(); String str = ""; diff = System.currentTimeMillis() - time; if (diff > 2592000000L) {// 30 * 24 * 60 * 60 * 1000=2592000000 毫秒 str = "1个月前"; } else if (diff > 1814400000) {// 21 * 24 * 60 * 60 * 1000=1814400000 毫秒 str = "3周前"; } else if (diff > 1209600000) {// 14 * 24 * 60 * 60 * 1000=1209600000 毫秒 str = "2周前"; } else if (diff > 604800000) {// 7 * 24 * 60 * 60 * 1000=604800000 毫秒 str = "1周前"; } else if (diff > 86400000) { // 24 * 60 * 60 * 1000=86400000 毫秒 // System.out.println("X天前"); str = (int) Math.floor(diff / 86400000f) + "天前"; } else if (diff > 18000000) {// 5 * 60 * 60 * 1000=18000000 毫秒 // System.out.println("X小时前"); str = (int) Math.floor(diff / 18000000f) + "小时前"; } else if (diff > 60000) {// 1 * 60 * 1000=60000 毫秒 // System.out.println("X分钟前"); str = (int) Math.floor(diff / 60000) + "分钟前"; } else { str = (int) Math.floor(diff / 1000) + "秒前"; } return str; } /** * 截取字符串 * * @param search * 待搜索的字符串 * @param start * 起始字符串 例如: * @param end * 结束字符串 例如: * @param defaultValue * @return */ public static String substring(String search, String start, String end, String defaultValue) { int start_len = start.length(); int start_pos = StringUtils.isEmpty(start) ? 0 : search.indexOf(start); if (start_pos > -1) { int end_pos = StringUtils.isEmpty(end) ? -1 : search.indexOf(end, start_pos + start_len); if (end_pos > -1) return search.substring(start_pos + start.length(), end_pos); else return search.substring(start_pos + start.length()); } return defaultValue; } /** * 截取字符串 * * @param search * 待搜索的字符串 * @param start * 起始字符串 例如: * @param end * 结束字符串 例如: * @return */ public static String substring(String search, String start, String end) { return substring(search, start, end, ""); } /** * 拼接字符串 * * @param strs * @return */ public static String concat(String... strs) { StringBuffer result = new StringBuffer(); if (strs != null) { for (String str : strs) { if (str != null) result.append(str); } } return result.toString(); } /** 获取中文字符个数 */ public static int getChineseCharCount(String str) { String tempStr; int count = 0; for (int i = 0; i < str.length(); i++) { tempStr = String.valueOf(str.charAt(i)); if (tempStr.getBytes().length == 3) { count++; } } return count; } /** 获取英文字符个数 */ public static int getEnglishCount(String str) { String tempStr; int count = 0; for (int i = 0; i < str.length(); i++) { tempStr = String.valueOf(str.charAt(i)); if (!(tempStr.getBytes().length == 3)) { count++; } } return count; } public static String encode(String url) { try { return URLEncoder.encode(url, "UTF-8"); } catch (UnsupportedEncodingException e) { Logger.e(e); } return url; } } ================================================ FILE: app/src/main/java/com/cjj/bb/utils/ToastUtils.java ================================================ package com.cjj.bb.utils; import android.app.Activity; import android.content.Context; import android.view.View; import android.widget.Toast; import com.cjj.bb.R; import com.cjj.bb.activity.ABPlayerApplication; public class ToastUtils { public static void showToast(int resID) { showToast(ABPlayerApplication.getContext(), Toast.LENGTH_SHORT, resID); } public static void showToast(String text) { showToast(ABPlayerApplication.getContext(), Toast.LENGTH_SHORT, text); } public static void showToast(Context ctx, int resID) { showToast(ctx, Toast.LENGTH_SHORT, resID); } public static void showToast(Context ctx, String text) { showToast(ctx, Toast.LENGTH_SHORT, text); } public static void showLongToast(Context ctx, int resID) { showToast(ctx, Toast.LENGTH_LONG, resID); } public static void showLongToast(int resID) { showToast(ABPlayerApplication.getContext(), Toast.LENGTH_LONG, resID); } public static void showLongToast(Context ctx, String text) { showToast(ctx, Toast.LENGTH_LONG, text); } public static void showLongToast(String text) { showToast(ABPlayerApplication.getContext(), Toast.LENGTH_LONG, text); } public static void showToast(Context ctx, int duration, int resID) { showToast(ctx, duration, ctx.getString(resID)); } public static void showToast(Context ctx, int duration, String text) { Toast toast = Toast.makeText(ctx, text, duration); View mNextView = toast.getView(); if (mNextView != null) // mNextView.setBackgroundResource(R.drawable.toast_frame); toast.show(); // Toast.makeText(ctx, text, duration).show(); } // public static void showToastOnUiThread(final String text) { // showToastOnUiThread(FSAppliction.getCurrentActivity(), text); // } /** 在UI线程运行弹出 */ public static void showToastOnUiThread(final Activity ctx, final String text) { if (ctx != null) { ctx.runOnUiThread(new Runnable() { @Override public void run() { showToast(ctx, text); } }); } } } ================================================ FILE: app/src/main/java/com/cjj/bb/utils/URLUtil.java ================================================ package com.cjj.bb.utils; /** * * @author wwj_748 * @date 2014/8/10 */ public class URLUtil { // BILIBILI_DATA_URL public static String URL_DONG_HUA = "http://www.bilibili.com/index/ding/1.json"; public static String URL_MAD_MAV = "http://www.bilibili.com/index/ding/24.json"; public static String URL_MAD_3D = "http://www.bilibili.com/index/ding/25.json"; public static String URL_DONG_HUA_DUAN_PIAN = "http://www.bilibili.com/index/ding/47.json"; public static String URL_DONG_HUA_ZONG_HE = "http://www.bilibili.com/index/ding/27.json"; public static String URL_LIAN_ZAI_DONG_HUA = "http://www.bilibili.com/index/ding/33.json"; public static String URL_WAN_JIE_DONG_HUA = "http://www.bilibili.com/index/ding/32.json"; public static String URL_ZHI_XUN = "http://www.bilibili.com/index/ding/51.json"; public static String URL_GUAN_FANG_YAN_SHEN = "http://www.bilibili.com/index/ding/152.json"; public static String URL_GUO_CHAN_DONG_HUA = "http://www.bilibili.com/index/ding/153.json"; public static String URL_YIN_YUE = "http://www.bilibili.com/index/ding/3.json"; public static String URL_FAN_CHANG = "http://www.bilibili.com/index/ding/31.json"; public static String URL_VOCALOID_UTAU = "http://www.bilibili.com/index/ding/30.json"; public static String URL_YAN_ZOU= "http://www.bilibili.com/index/ding/59.json"; public static String URL_YIN_YUE_XUAN_JI = "http://www.bilibili.com/index/ding/130.json"; public static String URL_KE_JI = "http://www.bilibili.com/index/ding/36.json"; public static String URL_JI_LU_PIAN = "http://www.bilibili.com/index/ding/37.json"; public static String URL_KE_PU_REN_WEN = "http://www.bilibili.com/index/ding/124.json"; public static String URL_YE_SHENG_JI_SHU= "http://www.bilibili.com/index/ding/122.json"; public static String URL_YAN_JIANG = "http://www.bilibili.com/index/ding/39.json"; public static String URL_JUN_SHI = "http://www.bilibili.com/index/ding/96.json"; public static String URL_SHU_MA = "http://www.bilibili.com/index/ding/95.json"; public static String URL_YU_LE = "http://www.bilibili.com/index/ding/5.json"; public static String URL_GAO_XIAO = "http://www.bilibili.com/index/ding/138.json"; public static String URL_SHENG_HUO = "http://www.bilibili.com/index/ding/21.json"; public static String URL_ZONG_YI = "http://www.bilibili.com/index/ding/71.json"; public static String URL_DIAN_YIN = "http://www.bilibili.com/index/ding/23.json"; public static String URL_OU_MEI_DIAN_YIN = "http://www.bilibili.com/index/ding/145.json"; public static String URL_RI_BEN_DIAN_YIN = "http://www.bilibili.com/index/ding/146.json"; public static String URL_GUO_CHAN_DIAN_YIN = "http://www.bilibili.com/index/ding/147.json"; public static String URL_DIAN_YIN_XIANG_GUAN = "http://www.bilibili.com/index/ding/82.json"; public static String URL_YOU_XI = "http://www.bilibili.com/index/ding/4.json"; public static String URL_DIAN_JI = "http://www.bilibili.com/index/ding/17.json"; public static String URL_WANG_LUO_DIAN_YIN = "http://www.bilibili.com/index/ding/65.json"; public static String URL_DIAN_ZI_JING_JI = "http://www.bilibili.com/index/ding/60.json"; public static String URL_RANK_QUAN_QU = "http://www.bilibili.com/index/rank/all-7-0.json";//全区 public static String URL_RANK_XIN_FAN = "http://www.bilibili.com/index/rank/all-7-33.json";//新番 public static String URL_RANK_DONG_HUA = "http://www.bilibili.com/index/rank/all-7-1.json";//动画 public static String URL_RANK_YIN_YUE = "http://www.bilibili.com/index/rank/all-7-3.json";//音乐 public static String URL_RANK_YOU_XI = "http://www.bilibili.com/index/rank/all-7-4.json";//游戏 public static String URL_RANK_KE_JI = "http://www.bilibili.com/index/rank/all-7-36.json";//科技 public static String URL_RANK_YU_LE = "http://www.bilibili.com/index/rank/all-7-5.json";//娱乐 public static String URL_RANK_DIAN_YING = "http://www.bilibili.com/index/rank/all-7-23.json";//电影 /** * 获取博客列表的URL * * @param blogType * 博客类型 * @param page * 页数 * @return */ public static String getVideoListURL(int videoType) { String url = ""; switch (videoType) { case Constants.DEF_VIDEO_TYPE.DONG_HUA: url = URL_DONG_HUA; break; case Constants.DEF_VIDEO_TYPE.MAD_AMV: url = URL_MAD_MAV; break; case Constants.DEF_VIDEO_TYPE.MMD_3D: url = URL_MAD_3D; break; case Constants.DEF_VIDEO_TYPE.DONG_HUA_DUAN_PIAN: url = URL_DONG_HUA_DUAN_PIAN; break; case Constants.DEF_VIDEO_TYPE.DONG_HUA_ZONG_HE: url = URL_DONG_HUA_ZONG_HE; break; case Constants.DEF_VIDEO_TYPE.LIAN_ZAI_DONG_HUA: url = URL_LIAN_ZAI_DONG_HUA; break; case Constants.DEF_VIDEO_TYPE.WAN_JIE_DONG_HUA: url = URL_WAN_JIE_DONG_HUA; break; case Constants.DEF_VIDEO_TYPE.ZHI_XUN: url = URL_ZHI_XUN; break; case Constants.DEF_VIDEO_TYPE.GUAN_FANG_YAN_SHEN: url = URL_GUAN_FANG_YAN_SHEN; break; case Constants.DEF_VIDEO_TYPE.GUO_CHAN_DONG_HUA: url = URL_GUO_CHAN_DONG_HUA; break; //<------------音乐区-------------> case Constants.DEF_VIDEO_TYPE.YIN_YUE: url = URL_YIN_YUE; break; case Constants.DEF_VIDEO_TYPE.FAN_CHANG: url = URL_FAN_CHANG; break; case Constants.DEF_VIDEO_TYPE.VOCALOID_UTAU: url = URL_VOCALOID_UTAU; break; case Constants.DEF_VIDEO_TYPE.YAN_ZOU: url = URL_YAN_ZOU; break; case Constants.DEF_VIDEO_TYPE.YIN_YUE_XUAN_JI: url = URL_YIN_YUE_XUAN_JI; break; //<------------科技区-------------> case Constants.DEF_VIDEO_TYPE.KE_JI: url = URL_KE_JI; break; case Constants.DEF_VIDEO_TYPE.JI_LU_PIAN: url = URL_JI_LU_PIAN; break; case Constants.DEF_VIDEO_TYPE.KE_PU_REN_WEN: url = URL_KE_PU_REN_WEN; break; case Constants.DEF_VIDEO_TYPE.YE_SHENG_JI_SHU: url = URL_YE_SHENG_JI_SHU; break; case Constants.DEF_VIDEO_TYPE.YAN_JIANG: url = URL_YAN_JIANG; break; case Constants.DEF_VIDEO_TYPE.JUN_SHI: url = URL_JUN_SHI; break; case Constants.DEF_VIDEO_TYPE.SHU_MA: url = URL_SHU_MA; break; //<------------娱乐区-------------> case Constants.DEF_VIDEO_TYPE.YU_LE: url = URL_YU_LE; break; case Constants.DEF_VIDEO_TYPE.GAO_XIAO: url = URL_GAO_XIAO; break; case Constants.DEF_VIDEO_TYPE.SHENG_HUO: url = URL_SHENG_HUO; break; case Constants.DEF_VIDEO_TYPE.ZONG_YI: url = URL_ZONG_YI; break; //<------------电影区-------------> case Constants.DEF_VIDEO_TYPE.DIAN_YIN: url = URL_DIAN_YIN; break; case Constants.DEF_VIDEO_TYPE.OU_MEI_DIAN_YIN: url = URL_OU_MEI_DIAN_YIN; break; case Constants.DEF_VIDEO_TYPE.RI_BEN_DIAN_YIN: url = URL_RI_BEN_DIAN_YIN; break; case Constants.DEF_VIDEO_TYPE.GUO_CHAN_DIAN_YIN: url = URL_GUO_CHAN_DIAN_YIN; break; case Constants.DEF_VIDEO_TYPE.DIAN_YIN_XIANG_GUAN: url = URL_DIAN_YIN_XIANG_GUAN; break; //<------------游戏区-------------> case Constants.DEF_VIDEO_TYPE.YOU_XI: url = URL_YOU_XI; break; case Constants.DEF_VIDEO_TYPE.DIAN_JI: url = URL_DIAN_JI; break; case Constants.DEF_VIDEO_TYPE.WANG_LUO_DIAN_YIN: url = URL_WANG_LUO_DIAN_YIN; break; case Constants.DEF_VIDEO_TYPE.DIAN_ZI_JING_JI: url = URL_DIAN_ZI_JING_JI; break; //<------------排行榜-------------> case 10070: url = URL_RANK_QUAN_QU; break; case 100733: url = URL_RANK_XIN_FAN; break; case 10071: url = URL_RANK_DONG_HUA; break; case 10073: url = URL_RANK_YIN_YUE; break; case 10074: url = URL_RANK_YOU_XI; break; case 100736: url = URL_RANK_KE_JI; break; case 10075: url = URL_RANK_YU_LE; break; case 100723: url = URL_RANK_DIAN_YING; break; default: break; } return url; } /** * 获取刷新博客的URL * * @param blogType * 博客类型 * @return */ public static String getRefreshBlogListURL(int blogType) { String url = ""; switch (blogType) { case Constants.DEF_VIDEO_TYPE.DONG_HUA: url = URL_DONG_HUA; break; case Constants.DEF_VIDEO_TYPE.MAD_AMV: url = URL_MAD_MAV; break; case Constants.DEF_VIDEO_TYPE.MMD_3D: url = URL_MAD_3D; break; case Constants.DEF_VIDEO_TYPE.DONG_HUA_DUAN_PIAN: url = URL_DONG_HUA_DUAN_PIAN; break; case Constants.DEF_VIDEO_TYPE.DONG_HUA_ZONG_HE: url = URL_DONG_HUA_ZONG_HE; break; case Constants.DEF_VIDEO_TYPE.LIAN_ZAI_DONG_HUA: url = URL_LIAN_ZAI_DONG_HUA; break; case Constants.DEF_VIDEO_TYPE.WAN_JIE_DONG_HUA: url = URL_WAN_JIE_DONG_HUA; break; case Constants.DEF_VIDEO_TYPE.ZHI_XUN: url = URL_ZHI_XUN; break; case Constants.DEF_VIDEO_TYPE.GUAN_FANG_YAN_SHEN: url = URL_GUAN_FANG_YAN_SHEN; break; case Constants.DEF_VIDEO_TYPE.GUO_CHAN_DONG_HUA: url = URL_GUO_CHAN_DONG_HUA; break; //<------------音乐区-------------> case Constants.DEF_VIDEO_TYPE.YIN_YUE: url = URL_YIN_YUE; break; case Constants.DEF_VIDEO_TYPE.FAN_CHANG: url = URL_FAN_CHANG; break; case Constants.DEF_VIDEO_TYPE.VOCALOID_UTAU: url = URL_VOCALOID_UTAU; break; case Constants.DEF_VIDEO_TYPE.YAN_ZOU: url = URL_YAN_ZOU; break; case Constants.DEF_VIDEO_TYPE.YIN_YUE_XUAN_JI: url = URL_YIN_YUE_XUAN_JI; break; //<------------科技区-------------> case Constants.DEF_VIDEO_TYPE.KE_JI: url = URL_KE_JI; break; case Constants.DEF_VIDEO_TYPE.JI_LU_PIAN: url = URL_JI_LU_PIAN; break; case Constants.DEF_VIDEO_TYPE.KE_PU_REN_WEN: url = URL_KE_PU_REN_WEN; break; case Constants.DEF_VIDEO_TYPE.YE_SHENG_JI_SHU: url = URL_YE_SHENG_JI_SHU; break; case Constants.DEF_VIDEO_TYPE.YAN_JIANG: url = URL_YAN_JIANG; break; case Constants.DEF_VIDEO_TYPE.JUN_SHI: url = URL_JUN_SHI; break; case Constants.DEF_VIDEO_TYPE.SHU_MA: url = URL_SHU_MA; break; //<------------娱乐区-------------> case Constants.DEF_VIDEO_TYPE.YU_LE: url = URL_YU_LE; break; case Constants.DEF_VIDEO_TYPE.GAO_XIAO: url = URL_GAO_XIAO; break; case Constants.DEF_VIDEO_TYPE.SHENG_HUO: url = URL_SHENG_HUO; break; case Constants.DEF_VIDEO_TYPE.ZONG_YI: url = URL_ZONG_YI; break; //<------------电影区-------------> case Constants.DEF_VIDEO_TYPE.DIAN_YIN: url = URL_DIAN_YIN; break; case Constants.DEF_VIDEO_TYPE.OU_MEI_DIAN_YIN: url = URL_OU_MEI_DIAN_YIN; break; case Constants.DEF_VIDEO_TYPE.RI_BEN_DIAN_YIN: url = URL_RI_BEN_DIAN_YIN; break; case Constants.DEF_VIDEO_TYPE.GUO_CHAN_DIAN_YIN: url = URL_GUO_CHAN_DIAN_YIN; break; case Constants.DEF_VIDEO_TYPE.DIAN_YIN_XIANG_GUAN: url = URL_DIAN_YIN_XIANG_GUAN; break; //<------------游戏区-------------> case Constants.DEF_VIDEO_TYPE.YOU_XI: url = URL_YOU_XI; break; case Constants.DEF_VIDEO_TYPE.DIAN_JI: url = URL_DIAN_JI; break; case Constants.DEF_VIDEO_TYPE.WANG_LUO_DIAN_YIN: url = URL_WANG_LUO_DIAN_YIN; break; case Constants.DEF_VIDEO_TYPE.DIAN_ZI_JING_JI: url = URL_DIAN_ZI_JING_JI; break; //<------------排行榜-------------> case 10070: url = URL_RANK_QUAN_QU; break; case 100733: url = URL_RANK_XIN_FAN; break; case 10071: url = URL_RANK_DONG_HUA; break; case 10073: url = URL_RANK_YIN_YUE; break; case 10074: url = URL_RANK_YOU_XI; break; case 100736: url = URL_RANK_KE_JI; break; case 10075: url = URL_RANK_YU_LE; break; case 100723: url = URL_RANK_DIAN_YING; break; default: break; } return url; } /** * 返回博文评论列表链接 * * @param filename * 文件名 * @param pageIndex * 页数 * @return */ public static String getCommentListURL(String filename, String pageIndex) { return "http://blog.csdn.net/wwj_748/comment/list/" + filename + "?page=" + pageIndex; } } ================================================ FILE: app/src/main/java/com/cjj/bb/utils/XmlReaderHelper.java ================================================ package com.cjj.bb.utils; import java.io.IOException; import java.util.ArrayList; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.NamedNodeMap; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.xml.sax.SAXException; import android.content.Context; import com.cjj.bb.model.OnlineVideo; /** 从XML读取电视台节目 */ public class XmlReaderHelper { /** 获取所有电视分类 */ public static ArrayList getAllCategory(final Context context) { ArrayList result = new ArrayList(); DocumentBuilderFactory docBuilderFactory = null; DocumentBuilder docBuilder = null; Document doc = null; try { docBuilderFactory = DocumentBuilderFactory.newInstance(); docBuilder = docBuilderFactory.newDocumentBuilder(); // xml file 放到 assets目录中的 doc = docBuilder.parse(context.getResources().getAssets() .open("online.xml")); // root element Element root = doc.getDocumentElement(); NodeList nodeList = root.getElementsByTagName("category"); for (int i = 0; i < nodeList.getLength(); i++) { Node node = nodeList.item(i);// category OnlineVideo ov = new OnlineVideo(); NamedNodeMap attr = node.getAttributes(); ov.title = attr.getNamedItem("name").getNodeValue(); ov.id = attr.getNamedItem("id").getNodeValue(); ov.category = 1; ov.level = 2; ov.is_category = true; result.add(ov); // Read Node } } catch (IOException e) { } catch (SAXException e) { } catch (ParserConfigurationException e) { } finally { doc = null; docBuilder = null; docBuilderFactory = null; } return result; } /** 读取分类下所有电视地址 */ public static ArrayList getVideos(final Context context, String categoryId) { ArrayList result = new ArrayList(); DocumentBuilderFactory docBuilderFactory = null; DocumentBuilder docBuilder = null; Document doc = null; try { docBuilderFactory = DocumentBuilderFactory.newInstance(); docBuilder = docBuilderFactory.newDocumentBuilder(); // xml file 放到 assets目录中的 doc = docBuilder.parse(context.getResources().getAssets() .open("online.xml")); // root element Element root = doc.getElementById(categoryId); if (root != null) { NodeList nodeList = root.getChildNodes(); for (int i = 0, j = nodeList.getLength(); i < j; i++) { Node baseNode = nodeList.item(i); if (!"item".equals(baseNode.getNodeName())) continue; String id = baseNode.getFirstChild().getNodeValue(); if (id == null) continue; OnlineVideo ov = new OnlineVideo(); ov.id = id; Element el = doc.getElementById(ov.id); if (el != null) { ov.title = el.getAttribute("title"); ov.icon_url = el.getAttribute("image"); ov.level = 3; ov.category = 1; NodeList nodes = el.getChildNodes(); for (int m = 0, n = nodes.getLength(); m < n; m++) { Node node = nodes.item(m); if (!"ref".equals(node.getNodeName())) continue; String href = node.getAttributes() .getNamedItem("href").getNodeValue(); if (ov.url == null) { ov.url = href; } else { if (ov.backup_url == null) ov.backup_url = new ArrayList(); ov.backup_url.add(href); } } if (ov.url != null) result.add(ov); } } } } catch (IOException e) { e.printStackTrace(); } catch (SAXException e) { e.printStackTrace(); } catch (ParserConfigurationException e) { e.printStackTrace(); } finally { doc = null; docBuilder = null; docBuilderFactory = null; } return result; } } ================================================ FILE: app/src/main/java/com/cjj/bb/view/ApplicationUtils.java ================================================ package com.cjj.bb.view; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.util.List; import android.app.Activity; import android.app.ActivityManager; import android.content.Context; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; import android.os.Environment; import android.widget.Toast; public class ApplicationUtils { /** * 备份App 首先无需提升权限就就可以复制APK,查看权限你就会知道,在data/app下的APK权限如下:-rw-r--r-- system * system 5122972 2012-12-13 10:38 com.taobao.taobao-1.apk 我们是有读取权限的。 * * @param packageName * @param mActivity * @throws java.io.IOException */ public static void backupApp(String packageName, Activity mActivity) throws IOException { // 存放位置 String newFile = Environment.getExternalStorageDirectory() .getAbsolutePath() + File.separator; String oldFile = null; try { // 原始位置 oldFile = mActivity.getPackageManager().getApplicationInfo( packageName, 0).sourceDir; } catch (NameNotFoundException e) { e.printStackTrace(); } System.out.println(newFile); System.out.println(oldFile); File in = new File(oldFile); File out = new File(newFile + packageName + ".apk"); if (!out.exists()) { out.createNewFile(); Toast.makeText(mActivity, "文件备份成功!" + "存放于" + newFile + "目录下", 1) .show(); } else { Toast.makeText(mActivity, "文件已经存在!" + "查看" + newFile + "目录下", 1) .show(); } FileInputStream fis = new FileInputStream(in); FileOutputStream fos = new FileOutputStream(out); int count; // 文件太大的话,我觉得需要修改 byte[] buffer = new byte[256 * 1024]; while ((count = fis.read(buffer)) > 0) { fos.write(buffer, 0, count); } fis.close(); fos.flush(); fos.close(); } /** * 获取当前Apk版本号 android:versionCode * * @param context * @return */ public static int getVerCode(Context context) { int verCode = -1; try { verCode = context.getPackageManager().getPackageInfo( context.getPackageName(), 0).versionCode; } catch (NameNotFoundException e) { } return verCode; } public static String getVerName(Context context) { try { return context.getPackageManager().getPackageInfo( context.getPackageName(), 0).versionName; } catch (NameNotFoundException e) { } return ""; } /** * 返回当前的应用是否处于前台显示状态 不需要android.permission.GET_TASKS权限 * http://zengrong.net/post/1680.htm * * @param packageName * @return */ public static boolean isTopActivity(Context context, String packageName) { // _context是一个保存的上下文 ActivityManager am = (ActivityManager) context.getApplicationContext() .getSystemService(Context.ACTIVITY_SERVICE); List list = am .getRunningAppProcesses(); if (list.size() == 0) return false; for (ActivityManager.RunningAppProcessInfo process : list) { // Log.d(getTAG(), Integer.toString(__process.importance)); // Log.d(getTAG(), __process.processName); if (process.importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND && process.processName.equals(packageName)) { return true; } } return false; } /** * 检测APP是否存在 * @param context * @param packageName * @return */ public static boolean checkAppExist(Context context, String packageName) { try { ApplicationInfo info = context.getPackageManager() .getApplicationInfo(packageName, 0); return info != null && info.packageName.equals(packageName); } catch (NameNotFoundException e) { } catch (Exception e) { } return false; } } ================================================ FILE: app/src/main/java/com/cjj/bb/view/CircleImageView.java ================================================ package com.cjj.bb.view; import android.content.Context; import android.content.res.TypedArray; import android.graphics.Bitmap; import android.graphics.BitmapShader; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Matrix; import android.graphics.Paint; import android.graphics.RectF; import android.graphics.Shader; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.Drawable; import android.net.Uri; import android.util.AttributeSet; import android.widget.ImageView; import com.cjj.bb.R; public class CircleImageView extends ImageView { private static final ScaleType SCALE_TYPE = ScaleType.CENTER_CROP; private static final Bitmap.Config BITMAP_CONFIG = Bitmap.Config.ARGB_8888; private static final int COLORDRAWABLE_DIMENSION = 1; private static final int DEFAULT_BORDER_WIDTH = 0; private static final int DEFAULT_BORDER_COLOR = Color.BLACK; private final RectF mDrawableRect = new RectF(); private final RectF mBorderRect = new RectF(); private final Matrix mShaderMatrix = new Matrix(); private final Paint mBitmapPaint = new Paint(); private final Paint mBorderPaint = new Paint(); private int mBorderColor = DEFAULT_BORDER_COLOR; private int mBorderWidth = DEFAULT_BORDER_WIDTH; private Bitmap mBitmap; private BitmapShader mBitmapShader; private int mBitmapWidth; private int mBitmapHeight; private float mDrawableRadius; private float mBorderRadius; private boolean mReady; private boolean mSetupPending; public CircleImageView(Context context) { super(context); init(); } public CircleImageView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public CircleImageView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.CircleImageView, defStyle, 0); mBorderWidth = a.getDimensionPixelSize(R.styleable.CircleImageView_border_width, DEFAULT_BORDER_WIDTH); mBorderColor = a.getColor(R.styleable.CircleImageView_border_color, DEFAULT_BORDER_COLOR); a.recycle(); init(); } private void init() { super.setScaleType(SCALE_TYPE); mReady = true; if (mSetupPending) { setup(); mSetupPending = false; } } @Override public ScaleType getScaleType() { return SCALE_TYPE; } @Override public void setScaleType(ScaleType scaleType) { if (scaleType != SCALE_TYPE) { throw new IllegalArgumentException(String.format("ScaleType %s not supported.", scaleType)); } } @Override protected void onDraw(Canvas canvas) { if (getDrawable() == null) { return; } canvas.drawCircle(getWidth() / 2, getHeight() / 2, mDrawableRadius, mBitmapPaint); if (mBorderWidth != 0) { canvas.drawCircle(getWidth() / 2, getHeight() / 2, mBorderRadius, mBorderPaint); } } @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); setup(); } public int getBorderColor() { return mBorderColor; } public void setBorderColor(int borderColor) { if (borderColor == mBorderColor) { return; } mBorderColor = borderColor; mBorderPaint.setColor(mBorderColor); invalidate(); } public int getBorderWidth() { return mBorderWidth; } public void setBorderWidth(int borderWidth) { if (borderWidth == mBorderWidth) { return; } mBorderWidth = borderWidth; setup(); } @Override public void setImageBitmap(Bitmap bm) { super.setImageBitmap(bm); mBitmap = bm; setup(); } @Override public void setImageDrawable(Drawable drawable) { super.setImageDrawable(drawable); mBitmap = getBitmapFromDrawable(drawable); setup(); } @Override public void setImageResource(int resId) { super.setImageResource(resId); mBitmap = getBitmapFromDrawable(getDrawable()); setup(); } @Override public void setImageURI(Uri uri) { super.setImageURI(uri); mBitmap = getBitmapFromDrawable(getDrawable()); setup(); } private Bitmap getBitmapFromDrawable(Drawable drawable) { if (drawable == null) { return null; } if (drawable instanceof BitmapDrawable) { return ((BitmapDrawable) drawable).getBitmap(); } try { Bitmap bitmap; if (drawable instanceof ColorDrawable) { bitmap = Bitmap.createBitmap(COLORDRAWABLE_DIMENSION, COLORDRAWABLE_DIMENSION, BITMAP_CONFIG); } else { bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), BITMAP_CONFIG); } Canvas canvas = new Canvas(bitmap); drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight()); drawable.draw(canvas); return bitmap; } catch (OutOfMemoryError e) { return null; } } private void setup() { if (!mReady) { mSetupPending = true; return; } if (mBitmap == null) { return; } mBitmapShader = new BitmapShader(mBitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP); mBitmapPaint.setAntiAlias(true); mBitmapPaint.setShader(mBitmapShader); mBorderPaint.setStyle(Paint.Style.STROKE); mBorderPaint.setAntiAlias(true); mBorderPaint.setColor(mBorderColor); mBorderPaint.setStrokeWidth(mBorderWidth); mBitmapHeight = mBitmap.getHeight(); mBitmapWidth = mBitmap.getWidth(); mBorderRect.set(0, 0, getWidth(), getHeight()); mBorderRadius = Math.min((mBorderRect.height() - mBorderWidth) / 2, (mBorderRect.width() - mBorderWidth) / 2); mDrawableRect.set(mBorderWidth, mBorderWidth, mBorderRect.width() - mBorderWidth, mBorderRect.height() - mBorderWidth); mDrawableRadius = Math.min(mDrawableRect.height() / 2, mDrawableRect.width() / 2); updateShaderMatrix(); invalidate(); } private void updateShaderMatrix() { float scale; float dx = 0; float dy = 0; mShaderMatrix.set(null); if (mBitmapWidth * mDrawableRect.height() > mDrawableRect.width() * mBitmapHeight) { scale = mDrawableRect.height() / (float) mBitmapHeight; dx = (mDrawableRect.width() - mBitmapWidth * scale) * 0.5f; } else { scale = mDrawableRect.width() / (float) mBitmapWidth; dy = (mDrawableRect.height() - mBitmapHeight * scale) * 0.5f; } mShaderMatrix.setScale(scale, scale); mShaderMatrix.postTranslate((int) (dx + 0.5f) + mBorderWidth, (int) (dy + 0.5f) + mBorderWidth); mBitmapShader.setLocalMatrix(mShaderMatrix); } } ================================================ FILE: app/src/main/java/com/cjj/bb/view/CommonGestures.java ================================================ /* * Copyright (C) 2012 YIXIA.COM * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.cjj.bb.view; import android.annotation.SuppressLint; import android.app.Activity; import android.support.v4.view.GestureDetectorCompat; import android.view.GestureDetector.SimpleOnGestureListener; import android.view.MotionEvent; import android.view.ScaleGestureDetector; import com.cjj.bb.utils.DeviceUtils; public class CommonGestures { public static final int SCALE_STATE_BEGIN = 0; public static final int SCALE_STATE_SCALEING = 1; public static final int SCALE_STATE_END = 2; private boolean mGestureEnabled; private GestureDetectorCompat mDoubleTapGestureDetector; private GestureDetectorCompat mTapGestureDetector; private ScaleGestureDetector mScaleDetector; private Activity mContext; public CommonGestures(Activity ctx) { mContext = ctx; mDoubleTapGestureDetector = new GestureDetectorCompat(mContext, new DoubleTapGestureListener()); mTapGestureDetector = new GestureDetectorCompat(mContext, new TapGestureListener()); mScaleDetector = new ScaleGestureDetector(mContext, new ScaleDetectorListener()); } public boolean onTouchEvent(MotionEvent event) { if (mListener == null) return false; if (mTapGestureDetector.onTouchEvent(event)) return true; if (event.getPointerCount() > 1) { try { if (mScaleDetector != null && mScaleDetector.onTouchEvent(event)) return true; } catch (Exception e) { e.printStackTrace(); } } if (mDoubleTapGestureDetector.onTouchEvent(event)) return true; switch (event.getAction() & MotionEvent.ACTION_MASK) { case MotionEvent.ACTION_UP: mListener.onGestureEnd(); break; } return false; } private class TapGestureListener extends SimpleOnGestureListener { @Override public boolean onSingleTapConfirmed(MotionEvent event) { if (mListener != null) mListener.onSingleTap(); return true; } @Override public void onLongPress(MotionEvent e) { if (mListener != null && mGestureEnabled) mListener.onLongPress(); } } @SuppressLint("NewApi") private class ScaleDetectorListener implements ScaleGestureDetector.OnScaleGestureListener { @Override public boolean onScale(ScaleGestureDetector detector) { if (mListener != null && mGestureEnabled) mListener.onScale(detector.getScaleFactor(), SCALE_STATE_SCALEING); return true; } @Override public void onScaleEnd(ScaleGestureDetector detector) { if (mListener != null && mGestureEnabled) mListener.onScale(0F, SCALE_STATE_END); } @Override public boolean onScaleBegin(ScaleGestureDetector detector) { if (mListener != null && mGestureEnabled) mListener.onScale(0F, SCALE_STATE_BEGIN); return true; } } private class DoubleTapGestureListener extends SimpleOnGestureListener { private boolean mDown = false; @Override public boolean onDown(MotionEvent event) { mDown = true; return super.onDown(event); } @Override public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { if (mListener != null && mGestureEnabled && e1 != null && e2 != null) { if (mDown) { mListener.onGestureBegin(); mDown = false; } float mOldX = e1.getX(), mOldY = e1.getY(); int windowWidth = DeviceUtils.getScreenWidth(mContext); int windowHeight = DeviceUtils.getScreenHeight(mContext); if (Math.abs(e2.getY(0) - mOldY) * 2 > Math.abs(e2.getX(0) - mOldX)) { if (mOldX > windowWidth * 4.0 / 5) { mListener.onRightSlide((mOldY - e2.getY(0)) / windowHeight); } else if (mOldX < windowWidth / 5.0) { mListener.onLeftSlide((mOldY - e2.getY(0)) / windowHeight); } } } return super.onScroll(e1, e2, distanceX, distanceY); } @Override public boolean onDoubleTap(MotionEvent event) { if (mListener != null && mGestureEnabled) mListener.onDoubleTap(); return super.onDoubleTap(event); } } public void setTouchListener(TouchListener l, boolean enable) { mListener = l; mGestureEnabled = enable; } private TouchListener mListener; public interface TouchListener { public void onGestureBegin(); public void onGestureEnd(); public void onLeftSlide(float percent); public void onRightSlide(float percent); public void onSingleTap(); public void onDoubleTap(); public void onScale(float scaleFactor, int state); public void onLongPress(); } } ================================================ FILE: app/src/main/java/com/cjj/bb/view/FileUtils.java ================================================ package com.cjj.bb.view; import java.io.File; import java.io.IOException; import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import android.os.Environment; import android.os.StatFs; import android.util.Log; import com.cjj.bb.utils.StringUtils; public class FileUtils { // http://www.fileinfo.com/filetypes/video , "dat" , "bin" , "rms" 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", "bix", "bmk", "box", "bs4", "bsf", "byu", "camre", "clpi", "cpi", "cvc", "d2v", "d3v", "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", "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" }; // http://www.fileinfo.com/filetypes/audio , "spx" , "mid" , "sf" 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", "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", "sf2", "sfk", "sfl", "shn", "sib", "sid", "sid", "smf", "smp", "snd", "snd", "snd", "sng", "sng", "sou", "sppack", "sprg", "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" }; private static final HashSet mHashVideo; private static final HashSet mHashAudio; private static final double KB = 1024.0; private static final double MB = KB * KB; private static final double GB = KB * KB * KB; static { mHashVideo = new HashSet(Arrays.asList(VIDEO_EXTENSIONS)); mHashAudio = new HashSet(Arrays.asList(AUDIO_EXTENSIONS)); } /** 是否是音频或者视频 */ public static boolean isVideoOrAudio(File f) { final String ext = getFileExtension(f); return mHashVideo.contains(ext) || mHashAudio.contains(ext); } public static boolean isVideoOrAudio(String f) { final String ext = getUrlExtension(f); return mHashVideo.contains(ext) || mHashAudio.contains(ext); } public static boolean isVideo(File f) { final String ext = getFileExtension(f); return mHashVideo.contains(ext); } /** 获取文件后缀 */ public static String getFileExtension(File f) { if (f != null) { String filename = f.getName(); int i = filename.lastIndexOf('.'); if (i > 0 && i < filename.length() - 1) { return filename.substring(i + 1).toLowerCase(); } } return null; } public static String getUrlFileName(String url) { int slashIndex = url.lastIndexOf('/'); int dotIndex = url.lastIndexOf('.'); String filenameWithoutExtension; if (dotIndex == -1) { filenameWithoutExtension = url.substring(slashIndex + 1); } else { filenameWithoutExtension = url.substring(slashIndex + 1, dotIndex); } return filenameWithoutExtension; } public static String getUrlExtension(String url) { if (!StringUtils.isEmpty(url)) { int i = url.lastIndexOf('.'); if (i > 0 && i < url.length() - 1) { return url.substring(i + 1).toLowerCase(); } } return ""; } public static String getFileNameNoEx(String filename) { if ((filename != null) && (filename.length() > 0)) { int dot = filename.lastIndexOf('.'); if ((dot > -1) && (dot < (filename.length()))) { return filename.substring(0, dot); } } return filename; } public static String showFileSize(long size) { String fileSize; if (size < KB) fileSize = size + "B"; else if (size < MB) fileSize = String.format("%.1f", size / KB) + "KB"; else if (size < GB) fileSize = String.format("%.1f", size / MB) + "MB"; else fileSize = String.format("%.1f", size / GB) + "GB"; return fileSize; } /** 显示SD卡剩余空间 */ public static String showFileAvailable() { String result = ""; if (Environment.MEDIA_MOUNTED.equals(Environment .getExternalStorageState())) { StatFs sf = new StatFs(Environment.getExternalStorageDirectory() .getPath()); long blockSize = sf.getBlockSize(); long blockCount = sf.getBlockCount(); long availCount = sf.getAvailableBlocks(); return showFileSize(availCount * blockSize) + " / " + showFileSize(blockSize * blockCount); } return result; } /** 如果不存在就创建 */ public static boolean createIfNoExists(String path) { File file = new File(path); boolean mk = false; if (!file.exists()) { mk = file.mkdirs(); } return mk; } private static HashMap mMimeType = new HashMap(); static { mMimeType.put("M1V", "video/mpeg"); mMimeType.put("MP2", "video/mpeg"); mMimeType.put("MPE", "video/mpeg"); mMimeType.put("MPG", "video/mpeg"); mMimeType.put("MPEG", "video/mpeg"); mMimeType.put("MP4", "video/mp4"); mMimeType.put("M4V", "video/mp4"); mMimeType.put("3GP", "video/3gpp"); mMimeType.put("3GPP", "video/3gpp"); mMimeType.put("3G2", "video/3gpp2"); mMimeType.put("3GPP2", "video/3gpp2"); mMimeType.put("MKV", "video/x-matroska"); mMimeType.put("WEBM", "video/x-matroska"); mMimeType.put("MTS", "video/mp2ts"); mMimeType.put("TS", "video/mp2ts"); mMimeType.put("TP", "video/mp2ts"); mMimeType.put("WMV", "video/x-ms-wmv"); mMimeType.put("ASF", "video/x-ms-asf"); mMimeType.put("ASX", "video/x-ms-asf"); mMimeType.put("FLV", "video/x-flv"); mMimeType.put("MOV", "video/quicktime"); mMimeType.put("QT", "video/quicktime"); mMimeType.put("RM", "video/x-pn-realvideo"); mMimeType.put("RMVB", "video/x-pn-realvideo"); mMimeType.put("VOB", "video/dvd"); mMimeType.put("DAT", "video/dvd"); mMimeType.put("AVI", "video/x-divx"); mMimeType.put("OGV", "video/ogg"); mMimeType.put("OGG", "video/ogg"); mMimeType.put("VIV", "video/vnd.vivo"); mMimeType.put("VIVO", "video/vnd.vivo"); mMimeType.put("WTV", "video/wtv"); mMimeType.put("AVS", "video/avs-video"); mMimeType.put("SWF", "video/x-shockwave-flash"); mMimeType.put("YUV", "video/x-raw-yuv"); } /** 获取MIME */ public static String getMimeType(String path) { int lastDot = path.lastIndexOf("."); if (lastDot < 0) return null; return mMimeType.get(path.substring(lastDot + 1).toUpperCase()); } /** 多个SD卡时 取外置SD卡 */ public static String getExternalStorageDirectory() { // 参考文章 // http://blog.csdn.net/bbmiku/article/details/7937745 Map map = System.getenv(); String[] values = new String[map.values().size()]; map.values().toArray(values); String path = values[values.length - 1]; Log.e("nmbb", "FileUtils.getExternalStorageDirectory : " + path); if (path.startsWith("/mnt/") && !Environment.getExternalStorageDirectory().getAbsolutePath() .equals(path)) return path; else return null; } public static String getCanonical(File f) { if (f == null) return null; try { return f.getCanonicalPath(); } catch (IOException e) { return f.getAbsolutePath(); } } public static boolean sdAvailable() { return Environment.MEDIA_MOUNTED_READ_ONLY.equals(Environment .getExternalStorageState()) || Environment.MEDIA_MOUNTED.equals(Environment .getExternalStorageState()); } } ================================================ FILE: app/src/main/java/com/cjj/bb/view/LeftSliderLayout.java ================================================ package com.cjj.bb.view; import android.content.Context; import android.graphics.Rect; import android.util.AttributeSet; import android.view.MotionEvent; import android.view.VelocityTracker; import android.view.View; import android.view.ViewConfiguration; import android.view.ViewGroup; import android.widget.Scroller; /** * 左边侧滑 * @author Administrator * */ public class LeftSliderLayout extends ViewGroup { private Scroller mScroller; private VelocityTracker mVelocityTracker; /** * Constant value for touch state * TOUCH_STATE_REST : no touch * TOUCH_STATE_SCROLLING : scrolling */ private static final int TOUCH_STATE_REST = 0; private static final int TOUCH_STATE_SCROLLING = 1; private int mTouchState = TOUCH_STATE_REST; /** * Distance in pixels a touch can wander before we think the user is scrolling */ private int mTouchSlop; /** * Values for saving axis of the last touch event. */ private float mLastMotionX; private float mLastMotionY; /** * Values for VelocityTracker to compute current velocity. * VELOCITY_UNITS in dp * mVelocityUnits in px */ private static final int VELOCITY_UNITS = 1000; private int mVelocityUnits; /** * The minimum velocity for determining the direction. * MINOR_VELOCITY in dp * mMinorVelocity in px */ private static final float MINOR_VELOCITY = 150.0f; private int mMinorVelocity; /** * The width of Sliding distance from left. * And it should be the same with the width of the View below SliderLayout in a FrameLayout. * DOCK_WIDTH in dp * mDockWidth in px */ private static final float SLIDING_WIDTH = 180.0f; private int mSlidingWidth; /** * The default values of shadow. * VELOCITY_UNITS in dp * mVelocityUnits in px */ private static final float DEF_SHADOW_WIDTH = 10.0f; private int mDefShadowWidth; /** * Value for checking a touch event is completed. */ private boolean mIsTouchEventDone = false; /** * Value for checking slider is open. */ private boolean mIsOpen = false; /** * Value for saving the last offset of scroller ’ x-axis. */ private int mSaveScrollX = 0; /** * Value for checking slider is allowed to slide. */ private boolean mEnableSlide = true; private View mMainChild = null; private OnLeftSliderLayoutStateListener mListener = null; /** * Instantiates a new LeftSliderLayout. * * @param context the associated Context * @param attrs AttributeSet */ public LeftSliderLayout(Context context, AttributeSet attrs) { this(context, attrs, 0); } /** * Instantiates a new LeftSliderLayout. * * @param context the associated Context * @param attrs AttributeSet * @param defStyle Style */ public LeftSliderLayout(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); mScroller = new Scroller(context); mTouchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop(); /** * Convert values in dp to values in px; */ final float fDensity = getResources().getDisplayMetrics().density; mVelocityUnits = (int) (VELOCITY_UNITS * fDensity + 0.5f); mMinorVelocity = (int) (MINOR_VELOCITY * fDensity + 0.5f); mSlidingWidth = (int) (SLIDING_WIDTH * fDensity + 0.5f); mDefShadowWidth = (int) (DEF_SHADOW_WIDTH * fDensity + 0.5f); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); // check Measure Mode is Exactly. final int widthMode = MeasureSpec.getMode(widthMeasureSpec); if (widthMode != MeasureSpec.EXACTLY) { throw new IllegalStateException("LeftSliderLayout only canmCurScreen run at EXACTLY mode!"); } final int heightMode = MeasureSpec.getMode(heightMeasureSpec); if (heightMode != MeasureSpec.EXACTLY) { throw new IllegalStateException("LeftSliderLayout only can run at EXACTLY mode!"); } // measure child views int nCount = getChildCount(); for (int i = 2; i < nCount; i++) { removeViewAt(i); } nCount = getChildCount(); if (nCount > 0) { if (nCount > 1) { mMainChild = getChildAt(1); getChildAt(0).measure(widthMeasureSpec, heightMeasureSpec); } else { mMainChild = getChildAt(0); } mMainChild.measure(widthMeasureSpec, heightMeasureSpec); } // Set the scrolled position scrollTo(mSaveScrollX, 0); } @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { final int nCount = getChildCount(); if (nCount <= 0) { return; } // Set the size and position of Main Child if (mMainChild != null) { mMainChild.layout( l, t, l + mMainChild.getMeasuredWidth(), t + mMainChild.getMeasuredHeight()); } // Set the size and position of Shadow Child if (nCount > 1) { int nLeftChildWidth = 0; View leftChild = getChildAt(0); LayoutParams layoutParams = leftChild.getLayoutParams(); if (layoutParams.width == LayoutParams.FILL_PARENT || layoutParams.width == LayoutParams.MATCH_PARENT) { nLeftChildWidth = mDefShadowWidth; } else { nLeftChildWidth = layoutParams.width; } leftChild.layout( l - nLeftChildWidth, t, l, t + leftChild.getMeasuredHeight()); } } @Override public void computeScroll() { if (mScroller.computeScrollOffset()) { scrollTo(mScroller.getCurrX(), mScroller.getCurrY()); postInvalidate(); } } @Override public boolean onTouchEvent(MotionEvent event) { int nCurScrollX = getScrollX(); // check touch point is in the rectangle of Main Child if (mMainChild != null && mTouchState != TOUCH_STATE_SCROLLING && mIsTouchEventDone) { Rect rect = new Rect(); mMainChild.getHitRect(rect); if (!rect.contains((int)event.getX() + nCurScrollX, (int)event.getY())) { return false; } } if (mVelocityTracker == null) { mVelocityTracker = VelocityTracker.obtain(); } mVelocityTracker.addMovement(event); final int action = event.getAction(); final float x = event.getX(); switch (action) { case MotionEvent.ACTION_DOWN: { if (!mScroller.isFinished()) { mScroller.abortAnimation(); } mIsTouchEventDone = false; mLastMotionX = x; break; } case MotionEvent.ACTION_MOVE: { // check slider is allowed to slide. if (!mEnableSlide) { break; } // compute the x-axis offset from last point to current point int deltaX = (int) (mLastMotionX - x); if (nCurScrollX + deltaX < getMinScrollX()) { deltaX = getMinScrollX() - nCurScrollX; mLastMotionX = mLastMotionX - deltaX; } else if (nCurScrollX + deltaX > getMaxScrollX()) { deltaX = getMaxScrollX() - nCurScrollX; mLastMotionX = mLastMotionX - deltaX; } else { mLastMotionX = x; } // Move view to the current point if (deltaX != 0) { scrollBy(deltaX, 0); } // Save the scrolled position mSaveScrollX = getScrollX(); break; } case MotionEvent.ACTION_CANCEL: case MotionEvent.ACTION_UP: { // check slider is allowed to slide. if (!mEnableSlide) { break; } final VelocityTracker velocityTracker = mVelocityTracker; velocityTracker.computeCurrentVelocity(mVelocityUnits); // Set open or close state, when get ACTION_UP or ACTION_CANCEL event. if (nCurScrollX < 0) { int velocityX = (int) velocityTracker.getXVelocity(); if (velocityX > mMinorVelocity) { scrollByWithAnim(getMinScrollX() - nCurScrollX); setState(true); } else if (velocityX < -mMinorVelocity) { scrollByWithAnim(-nCurScrollX); setState(false); } else { if (nCurScrollX >= getMinScrollX() / 2) { scrollByWithAnim(- nCurScrollX); setState(false); } else { scrollByWithAnim(getMinScrollX() - nCurScrollX); setState(true); } } } else { if (nCurScrollX > 0) { scrollByWithAnim(-nCurScrollX); } setState(false); } if (mVelocityTracker != null) { mVelocityTracker.recycle(); mVelocityTracker = null; } mTouchState = TOUCH_STATE_REST; mIsTouchEventDone = true; break; } } return true; } @Override public boolean onInterceptTouchEvent(MotionEvent ev) { final int action = ev.getAction(); if (mListener != null && !mListener.OnLeftSliderLayoutInterceptTouch(ev)) { return false; } if ((action == MotionEvent.ACTION_MOVE) && (mTouchState != TOUCH_STATE_REST)) { return true; } final float x = ev.getX(); final float y = ev.getY(); switch (action) { case MotionEvent.ACTION_DOWN: mLastMotionX = x; mLastMotionY = y; mTouchState = mScroller.isFinished() ? TOUCH_STATE_REST : TOUCH_STATE_SCROLLING; break; case MotionEvent.ACTION_MOVE: final int xDiff = (int) Math.abs(mLastMotionX - x); if (xDiff > mTouchSlop) { if (Math.abs(mLastMotionY - y) / Math.abs(mLastMotionX - x) < 1) mTouchState = TOUCH_STATE_SCROLLING; } break; case MotionEvent.ACTION_CANCEL: case MotionEvent.ACTION_UP: mTouchState = TOUCH_STATE_REST; break; } return mTouchState != TOUCH_STATE_REST; } /** * With the horizontal scroll of the animation * * @param nDx x-axis offset */ void scrollByWithAnim(int nDx) { if (nDx == 0) { return; } mScroller.startScroll(getScrollX(), 0, nDx, 0, Math.abs(nDx)); invalidate(); } /** * Get distance of the maximum horizontal scroll * * @return distance in px */ private int getMaxScrollX() { return 0; } /** * Get distance of the minimum horizontal scroll * @return distance in px */ private int getMinScrollX() { return -mSlidingWidth; } /** * Open LeftSlideLayout */ public void open() { if (mEnableSlide) { scrollByWithAnim(getMinScrollX() - getScrollX()); setState(true); } } /** * Close LeftSlideLayout */ public void close() { if (mEnableSlide) { scrollByWithAnim((-1) * getScrollX()); setState(false); } } /** * Determine whether LeftSlideLayout is open * * @return true-open,false-close */ public boolean isOpen() { return mIsOpen; } /** * Set state of LeftSliderLayout * * @param bIsOpen the new state */ private void setState(boolean bIsOpen) { boolean bStateChanged = false; if (mIsOpen && !bIsOpen) { bStateChanged = true; } else if (!mIsOpen && bIsOpen) { bStateChanged = true; } mIsOpen = bIsOpen; if (bIsOpen) { mSaveScrollX = getMaxScrollX(); } else { mSaveScrollX = 0; } if (bStateChanged && mListener != null) { mListener.OnLeftSliderLayoutStateChanged(bIsOpen); } } /** * enable slide action of LeftSliderLayout * * @param bEnable */ public void enableSlide(boolean bEnable) { mEnableSlide = bEnable; } /** * Set listener to LeftSliderLayout */ public void setOnLeftSliderLayoutListener(OnLeftSliderLayoutStateListener listener) { mListener = listener; } /** * LeftSliderLayout Listener * */ public interface OnLeftSliderLayoutStateListener { /** * Called when LeftSliderLayout’s state has been changed. * * @param bIsOpen the new state */ public void OnLeftSliderLayoutStateChanged(boolean bIsOpen); /** * Called when LeftSliderLayout has got onInterceptTouchEvent. * * @param ev Touch Event * @return true - LeftSliderLayout need to manage the InterceptTouchEvent. * false - LeftSliderLayout don't need to manage the InterceptTouchEvent. */ public boolean OnLeftSliderLayoutInterceptTouch(MotionEvent ev); } } ================================================ FILE: app/src/main/java/com/cjj/bb/view/MediaController.java ================================================ /* * Copyright (C) 2012 YIXIA.COM * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.cjj.bb.view; import java.lang.ref.WeakReference; import java.lang.reflect.Field; import java.lang.reflect.Method; import android.annotation.SuppressLint; import android.annotation.TargetApi; import android.app.Activity; import android.content.Context; import android.graphics.Rect; import android.graphics.RectF; import android.media.AudioManager; import android.os.Handler; import android.os.Message; import android.view.Gravity; import android.view.KeyEvent; import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; import android.view.Window; import android.view.WindowManager; import android.view.animation.Animation; import android.view.animation.Animation.AnimationListener; import android.view.animation.AnimationUtils; import android.widget.FrameLayout; import android.widget.ImageButton; import android.widget.ImageView; import android.widget.PopupWindow; import android.widget.SeekBar; import android.widget.SeekBar.OnSeekBarChangeListener; import android.widget.TextView; import com.cjj.bb.R; import com.cjj.bb.utils.DeviceUtils; import com.cjj.bb.utils.FractionalTouchDelegate; import com.cjj.bb.utils.Logger; import com.cjj.bb.utils.StringUtils; import com.cjj.bb.utils.ToastUtils; public class MediaController extends FrameLayout { private MediaPlayerControl mPlayer; private Activity mContext; private PopupWindow mWindow; private View mAnchor; private View mRoot; private ImageButton mLock; private ImageButton mScreenToggle; private ImageButton mSnapshot; private SeekBar mProgress; private TextView mEndTime, mCurrentTime; private long mDuration; private boolean mShowing; private boolean mScreenLocked = false; private boolean mDragging; private boolean mInstantSeeking = true; private static final int DEFAULT_TIME_OUT = 3000; private static final int DEFAULT_LONG_TIME_SHOW = 120000; private static final int DEFAULT_SEEKBAR_VALUE = 1000; private static final int TIME_TICK_INTERVAL = 1000; private ImageButton mPauseButton; private View mMediaController; private View mControlsLayout; private View mSystemInfoLayout; private View mControlsButtons; private View mMenu; private TextView mDateTime; private TextView mDownloadRate; private TextView mFileName; private TextView mBatteryLevel; private TextView mOperationInfo; private View mOperationVolLum; private ImageView mVolLumNum; private ImageView mVolLumBg; private AudioManager mAM; private int mMaxVolume; private float mBrightness = 0.01f; private int mVolume = 0; private Handler mHandler; private Animation mAnimSlideInTop; private Animation mAnimSlideInBottom; private Animation mAnimSlideOutTop; private Animation mAnimSlideOutBottom; private CommonGestures mGestures; private int mVideoMode; private ImageButton mDanmakuSend; private ImageButton mDanmakuSwitch; private boolean mDanmakuShow = true; public MediaController(Context context) { super(context); mContext = (Activity) context; initFloatingWindow(); initResources(); } public void setDanmakuVisible(boolean isVisible){ if(isVisible){ mDanmakuSend.setVisibility(View.VISIBLE); mDanmakuSwitch.setVisibility(View.VISIBLE); }else{ mDanmakuSend.setVisibility(View.GONE); mDanmakuSwitch.setVisibility(View.GONE); } } public MediaController(Context context, boolean locked) { this(context); mScreenLocked = locked; lock(mScreenLocked); } private void initFloatingWindow() { mWindow = new PopupWindow(mContext); mWindow.setFocusable(true); mWindow.setBackgroundDrawable(null); mWindow.setOutsideTouchable(true); } @TargetApi(11) public void setWindowLayoutType() { if (DeviceUtils.hasICS()) { try { mAnchor.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION); Method setWindowLayoutType = PopupWindow.class.getMethod("setWindowLayoutType", new Class[] { int.class }); setWindowLayoutType.invoke(mWindow, WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG); } catch (Exception e) { Logger.e(e); } } } @SuppressLint("NewApi") private void initResources() { mHandler = new MHandler(this); mAM = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE); mMaxVolume = mAM.getStreamMaxVolume(AudioManager.STREAM_MUSIC); mGestures = new CommonGestures(mContext); mGestures.setTouchListener(mTouchListener, true); mAnimSlideOutBottom = AnimationUtils.loadAnimation(mContext, R.anim.slide_out_bottom); mAnimSlideOutTop = AnimationUtils.loadAnimation(mContext, R.anim.slide_out_top); mAnimSlideInBottom = AnimationUtils.loadAnimation(mContext, R.anim.slide_in_bottom); mAnimSlideInTop = AnimationUtils.loadAnimation(mContext, R.anim.slide_in_top); mAnimSlideOutBottom.setAnimationListener(new AnimationListener() { @Override public void onAnimationStart(Animation animation) { } @Override public void onAnimationEnd(Animation animation) { mMediaController.setVisibility(View.GONE); showButtons(false); mHandler.removeMessages(MSG_HIDE_SYSTEM_UI); mHandler.sendEmptyMessageDelayed(MSG_HIDE_SYSTEM_UI, DEFAULT_TIME_OUT); } @Override public void onAnimationRepeat(Animation animation) { } }); removeAllViews(); mRoot = inflateLayout(); mWindow.setContentView(mRoot); mWindow.setWidth(ViewGroup.LayoutParams.MATCH_PARENT); mWindow.setHeight(ViewGroup.LayoutParams.MATCH_PARENT); findViewItems(mRoot); showSystemUi(false); if (DeviceUtils.hasHoneycomb()) { mRoot.setOnSystemUiVisibilityChangeListener(new OnSystemUiVisibilityChangeListener() { @Override public void onSystemUiVisibilityChange(int visibility) { if ((visibility & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) == 0) { mHandler.sendEmptyMessageDelayed(MSG_HIDE_SYSTEM_UI, DEFAULT_TIME_OUT); } } }); } } private View inflateLayout() { return ((LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE)).inflate(R.layout.mediacontroller, this); } private void findViewItems(View v) { mMediaController = v.findViewById(R.id.mediacontroller); mSystemInfoLayout = v.findViewById(R.id.info_panel); mEndTime = (TextView) v.findViewById(R.id.mediacontroller_time_total); mCurrentTime = (TextView) v.findViewById(R.id.mediacontroller_time_current); mMenu = v.findViewById(R.id.video_menu); mMenu.setOnClickListener(mMenuListener); FractionalTouchDelegate.setupDelegate(mSystemInfoLayout, mMenu, new RectF(1.0f, 1f, 1.2f, 1.2f)); mFileName = (TextView) v.findViewById(R.id.mediacontroller_file_name); mDateTime = (TextView) v.findViewById(R.id.date_time); mDownloadRate = (TextView) v.findViewById(R.id.download_rate); mBatteryLevel = (TextView) v.findViewById(R.id.battery_level); mControlsLayout = v.findViewById(R.id.mediacontroller_controls); mControlsButtons = v.findViewById(R.id.mediacontroller_controls_buttons); mOperationInfo = (TextView) v.findViewById(R.id.operation_info); mOperationVolLum = v.findViewById(R.id.operation_volume_brightness); mVolLumBg = (ImageView) v.findViewById(R.id.operation_bg); mVolLumNum = (ImageView) v.findViewById(R.id.operation_percent); mLock = (ImageButton) v.findViewById(R.id.mediacontroller_lock); mLock.setOnClickListener(mLockClickListener); FractionalTouchDelegate.setupDelegate(mSystemInfoLayout, mLock, new RectF(1.0f, 1f, 1.2f, 1.2f)); mScreenToggle = (ImageButton) v.findViewById(R.id.mediacontroller_screen_size); mScreenToggle.setOnClickListener(mScreenToggleListener); mSnapshot = (ImageButton) v.findViewById(R.id.mediacontroller_snapshot); mSnapshot.setOnClickListener(mSnapshotListener); mPauseButton = (ImageButton) v.findViewById(R.id.mediacontroller_play_pause); mPauseButton.setOnClickListener(mPauseListener); mProgress = (SeekBar) v.findViewById(R.id.mediacontroller_seekbar); mProgress.setOnSeekBarChangeListener(mSeekListener); mProgress.setMax(DEFAULT_SEEKBAR_VALUE); mDanmakuSend = (ImageButton) v.findViewById(R.id.mediacontroller_send_danmaku); mDanmakuSend.setOnClickListener(mDanmakuSendListener); mDanmakuSwitch = (ImageButton) v.findViewById(R.id.mediacontroller_danmaku_switch); mDanmakuSwitch.setOnClickListener(mDanmakuSwitchListener); } public void setAnchorView(View view) { mAnchor = view; int[] location = new int[2]; mAnchor.getLocationOnScreen(location); Rect anchorRect = new Rect(location[0], location[1], location[0] + mAnchor.getWidth(), location[1] + mAnchor.getHeight()); setWindowLayoutType(); mWindow.showAtLocation(mAnchor, Gravity.NO_GRAVITY, anchorRect.left, anchorRect.bottom); } public void release() { if (mWindow != null) { mWindow.dismiss(); mWindow = null; } } private OnClickListener mMenuListener = new OnClickListener() { @Override public void onClick(View v) { mPlayer.showMenu(); } }; private void setOperationInfo(String info, long time) { mOperationInfo.setText(info); mOperationInfo.setVisibility(View.VISIBLE); mHandler.removeMessages(MSG_HIDE_OPERATION_INFO); mHandler.sendEmptyMessageDelayed(MSG_HIDE_OPERATION_INFO, time); } private void setBrightnessScale(float scale) { setGraphicOperationProgress(R.drawable.video_brightness_bg, scale); } private void setVolumeScale(float scale) { setGraphicOperationProgress(R.drawable.video_volumn_bg, scale); } private void setGraphicOperationProgress(int bgID, float scale) { mVolLumBg.setImageResource(bgID); mOperationInfo.setVisibility(View.GONE); mOperationVolLum.setVisibility(View.VISIBLE); ViewGroup.LayoutParams lp = mVolLumNum.getLayoutParams(); lp.width = (int) (findViewById(R.id.operation_full).getLayoutParams().width * scale); mVolLumNum.setLayoutParams(lp); } public void setFileName(String name) { mFileName.setText(name); } public void setDownloadRate(String rate) { mDownloadRate.setVisibility(View.VISIBLE); mDownloadRate.setText(rate); } public void setBatteryLevel(String level) { mBatteryLevel.setVisibility(View.VISIBLE); mBatteryLevel.setText(level); } public void setMediaPlayer(MediaPlayerControl player) { mPlayer = player; updatePausePlay(); } public void show() { show(DEFAULT_TIME_OUT); } public void show(int timeout) { if (timeout != 0) { mHandler.removeMessages(MSG_FADE_OUT); mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_FADE_OUT), timeout); } if (!mShowing) { showButtons(true); mHandler.removeMessages(MSG_HIDE_SYSTEM_UI); showSystemUi(true); mPauseButton.requestFocus(); mControlsLayout.startAnimation(mAnimSlideInTop); mSystemInfoLayout.startAnimation(mAnimSlideInBottom); mMediaController.setVisibility(View.VISIBLE); updatePausePlay(); mHandler.sendEmptyMessage(MSG_TIME_TICK); mHandler.sendEmptyMessage(MSG_SHOW_PROGRESS); mShowing = true; } } public void hide() { if (mShowing) { try { mHandler.removeMessages(MSG_TIME_TICK); mHandler.removeMessages(MSG_SHOW_PROGRESS); mControlsLayout.startAnimation(mAnimSlideOutTop); mSystemInfoLayout.startAnimation(mAnimSlideOutBottom); } catch (IllegalArgumentException ex) { Logger.d("MediaController already removed"); } mShowing = false; } } private void toggleVideoMode(boolean larger, boolean recycle) { if (larger) { if (mVideoMode < VideoView.VIDEO_LAYOUT_ZOOM) mVideoMode++; else if (recycle) mVideoMode = VideoView.VIDEO_LAYOUT_ORIGIN; } else { if (mVideoMode > VideoView.VIDEO_LAYOUT_ORIGIN) mVideoMode--; else if (recycle) mVideoMode = VideoView.VIDEO_LAYOUT_ZOOM; } switch (mVideoMode) { case VideoView.VIDEO_LAYOUT_ORIGIN: setOperationInfo(mContext.getString(R.string.video_original), 500); mScreenToggle.setImageResource(R.drawable.mediacontroller_sreen_size_100); break; case VideoView.VIDEO_LAYOUT_SCALE: setOperationInfo(mContext.getString(R.string.video_fit_screen), 500); mScreenToggle.setImageResource(R.drawable.mediacontroller_screen_fit); break; case VideoView.VIDEO_LAYOUT_STRETCH: setOperationInfo(mContext.getString(R.string.video_stretch), 500); mScreenToggle.setImageResource(R.drawable.mediacontroller_screen_size); break; case VideoView.VIDEO_LAYOUT_ZOOM: setOperationInfo(mContext.getString(R.string.video_crop), 500); mScreenToggle.setImageResource(R.drawable.mediacontroller_sreen_size_crop); break; } mPlayer.toggleVideoMode(mVideoMode); } private void lock(boolean toLock) { if (toLock) { mLock.setImageResource(R.drawable.mediacontroller_lock); mMenu.setVisibility(View.GONE); mControlsButtons.setVisibility(View.GONE); mProgress.setEnabled(false); if (mScreenLocked != toLock) setOperationInfo(mContext.getString(R.string.video_screen_locked), 1000); } else { mLock.setImageResource(R.drawable.mediacontroller_unlock); // If you wanna to show, set mMenu visible mMenu.setVisibility(View.GONE); mControlsButtons.setVisibility(View.VISIBLE); mProgress.setEnabled(true); if (mScreenLocked != toLock) setOperationInfo(mContext.getString(R.string.video_screen_unlocked), 1000); } mScreenLocked = toLock; mGestures.setTouchListener(mTouchListener, !mScreenLocked); } public boolean isLocked() { return mScreenLocked; } private static final int MSG_FADE_OUT = 1; private static final int MSG_SHOW_PROGRESS = 2; private static final int MSG_HIDE_SYSTEM_UI = 3; private static final int MSG_TIME_TICK = 4; private static final int MSG_HIDE_OPERATION_INFO = 5; private static final int MSG_HIDE_OPERATION_VOLLUM = 6; private static class MHandler extends Handler { private WeakReference mc; public MHandler(MediaController mc) { this.mc = new WeakReference(mc); } @Override public void handleMessage(Message msg) { MediaController c = mc.get(); if (c == null) return; switch (msg.what) { case MSG_FADE_OUT: c.hide(); break; case MSG_SHOW_PROGRESS: long pos = c.setProgress(); if (!c.mDragging && c.mShowing) { msg = obtainMessage(MSG_SHOW_PROGRESS); sendMessageDelayed(msg, 1000 - (pos % 1000)); c.updatePausePlay(); } break; case MSG_HIDE_SYSTEM_UI: if (!c.mShowing) c.showSystemUi(false); break; case MSG_TIME_TICK: c.mDateTime.setText(StringUtils.currentTimeString()); sendEmptyMessageDelayed(MSG_TIME_TICK, TIME_TICK_INTERVAL); break; case MSG_HIDE_OPERATION_INFO: c.mOperationInfo.setVisibility(View.GONE); break; case MSG_HIDE_OPERATION_VOLLUM: c.mOperationVolLum.setVisibility(View.GONE); break; } } }; private long setProgress() { if (mPlayer == null || mDragging) return 0; long position = mPlayer.getCurrentPosition(); long duration = mPlayer.getDuration(); if (duration > 0) { long pos = 1000L * position / duration; mProgress.setProgress((int) pos); } int percent = mPlayer.getBufferPercentage(); mProgress.setSecondaryProgress(percent * 10); mDuration = duration; mEndTime.setText(StringUtils.generateTime(mDuration)); mCurrentTime.setText(StringUtils.generateTime(position)); return position; } @Override public boolean onTouchEvent(MotionEvent event) { mHandler.removeMessages(MSG_HIDE_SYSTEM_UI); mHandler.sendEmptyMessageDelayed(MSG_HIDE_SYSTEM_UI, DEFAULT_TIME_OUT); return mGestures.onTouchEvent(event) || super.onTouchEvent(event); } private CommonGestures.TouchListener mTouchListener = new CommonGestures.TouchListener() { @Override public void onGestureBegin() { mBrightness = mContext.getWindow().getAttributes().screenBrightness; mVolume = mAM.getStreamVolume(AudioManager.STREAM_MUSIC); if (mBrightness <= 0.00f) mBrightness = 0.50f; if (mBrightness < 0.01f) mBrightness = 0.01f; if (mVolume < 0) mVolume = 0; } @Override public void onGestureEnd() { mOperationVolLum.setVisibility(View.GONE); } @Override public void onLeftSlide(float percent) { setBrightness(mBrightness + percent); setBrightnessScale(mContext.getWindow().getAttributes().screenBrightness); } @Override public void onRightSlide(float percent) { int v = (int) (percent * mMaxVolume) + mVolume; setVolume(v); } @Override public void onSingleTap() { if (mShowing) hide(); else show(); if (mPlayer.getBufferPercentage() >= 100) mPlayer.removeLoadingView(); } @Override public void onDoubleTap() { toggleVideoMode(true, true); } @Override public void onLongPress() { doPauseResume(); } @Override public void onScale(float scaleFactor, int state) { switch (state) { case CommonGestures.SCALE_STATE_BEGIN: mVideoMode = VideoView.VIDEO_LAYOUT_SCALE_ZOOM; mScreenToggle.setImageResource(R.drawable.mediacontroller_sreen_size_100); mPlayer.toggleVideoMode(mVideoMode); break; case CommonGestures.SCALE_STATE_SCALEING: float currentRatio = mPlayer.scale(scaleFactor); setOperationInfo((int) (currentRatio * 100) + "%", 500); break; case CommonGestures.SCALE_STATE_END: break; } } }; private void setVolume(int v) { if (v > mMaxVolume) v = mMaxVolume; else if (v < 0) v = 0; mAM.setStreamVolume(AudioManager.STREAM_MUSIC, v, 0); setVolumeScale((float) v / mMaxVolume); } private void setBrightness(float f) { WindowManager.LayoutParams lp = mContext.getWindow().getAttributes(); lp.screenBrightness = f; if (lp.screenBrightness > 1.0f) lp.screenBrightness = 1.0f; else if (lp.screenBrightness < 0.01f) lp.screenBrightness = 0.01f; mContext.getWindow().setAttributes(lp); } @Override public boolean onTrackballEvent(MotionEvent ev) { show(DEFAULT_TIME_OUT); return false; } @Override public boolean dispatchKeyEvent(KeyEvent event) { int keyCode = event.getKeyCode(); switch (keyCode) { case KeyEvent.KEYCODE_VOLUME_MUTE: return super.dispatchKeyEvent(event); case KeyEvent.KEYCODE_VOLUME_UP: case KeyEvent.KEYCODE_VOLUME_DOWN: mVolume = mAM.getStreamVolume(AudioManager.STREAM_MUSIC); int step = keyCode == KeyEvent.KEYCODE_VOLUME_UP ? 1 : -1; setVolume(mVolume + step); mHandler.removeMessages(MSG_HIDE_OPERATION_VOLLUM); mHandler.sendEmptyMessageDelayed(MSG_HIDE_OPERATION_VOLLUM, 500); return true; } if (isLocked()) { show(); return true; } if (event.getRepeatCount() == 0 && (keyCode == KeyEvent.KEYCODE_HEADSETHOOK || keyCode == KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE || keyCode == KeyEvent.KEYCODE_SPACE)) { doPauseResume(); show(DEFAULT_TIME_OUT); return true; } else if (keyCode == KeyEvent.KEYCODE_MEDIA_STOP) { if (mPlayer.isPlaying()) { mPlayer.pause(); updatePausePlay(); } return true; } else if (keyCode == KeyEvent.KEYCODE_BACK) { release(); mPlayer.stop(); return true; } else { show(DEFAULT_TIME_OUT); } return super.dispatchKeyEvent(event); } @TargetApi(11) private void showSystemUi(boolean visible) { if (DeviceUtils.hasHoneycomb()) { int flag = visible ? 0 : View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_LOW_PROFILE; mRoot.setSystemUiVisibility(flag); } } private void showButtons(boolean showButtons) { Window window = mContext.getWindow(); WindowManager.LayoutParams layoutParams = window.getAttributes(); float val = showButtons ? -1 : 0; try { Field buttonBrightness = layoutParams.getClass().getField("buttonBrightness"); buttonBrightness.set(layoutParams, val); } catch (Exception e) { Logger.e("dimButtons", e); } window.setAttributes(layoutParams); } private void updatePausePlay() { if (mPlayer.isPlaying()) mPauseButton.setImageResource(R.drawable.mediacontroller_pause); else mPauseButton.setImageResource(R.drawable.mediacontroller_play); } private void doPauseResume() { if (mPlayer.isPlaying()) mPlayer.pause(); else mPlayer.start(); updatePausePlay(); } private OnClickListener mPauseListener = new OnClickListener() { @Override public void onClick(View v) { if (mPlayer.isPlaying()) show(DEFAULT_LONG_TIME_SHOW); else show(); doPauseResume(); } }; private OnClickListener mLockClickListener = new OnClickListener() { @Override public void onClick(View v) { hide(); lock(!mScreenLocked); show(); } }; private OnClickListener mScreenToggleListener = new OnClickListener() { @Override public void onClick(View v) { show(DEFAULT_TIME_OUT); toggleVideoMode(true, true); } }; private OnClickListener mSnapshotListener = new OnClickListener() { @Override public void onClick(View v) { show(DEFAULT_TIME_OUT); mSnapshot.setEnabled(false); mPlayer.snapshot(); mSnapshot.setEnabled(true); } }; private OnSeekBarChangeListener mSeekListener = new OnSeekBarChangeListener() { private boolean wasStopped = false; @Override public void onStartTrackingTouch(SeekBar bar) { mDragging = true; show(3600000); mHandler.removeMessages(MSG_SHOW_PROGRESS); wasStopped = !mPlayer.isPlaying(); if (mInstantSeeking) { mAM.setStreamMute(AudioManager.STREAM_MUSIC, true); if (wasStopped) { mPlayer.start(); } } } @Override public void onProgressChanged(SeekBar bar, int progress, boolean fromuser) { if (!fromuser) return; long newposition = (mDuration * progress) / 1000; String time = StringUtils.generateTime(newposition); if (mInstantSeeking) mPlayer.seekTo(newposition); setOperationInfo(time, 1500); mCurrentTime.setText(time); } @Override public void onStopTrackingTouch(SeekBar bar) { if (!mInstantSeeking) { mPlayer.seekTo((mDuration * bar.getProgress()) / 1000); } else if (wasStopped) { mPlayer.pause(); } mOperationInfo.setVisibility(View.GONE); show(DEFAULT_TIME_OUT); mHandler.removeMessages(MSG_SHOW_PROGRESS); mAM.setStreamMute(AudioManager.STREAM_MUSIC, false); mDragging = false; mHandler.sendEmptyMessageDelayed(MSG_SHOW_PROGRESS, 1000); } }; private OnClickListener mDanmakuSendListener = new OnClickListener() { @Override public void onClick(View v) { ToastUtils.showToast("发送弹幕(没有实现功能)"); } }; private OnClickListener mDanmakuSwitchListener = new OnClickListener() { @Override public void onClick(View v) { if (mDanmakuShow) { mDanmakuSwitch.setImageResource(R.drawable.bili_player_danmaku_is_closed); mPlayer.setDanmakushow(false); mDanmakuShow = false; } else { mDanmakuSwitch.setImageResource(R.drawable.bili_player_danmaku_is_open); mPlayer.setDanmakushow(true); mDanmakuShow = true; } } }; public interface MediaPlayerControl { void start(); void pause(); void stop(); void seekTo(long pos); boolean isPlaying(); long getDuration(); long getCurrentPosition(); int getBufferPercentage(); void previous(); void next(); long goForward(); long goBack(); void toggleVideoMode(int mode); void showMenu(); void removeLoadingView(); float scale(float scale); void snapshot(); void setDanmakushow(boolean isShow); } } ================================================ FILE: app/src/main/java/com/cjj/bb/view/PlayerService.java ================================================ /* * Copyright (C) 2012 YIXIA.COM * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.cjj.bb.view; import io.vov.vitamio.MediaPlayer; import io.vov.vitamio.MediaPlayer.OnBufferingUpdateListener; import io.vov.vitamio.MediaPlayer.OnCompletionListener; import io.vov.vitamio.MediaPlayer.OnErrorListener; import io.vov.vitamio.MediaPlayer.OnHWRenderFailedListener; import io.vov.vitamio.MediaPlayer.OnInfoListener; import io.vov.vitamio.MediaPlayer.OnPreparedListener; import io.vov.vitamio.MediaPlayer.OnSeekCompleteListener; import io.vov.vitamio.MediaPlayer.OnTimedTextListener; import io.vov.vitamio.MediaPlayer.OnVideoSizeChangedListener; import io.vov.vitamio.Vitamio; import io.vov.vitamio.utils.Log; import java.io.File; import java.io.IOException; import java.util.ArrayList; import android.app.Service; import android.content.Context; import android.content.Intent; import android.graphics.Bitmap; import android.net.Uri; import android.os.Binder; import android.os.IBinder; import android.telephony.PhoneStateListener; import android.telephony.TelephonyManager; import android.view.SurfaceHolder; import com.cjj.bb.utils.Logger; public class PlayerService extends Service implements OnBufferingUpdateListener, OnCompletionListener, OnPreparedListener, OnVideoSizeChangedListener, OnErrorListener, OnInfoListener, OnSeekCompleteListener, OnTimedTextListener { private MediaPlayer mPlayer; private VPlayerListener mListener; private Uri mUri; private Uri mOldUri; private float mSeekTo = -1f; private boolean mFromNotification; private String[] mSubPaths; private boolean mInitialized; private final IBinder mBinder = new LocalBinder(); private TelephonyManager mTelephonyManager; private int mCurrentState; private SurfaceHolder mSurfaceHolder; public static final int VPLYAER_NOTIFICATION_ID = 1; public static final int STATE_PREPARED = -1; public static final int STATE_PLAYING = 0; public static final int STATE_NEED_RESUME = 1; public static final int STATE_STOPPED = 2; public static final int STATE_RINGING = 3; private int mLastAudioTrack = -1; private String mLastSubTrack; private int mLastSubTrackId = -1; private long mMediaId = -1l; public class LocalBinder extends Binder { public PlayerService getService() { return PlayerService.this; } } @Override public void onCreate() { super.onCreate(); mInitialized = false; mTelephonyManager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE); mTelephonyManager.listen(mPhoneListener, PhoneStateListener.LISTEN_CALL_STATE); } @Override public int onStartCommand(Intent intent, int flags, int startId) { if (Vitamio.isInitialized(this)) { vplayerInit(intent.getBooleanExtra("isHWCodec", false)); } else { stopSelf(); } Log.d("CREATE OK"); return super.onStartCommand(intent, flags, startId); } private void vplayerInit(boolean isHWCodec) { mPlayer = new MediaPlayer(PlayerService.this.getApplicationContext(), isHWCodec); mPlayer.setOnHWRenderFailedListener(new OnHWRenderFailedListener() { @Override public void onFailed() { if (mListener != null) mListener.onHWRenderFailed(); } }); mPlayer.setOnBufferingUpdateListener(PlayerService.this); mPlayer.setOnCompletionListener(PlayerService.this); mPlayer.setOnPreparedListener(PlayerService.this); mPlayer.setOnVideoSizeChangedListener(PlayerService.this); mPlayer.setOnErrorListener(PlayerService.this); mPlayer.setOnInfoListener(PlayerService.this); } public void releaseContext() { if (mPlayer != null) mPlayer.release(); mPlayer = null; } @Override public IBinder onBind(Intent intent) { Log.d("BIND OK : " + intent.getPackage()); return mBinder; } @Override public void onDestroy() { super.onDestroy(); release(true); releaseContext(); } public boolean isInitialized() { return mInitialized; } private String mTitle; public boolean initialize(Uri filePath, String displayName, boolean saveUri, float startPos, VPlayerListener listener, int parentId, boolean isHWCodec) { if (mPlayer == null) vplayerInit(isHWCodec); mTitle = displayName; mListener = listener; mOldUri = mUri; mUri = filePath; mSeekTo = startPos; mMediaId = -1; mLastAudioTrack = -1; mLastSubTrackId = -1; mLastSubTrack = ""; setMediaTrack(); Log.i("%s ==> %s, %s, %s, %s", mOldUri, mUri, mInitialized, mPrepared, mVideoSizeKnown); mFromNotification = mInitialized && mUri != null && mUri.equals(mOldUri); mListener.onOpenStart(); if (!mFromNotification) openVideo(); else openSuccess(); return mInitialized; } private void setMediaTrack() { } private void openVideo() { if (mUri == null || mPlayer == null) return; mPlayer.reset(); mInitialized = false; mPrepared = false; mVideoSizeKnown = false; try { mPlayer.setScreenOnWhilePlaying(true); mPlayer.setDataSource(PlayerService.this, mUri); // if (mLastAudioTrack != -1) // mPlayer.setInitialAudioTrack(mLastAudioTrack); // if (mLastSubTrackId != -1) // mPlayer.setInitialSubTrack(mLastSubTrackId); if (mSurfaceHolder != null && mSurfaceHolder.getSurface() != null && mSurfaceHolder.getSurface().isValid()) mPlayer.setDisplay(mSurfaceHolder); mPlayer.prepareAsync(); } catch (IllegalArgumentException e) { Logger.e("openVideo", e); } catch (IllegalStateException e) { Logger.e("openVideo", e); } catch (IOException e) { Logger.e("openVideo", e); } } public Uri getUri() { return mUri; } public long getMediaId() { return mMediaId; } public int getLastAudioTrack() { return mLastAudioTrack; } public String getLastSubTrack() { return mLastSubTrack; } public int getLastSubTrackId() { return mLastSubTrackId; } public void setVPlayerListener(VPlayerListener listener) { mListener = listener; } public void setState(int state) { mCurrentState = state; } public boolean needResume() { return mInitialized && (mCurrentState == STATE_NEED_RESUME || mCurrentState == STATE_PREPARED); } public boolean ringingState() { return mInitialized && mCurrentState == STATE_RINGING; } public void release() { release(true); } private void release(boolean all) { if (mPlayer != null) { if (mListener != null) mListener.onCloseStart(); mPlayer.reset(); mInitialized = false; mPrepared = false; mVideoSizeKnown = false; if (mListener != null) mListener.onCloseComplete(); } if (all) { mListener = null; mUri = null; } } public void stop() { if (mInitialized) { mPlayer.pause(); } } public void start() { if (mInitialized) { mPlayer.start(); setState(STATE_PLAYING); } } public void setDisplay(SurfaceHolder surface) { mSurfaceHolder = surface; if (mPlayer != null) mPlayer.setDisplay(surface); } public void releaseSurface() { if (mInitialized) mPlayer.releaseDisplay(); } public boolean isPlaying() { return (mInitialized && mPlayer.isPlaying()); } public int getVideoWidth() { if (mInitialized) return mPlayer.getVideoWidth(); return 0; } public int getVideoHeight() { if (mInitialized) return mPlayer.getVideoHeight(); return 0; } public float getVideoAspectRatio() { if (mInitialized) return mPlayer.getVideoAspectRatio(); return 0f; } public long getDuration() { if (mInitialized) return mPlayer.getDuration(); return 0; } public long getCurrentPosition() { if (mInitialized) return mPlayer.getCurrentPosition(); return 0; } public Bitmap getCurrentFrame() { if (mInitialized) return mPlayer.getCurrentFrame(); return null; } public float getBufferProgress() { if (mInitialized) return mPlayer.getBufferProgress(); return 0f; } public void seekTo(float percent) { if (mInitialized) mPlayer.seekTo((int) (percent * getDuration())); } public String getMetaEncoding() { if (mInitialized) return mPlayer.getMetaEncoding(); return null; } public void setAudioTrack(int num) { if (mInitialized) mPlayer.selectTrack(num); // mPlayer.setAudioTrack(num); } public int getAudioTrack() { if (mInitialized) return mPlayer.getAudioTrack(); return 0; } // public HashMap getAudioTrackMap() { // if (!mInitialized) // return null; // String enc = VP.DEFAULT_META_ENCODING; // return mPlayer.getAudioTrackMap(enc.equals(VP.DEFAULT_META_ENCODING) ? // getMetaEncoding() : enc); // } // // public HashMap getSubTrackMap() { // if (!mInitialized) // return null; // String enc = VP.DEFAULT_SUB_ENCODING; // HashMap trackMap = new HashMap(); // HashMap m = // mPlayer.getSubTrackMap(enc.equals(VP.DEFAULT_SUB_ENCODING) ? // getMetaEncoding() : enc); // if (m != null) // for (String k : m.keySet()) // trackMap.put(k, m.get(k)); // // if (mSubPaths != null) // for (String s : mSubPaths) // trackMap.put(new File(s).getName(), s); // // return trackMap; // } // // public int getSubTrack() { // if (mInitialized) // return mPlayer.getSubTrack(); // return 0; // } // // public void setSubTrack(int id) { // if (mInitialized) // mPlayer.setSubTrack(id); // } // // public String getSubPath() { // if (mInitialized) // return mPlayer.getSubPath(); // return null; // } public void setSubShown(boolean shown) { if (mInitialized) mPlayer.setTimedTextShown(shown);// setSubtitleShown -> // setTimedTextShown 4.0 } public boolean isBuffering() { return (mInitialized && mPlayer.isBuffering()); } public void setBuffer(int bufSize) { if (mInitialized) mPlayer.setBufferSize(bufSize); } public void setVolume(float left, float right) { if (mInitialized) { if (left <= 0f) left = 0f; else if (left >= 1f) left = 1f; if (right <= 0f) right = 0f; else if (right >= 1f) right = 1f; mPlayer.setVolume(left, right); } } public void setVideoQuality(int quality) { if (mInitialized) mPlayer.setVideoQuality(quality); } public void setDeinterlace(boolean deinterlace) { if (mInitialized) mPlayer.setDeinterlace(deinterlace); } // public int getSubLocation() { // if (mInitialized) // return mPlayer.getSubLocation(); // return -1; // } // public void setSubEncoding(String encoding) { if (mInitialized) { String enc = encoding.equals(VP.DEFAULT_SUB_ENCODING) ? null : encoding; mPlayer.setTimedTextEncoding(enc);// setSubEncoding -> // setTimedTextEncoding } } public void setSubPath(String subPath) { if (mInitialized) mPlayer.addTimedTextSource(subPath); // mPlayer.setSubPath(subPath); } public static interface VPlayerListener { public void onHWRenderFailed(); public void onVideoSizeChanged(int width, int height); public void onSubChanged(String text); public void onSubChanged(byte[] pixels, int width, int height); public void onOpenStart(); public void onOpenSuccess(); public void onOpenFailed(); public void onBufferStart(); public void onBufferComplete(); public void onDownloadRateChanged(int kbPerSec); public void onPlaybackComplete(); public void onCloseStart(); public void onCloseComplete(); } private PhoneStateListener mPhoneListener = new PhoneStateListener() { @Override public void onCallStateChanged(int state, String incomingNumber) { switch (state) { case TelephonyManager.CALL_STATE_IDLE: break; case TelephonyManager.CALL_STATE_OFFHOOK: case TelephonyManager.CALL_STATE_RINGING: if (isPlaying()) { stop(); setState(STATE_RINGING); } break; default: break; } } }; private boolean mVideoSizeKnown = false; private boolean mPrepared = false; @Override public void onVideoSizeChanged(MediaPlayer arg0, int arg1, int arg2) { mVideoSizeKnown = true; if (mListener != null) mListener.onVideoSizeChanged(arg1, arg2); } @Override public void onPrepared(MediaPlayer arg0) { mPrepared = true; openSuccess(); } private void openSuccess() { mInitialized = true; if (!mFromNotification && mSeekTo > 0 && mSeekTo < 1) seekTo(mSeekTo); mSeekTo = -1; mListener.onOpenSuccess(); if (!mFromNotification) { setSubEncoding(VP.DEFAULT_SUB_ENCODING); if (mUri != null) mSubPaths = getSubFiles(mUri.getPath()); if (mSubPaths != null) setSubPath(FileUtils.getCanonical(new File(mSubPaths[0]))); setSubShown(VP.DEFAULT_SUB_SHOWN); } } @Override public void onCompletion(MediaPlayer arg0) { if (mListener != null) { mListener.onPlaybackComplete(); } else { release(true); } } @Override public void onBufferingUpdate(MediaPlayer arg0, int arg1) { } @Override public void onSeekComplete(MediaPlayer arg0) { } @Override public boolean onInfo(MediaPlayer arg0, int arg1, int arg2) { switch (arg1) { case MediaPlayer.MEDIA_INFO_BUFFERING_START: if (mListener != null) mListener.onBufferStart(); else mPlayer.pause(); break; case MediaPlayer.MEDIA_INFO_BUFFERING_END: if (mListener != null) mListener.onBufferComplete(); else mPlayer.start(); break; case MediaPlayer.MEDIA_INFO_DOWNLOAD_RATE_CHANGED: if (mListener != null) mListener.onDownloadRateChanged(arg2); break; } return true; } @Override public boolean onError(MediaPlayer arg0, int arg1, int arg2) { mListener.onOpenFailed(); return true; } private String[] getSubFiles(String videoPath) { ArrayList files = new ArrayList(); for (String ext : MediaPlayer.SUB_TYPES) { File s = new File(videoPath.substring(0, videoPath.lastIndexOf('.') > 0 ? videoPath.lastIndexOf('.') : videoPath.length()) + ext); if (s.exists() && s.isFile() && s.canRead()) files.add(s.getAbsolutePath()); } if (files.isEmpty()) return null; else return files.toArray(new String[files.size()]); } @Override public void onTimedText(String text) { if (mListener != null) mListener.onSubChanged(text); } @Override public void onTimedTextUpdate(byte[] pixels, int width, int height) { if (mListener != null) mListener.onSubChanged(pixels, width, height); } // @Override // public void onSubtitleUpdate(String arg0) { // if (mListener != null) // mListener.onSubChanged(arg0); // } // // @Override // public void onSubtitleUpdate(byte[] arg0, int arg1, int arg2) { // if (mListener != null) // mListener.onSubChanged(arg0, arg1, arg2); // } } ================================================ FILE: app/src/main/java/com/cjj/bb/view/PullToZoomListView.java ================================================ package com.cjj.bb.view; import android.app.Activity; import android.content.Context; import android.os.SystemClock; import android.util.AttributeSet; import android.util.DisplayMetrics; import android.util.Log; import android.view.MotionEvent; import android.view.ViewGroup; import android.view.animation.Interpolator; import android.widget.AbsListView; import android.widget.FrameLayout; import android.widget.ImageView; import android.widget.ListView; /** * 下拉缩放 * * @author open resource * */ public class PullToZoomListView extends ListView implements AbsListView.OnScrollListener { private static final int INVALID_VALUE = -1; private static final String TAG = "PullToZoomListView"; private static final Interpolator sInterpolator = new Interpolator() { public float getInterpolation(float paramAnonymousFloat) { float f = paramAnonymousFloat - 1.0F; return 1.0F + f * (f * (f * (f * f))); } }; int mActivePointerId = -1; private FrameLayout mHeaderContainer; private int mHeaderHeight; private ImageView mHeaderImage; float mLastMotionY = -1.0F; float mLastScale = -1.0F; float mMaxScale = -1.0F; private OnScrollListener mOnScrollListener; private ScalingRunnalable mScalingRunnalable; private int mScreenHeight; private ImageView mShadow; public PullToZoomListView(Context paramContext) { super(paramContext); init(paramContext); } public PullToZoomListView(Context paramContext, AttributeSet paramAttributeSet) { super(paramContext, paramAttributeSet); init(paramContext); } public PullToZoomListView(Context paramContext, AttributeSet paramAttributeSet, int paramInt) { super(paramContext, paramAttributeSet, paramInt); init(paramContext); } private void endScraling() { if (this.mHeaderContainer.getBottom() >= this.mHeaderHeight) Log.d("mmm", "endScraling"); this.mScalingRunnalable.startAnimation(200L); } private void init(Context paramContext) { DisplayMetrics localDisplayMetrics = new DisplayMetrics(); ((Activity) paramContext).getWindowManager().getDefaultDisplay() .getMetrics(localDisplayMetrics); this.mScreenHeight = localDisplayMetrics.heightPixels; this.mHeaderContainer = new FrameLayout(paramContext); this.mHeaderImage = new ImageView(paramContext); int i = localDisplayMetrics.widthPixels; setHeaderViewSize(i, (int) (9.0F * (i / 16.0F))); this.mShadow = new ImageView(paramContext); FrameLayout.LayoutParams localLayoutParams = new FrameLayout.LayoutParams( -1, -2); localLayoutParams.gravity = 80; this.mShadow.setLayoutParams(localLayoutParams); this.mHeaderContainer.addView(this.mHeaderImage); this.mHeaderContainer.addView(this.mShadow); addHeaderView(this.mHeaderContainer); this.mScalingRunnalable = new ScalingRunnalable(); super.setOnScrollListener(this); } private void onSecondaryPointerUp(MotionEvent paramMotionEvent) { int i = (paramMotionEvent.getAction()) >> 8; if (paramMotionEvent.getPointerId(i) == this.mActivePointerId) if (i != 0) { int j = 1; this.mLastMotionY = paramMotionEvent.getY(0); this.mActivePointerId = paramMotionEvent.getPointerId(0); return; } } private void reset() { this.mActivePointerId = -1; this.mLastMotionY = -1.0F; this.mMaxScale = -1.0F; this.mLastScale = -1.0F; } public ImageView getHeaderView() { return this.mHeaderImage; } public boolean onInterceptTouchEvent(MotionEvent paramMotionEvent) { return super.onInterceptTouchEvent(paramMotionEvent); } protected void onLayout(boolean paramBoolean, int paramInt1, int paramInt2, int paramInt3, int paramInt4) { super.onLayout(paramBoolean, paramInt1, paramInt2, paramInt3, paramInt4); if (this.mHeaderHeight == 0) this.mHeaderHeight = this.mHeaderContainer.getHeight(); } @Override public void onScroll(AbsListView paramAbsListView, int paramInt1, int paramInt2, int paramInt3) { Log.d("mmm", "onScroll"); float f = this.mHeaderHeight - this.mHeaderContainer.getBottom(); Log.d("mmm", "f|" + f); if ((f > 0.0F) && (f < this.mHeaderHeight)) { Log.d("mmm", "1"); int i = (int) (0.65D * f); this.mHeaderImage.scrollTo(0, -i); } else if (this.mHeaderImage.getScrollY() != 0) { Log.d("mmm", "2"); this.mHeaderImage.scrollTo(0, 0); } if (this.mOnScrollListener != null) { this.mOnScrollListener.onScroll(paramAbsListView, paramInt1, paramInt2, paramInt3); } } public void onScrollStateChanged(AbsListView paramAbsListView, int paramInt) { if (this.mOnScrollListener != null) this.mOnScrollListener.onScrollStateChanged(paramAbsListView, paramInt); } public boolean onTouchEvent(MotionEvent paramMotionEvent) { Log.d("mmm", "" + (0xFF & paramMotionEvent.getAction())); switch (0xFF & paramMotionEvent.getAction()) { case 4: case 0: if (!this.mScalingRunnalable.mIsFinished) { this.mScalingRunnalable.abortAnimation(); } this.mLastMotionY = paramMotionEvent.getY(); this.mActivePointerId = paramMotionEvent.getPointerId(0); this.mMaxScale = (this.mScreenHeight / this.mHeaderHeight); this.mLastScale = (this.mHeaderContainer.getBottom() / this.mHeaderHeight); break; case 2: Log.d("mmm", "mActivePointerId" + mActivePointerId); int j = paramMotionEvent.findPointerIndex(this.mActivePointerId); if (j == -1) { Log.e("PullToZoomListView", "Invalid pointerId=" + this.mActivePointerId + " in onTouchEvent"); } else { if (this.mLastMotionY == -1.0F) this.mLastMotionY = paramMotionEvent.getY(j); if (this.mHeaderContainer.getBottom() >= this.mHeaderHeight) { ViewGroup.LayoutParams localLayoutParams = this.mHeaderContainer .getLayoutParams(); float f = ((paramMotionEvent.getY(j) - this.mLastMotionY + this.mHeaderContainer .getBottom()) / this.mHeaderHeight - this.mLastScale) / 2.0F + this.mLastScale; if ((this.mLastScale <= 1.0D) && (f < this.mLastScale)) { localLayoutParams.height = this.mHeaderHeight; this.mHeaderContainer .setLayoutParams(localLayoutParams); return super.onTouchEvent(paramMotionEvent); } this.mLastScale = Math.min(Math.max(f, 1.0F), this.mMaxScale); localLayoutParams.height = ((int) (this.mHeaderHeight * this.mLastScale)); if (localLayoutParams.height < this.mScreenHeight) this.mHeaderContainer .setLayoutParams(localLayoutParams); this.mLastMotionY = paramMotionEvent.getY(j); return true; } this.mLastMotionY = paramMotionEvent.getY(j); } break; case 1: reset(); endScraling(); break; case 3: int i = paramMotionEvent.getActionIndex(); this.mLastMotionY = paramMotionEvent.getY(i); this.mActivePointerId = paramMotionEvent.getPointerId(i); break; case 5: onSecondaryPointerUp(paramMotionEvent); this.mLastMotionY = paramMotionEvent.getY(paramMotionEvent .findPointerIndex(this.mActivePointerId)); break; case 6: } return super.onTouchEvent(paramMotionEvent); } public void setHeaderViewSize(int paramInt1, int paramInt2) { Object localObject = this.mHeaderContainer.getLayoutParams(); if (localObject == null) localObject = new LayoutParams(paramInt1, paramInt2); ((ViewGroup.LayoutParams) localObject).width = paramInt1; ((ViewGroup.LayoutParams) localObject).height = paramInt2; this.mHeaderContainer .setLayoutParams((ViewGroup.LayoutParams) localObject); this.mHeaderHeight = paramInt2; } public void setOnScrollListener( OnScrollListener paramOnScrollListener) { this.mOnScrollListener = paramOnScrollListener; } public void setShadow(int paramInt) { this.mShadow.setBackgroundResource(paramInt); } class ScalingRunnalable implements Runnable { long mDuration; boolean mIsFinished = true; float mScale; long mStartTime; ScalingRunnalable() { } public void abortAnimation() { this.mIsFinished = true; } public boolean isFinished() { return this.mIsFinished; } public void run() { float f2; ViewGroup.LayoutParams localLayoutParams; if ((!this.mIsFinished) && (this.mScale > 1.0D)) { float f1 = ((float) SystemClock.currentThreadTimeMillis() - (float) this.mStartTime) / (float) this.mDuration; f2 = this.mScale - (this.mScale - 1.0F) * PullToZoomListView.sInterpolator.getInterpolation(f1); localLayoutParams = PullToZoomListView.this.mHeaderContainer .getLayoutParams(); if (f2 > 1.0F) { Log.d("mmm", "f2>1.0"); localLayoutParams.height = PullToZoomListView.this.mHeaderHeight; localLayoutParams.height = ((int) (f2 * PullToZoomListView.this.mHeaderHeight)); PullToZoomListView.this.mHeaderContainer .setLayoutParams(localLayoutParams); PullToZoomListView.this.post(this); return; } this.mIsFinished = true; } } public void startAnimation(long paramLong) { this.mStartTime = SystemClock.currentThreadTimeMillis(); this.mDuration = paramLong; this.mScale = ((float) (PullToZoomListView.this.mHeaderContainer .getBottom()) / PullToZoomListView.this.mHeaderHeight); this.mIsFinished = false; PullToZoomListView.this.post(this); } } } ================================================ FILE: app/src/main/java/com/cjj/bb/view/VP.java ================================================ package com.cjj.bb.view; import io.vov.vitamio.MediaPlayer; import android.graphics.Typeface; public class VP { public static final String SNAP_SHOT_PATH = "/Player"; public static final String SESSION_LAST_POSITION_SUFIX = ".last"; // key public static final String SUB_SHADOW_COLOR = "vplayer_sub_shadow_color"; public static final String SUB_POSITION = "vplayer_sub_position"; public static final String SUB_SIZE = "vplayer_sub_size"; public static final String SUB_SHADOW_RADIUS = "vplayer_sub_shadow_radius"; public static final String SUB_ENABLED = "vplayer_sub_enabled"; public static final String SUB_SHADOW_ENABLED = "vplayer_sub_shadow_enabled"; public static final String SUB_TEXT_KEY = "sub_text"; public static final String SUB_PIXELS_KEY = "sub_pixels"; public static final String SUB_WIDTH_KEY = "sub_width"; public static final String SUB_HEIGHT_KEY = "sub_height"; // default value 1024 public static final int DEFAULT_BUF_SIZE = 512 * 1024; public static final int DEFAULT_VIDEO_QUALITY = MediaPlayer.VIDEOQUALITY_MEDIUM; public static final boolean DEFAULT_DEINTERLACE = false; public static final float DEFAULT_ASPECT_RATIO = 0f; public static final float DEFAULT_STEREO_VOLUME = 1.0f; public static final String DEFAULT_META_ENCODING = "auto"; public static final String DEFAULT_SUB_ENCODING = "auto"; public static final int DEFAULT_SUB_STYLE = Typeface.BOLD; public static final int DEFAULT_SUB_COLOR = 0xffffffff; public static final int DEFAULT_SUB_SHADOWCOLOR = 0xff000000; public static final float DEFAULT_SUB_SHADOWRADIUS = 2.0f; public static final float DEFAULT_SUB_SIZE = 18.0f; public static final float DEFAULT_SUB_POS = 10.0f; public static final int DEFAULT_TYPEFACE_INT = 0; public static final boolean DEFAULT_SUB_SHOWN = true; public static final boolean DEFAULT_SUB_SHADOW = true; public static final Typeface DEFAULT_TYPEFACE = Typeface.DEFAULT; public static Typeface getTypeface(int type) { switch (type) { case 0: return Typeface.DEFAULT; case 1: return Typeface.SANS_SERIF; case 2: return Typeface.SERIF; case 3: return Typeface.MONOSPACE; default: return DEFAULT_TYPEFACE; } } } ================================================ FILE: app/src/main/java/com/cjj/bb/view/VideoView.java ================================================ /* * Copyright (C) 2012 YIXIA.COM * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.cjj.bb.view; import android.app.Activity; import android.content.Context; import android.graphics.PixelFormat; import android.util.AttributeSet; import android.view.SurfaceHolder; import android.view.SurfaceView; import android.view.ViewGroup.LayoutParams; import com.cjj.bb.utils.DeviceUtils; public class VideoView extends SurfaceView { private Activity mActivity; private SurfaceHolder mSurfaceHolder; private int mSurfaceWidth, mSurfaceHeight; private int mVideoMode = VIDEO_LAYOUT_SCALE; public static final int VIDEO_LAYOUT_ORIGIN = 0; public static final int VIDEO_LAYOUT_SCALE = 1; public static final int VIDEO_LAYOUT_STRETCH = 2; public static final int VIDEO_LAYOUT_ZOOM = 3; public static final int VIDEO_LAYOUT_SCALE_ZOOM = 4; public int mVideoHeight; public VideoView(Context context, AttributeSet attrs) { super(context, attrs); getHolder().addCallback(mCallback); getHolder().setFormat(PixelFormat.RGBA_8888); } @SuppressWarnings("deprecation") public void initialize(Activity activity, SurfaceCallback l, boolean push) { mActivity = activity; mListener = l; if (mSurfaceHolder == null) mSurfaceHolder = getHolder(); // These methods is set to hw decoder or sw decoder, <= 2.3 if (push) getHolder().setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); else getHolder().setType(SurfaceHolder.SURFACE_TYPE_NORMAL); } private void setSurfaceLayout(float userRatio, int videoWidth, int videoHeight, float videoAspectRatio) { LayoutParams lp = getLayoutParams(); int windowWidth = DeviceUtils.getScreenWidth(mActivity); int windowHeight = DeviceUtils.getScreenHeight(mActivity); float windowRatio = windowWidth / (float) windowHeight; float videoRatio = userRatio <= 0.01f ? videoAspectRatio : userRatio; mSurfaceHeight = videoHeight; mSurfaceWidth = videoWidth; if (VIDEO_LAYOUT_ORIGIN == mVideoMode && mSurfaceWidth < windowWidth && mSurfaceHeight < windowHeight) { lp.width = (int) (mSurfaceHeight * videoRatio); lp.height = mSurfaceHeight; } else if (mVideoMode == VIDEO_LAYOUT_ZOOM) { lp.width = windowRatio > videoRatio ? windowWidth : (int) (videoRatio * windowHeight); lp.height = windowRatio < videoRatio ? windowHeight : (int) (windowWidth / videoRatio); } else if (mVideoMode == VIDEO_LAYOUT_SCALE_ZOOM && mVideoHeight > 0) { lp.width = (int) (mVideoHeight * videoRatio); lp.height = mVideoHeight; } else { boolean full = mVideoMode == VIDEO_LAYOUT_STRETCH; lp.width = (full || windowRatio < videoRatio) ? windowWidth : (int) (videoRatio * windowHeight); lp.height = (full || windowRatio > videoRatio) ? windowHeight : (int) (windowWidth / videoRatio); } mVideoHeight = lp.height; setLayoutParams(lp); getHolder().setFixedSize(mSurfaceWidth, mSurfaceHeight); //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); } public void setVideoLayout(int layout, float userRatio, int videoWidth, int videoHeight, float videoRatio) { mVideoMode = layout; setSurfaceLayout(userRatio, videoWidth, videoHeight, videoRatio); } private SurfaceHolder.Callback mCallback = new SurfaceHolder.Callback() { @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { holder.setKeepScreenOn(true); if (mListener != null) mListener.onSurfaceChanged(holder, format, width, height); } @Override public void surfaceCreated(SurfaceHolder holder) { mSurfaceHolder = holder; if (mListener != null) mListener.onSurfaceCreated(holder); } @Override public void surfaceDestroyed(SurfaceHolder holder) { if (mListener != null) mListener.onSurfaceDestroyed(holder); } }; private SurfaceCallback mListener; public interface SurfaceCallback { public void onSurfaceCreated(SurfaceHolder holder); public void onSurfaceChanged(SurfaceHolder holder, int format, int width, int height); public void onSurfaceDestroyed(SurfaceHolder holder); } } ================================================ FILE: app/src/main/java/viewpagerindicator/CirclePageIndicator.java ================================================ /* * Copyright (C) 2011 Patrik Akerfeldt * Copyright (C) 2011 Jake Wharton * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package viewpagerindicator; import android.content.Context; import android.content.res.Resources; import android.content.res.TypedArray; import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.Paint.Style; import android.graphics.drawable.Drawable; import android.os.Parcel; import android.os.Parcelable; import android.support.v4.view.MotionEventCompat; import android.support.v4.view.ViewConfigurationCompat; import android.support.v4.view.ViewPager; import android.util.AttributeSet; import android.view.MotionEvent; import android.view.View; import android.view.ViewConfiguration; import com.cjj.bb.R; import static android.graphics.Paint.ANTI_ALIAS_FLAG; import static android.widget.LinearLayout.HORIZONTAL; import static android.widget.LinearLayout.VERTICAL; /** * Draws circles (one for each view). The current view position is filled and * others are only stroked. */ public class CirclePageIndicator extends View implements PageIndicator { private static final int INVALID_POINTER = -1; private float mRadius; private final Paint mPaintPageFill = new Paint(ANTI_ALIAS_FLAG); private final Paint mPaintStroke = new Paint(ANTI_ALIAS_FLAG); private final Paint mPaintFill = new Paint(ANTI_ALIAS_FLAG); private ViewPager mViewPager; private ViewPager.OnPageChangeListener mListener; private int mCurrentPage; private int mSnapPage; private float mPageOffset; private int mScrollState; private int mOrientation; private boolean mCentered; private boolean mSnap; private int mTouchSlop; private float mLastMotionX = -1; private int mActivePointerId = INVALID_POINTER; private boolean mIsDragging; public CirclePageIndicator(Context context) { this(context, null); } public CirclePageIndicator(Context context, AttributeSet attrs) { this(context, attrs, R.attr.vpiCirclePageIndicatorStyle); } public CirclePageIndicator(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); if (isInEditMode()) return; //Load defaults from resources final Resources res = getResources(); final int defaultPageColor = res.getColor(R.color.default_circle_indicator_page_color); final int defaultFillColor = res.getColor(R.color.default_circle_indicator_fill_color); final int defaultOrientation = res.getInteger(R.integer.default_circle_indicator_orientation); final int defaultStrokeColor = res.getColor(R.color.default_circle_indicator_stroke_color); final float defaultStrokeWidth = res.getDimension(R.dimen.default_circle_indicator_stroke_width); final float defaultRadius = res.getDimension(R.dimen.default_circle_indicator_radius); final boolean defaultCentered = res.getBoolean(R.bool.default_circle_indicator_centered); final boolean defaultSnap = res.getBoolean(R.bool.default_circle_indicator_snap); //Retrieve styles attributes TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.CirclePageIndicator, defStyle, 0); mCentered = a.getBoolean(R.styleable.CirclePageIndicator_centered, defaultCentered); mOrientation = a.getInt(R.styleable.CirclePageIndicator_android_orientation, defaultOrientation); mPaintPageFill.setStyle(Style.FILL); mPaintPageFill.setColor(a.getColor(R.styleable.CirclePageIndicator_pageColor, defaultPageColor)); mPaintStroke.setStyle(Style.STROKE); mPaintStroke.setColor(a.getColor(R.styleable.CirclePageIndicator_strokeColor, defaultStrokeColor)); mPaintStroke.setStrokeWidth(a.getDimension(R.styleable.CirclePageIndicator_strokeWidth, defaultStrokeWidth)); mPaintFill.setStyle(Style.FILL); mPaintFill.setColor(a.getColor(R.styleable.CirclePageIndicator_fillColor, defaultFillColor)); mRadius = a.getDimension(R.styleable.CirclePageIndicator_radius, defaultRadius); mSnap = a.getBoolean(R.styleable.CirclePageIndicator_snap, defaultSnap); Drawable background = a.getDrawable(R.styleable.CirclePageIndicator_android_background); if (background != null) { setBackgroundDrawable(background); } a.recycle(); final ViewConfiguration configuration = ViewConfiguration.get(context); mTouchSlop = ViewConfigurationCompat.getScaledPagingTouchSlop(configuration); } public void setCentered(boolean centered) { mCentered = centered; invalidate(); } public boolean isCentered() { return mCentered; } public void setPageColor(int pageColor) { mPaintPageFill.setColor(pageColor); invalidate(); } public int getPageColor() { return mPaintPageFill.getColor(); } public void setFillColor(int fillColor) { mPaintFill.setColor(fillColor); invalidate(); } public int getFillColor() { return mPaintFill.getColor(); } public void setOrientation(int orientation) { switch (orientation) { case HORIZONTAL: case VERTICAL: mOrientation = orientation; requestLayout(); break; default: throw new IllegalArgumentException("Orientation must be either HORIZONTAL or VERTICAL."); } } public int getOrientation() { return mOrientation; } public void setStrokeColor(int strokeColor) { mPaintStroke.setColor(strokeColor); invalidate(); } public int getStrokeColor() { return mPaintStroke.getColor(); } public void setStrokeWidth(float strokeWidth) { mPaintStroke.setStrokeWidth(strokeWidth); invalidate(); } public float getStrokeWidth() { return mPaintStroke.getStrokeWidth(); } public void setRadius(float radius) { mRadius = radius; invalidate(); } public float getRadius() { return mRadius; } public void setSnap(boolean snap) { mSnap = snap; invalidate(); } public boolean isSnap() { return mSnap; } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); if (mViewPager == null) { return; } final int count = mViewPager.getAdapter().getCount(); if (count == 0) { return; } if (mCurrentPage >= count) { setCurrentItem(count - 1); return; } int longSize; int longPaddingBefore; int longPaddingAfter; int shortPaddingBefore; if (mOrientation == HORIZONTAL) { longSize = getWidth(); longPaddingBefore = getPaddingLeft(); longPaddingAfter = getPaddingRight(); shortPaddingBefore = getPaddingTop(); } else { longSize = getHeight(); longPaddingBefore = getPaddingTop(); longPaddingAfter = getPaddingBottom(); shortPaddingBefore = getPaddingLeft(); } final float threeRadius = mRadius * 3; final float shortOffset = shortPaddingBefore + mRadius; float longOffset = longPaddingBefore + mRadius; if (mCentered) { longOffset += ((longSize - longPaddingBefore - longPaddingAfter) / 2.0f) - ((count * threeRadius) / 2.0f); } float dX; float dY; float pageFillRadius = mRadius; if (mPaintStroke.getStrokeWidth() > 0) { pageFillRadius -= mPaintStroke.getStrokeWidth() / 2.0f; } //Draw stroked circles for (int iLoop = 0; iLoop < count; iLoop++) { float drawLong = longOffset + (iLoop * threeRadius); if (mOrientation == HORIZONTAL) { dX = drawLong; dY = shortOffset; } else { dX = shortOffset; dY = drawLong; } // Only paint fill if not completely transparent if (mPaintPageFill.getAlpha() > 0) { canvas.drawCircle(dX, dY, pageFillRadius, mPaintPageFill); } // Only paint stroke if a stroke width was non-zero if (pageFillRadius != mRadius) { canvas.drawCircle(dX, dY, mRadius, mPaintStroke); } } //Draw the filled circle according to the current scroll float cx = (mSnap ? mSnapPage : mCurrentPage) * threeRadius; if (!mSnap) { cx += mPageOffset * threeRadius; } if (mOrientation == HORIZONTAL) { dX = longOffset + cx; dY = shortOffset; } else { dX = shortOffset; dY = longOffset + cx; } canvas.drawCircle(dX, dY, mRadius, mPaintFill); } public boolean onTouchEvent(MotionEvent ev) { if (super.onTouchEvent(ev)) { return true; } if ((mViewPager == null) || (mViewPager.getAdapter().getCount() == 0)) { return false; } final int action = ev.getAction() & MotionEventCompat.ACTION_MASK; switch (action) { case MotionEvent.ACTION_DOWN: mActivePointerId = MotionEventCompat.getPointerId(ev, 0); mLastMotionX = ev.getX(); break; case MotionEvent.ACTION_MOVE: { final int activePointerIndex = MotionEventCompat.findPointerIndex(ev, mActivePointerId); final float x = MotionEventCompat.getX(ev, activePointerIndex); final float deltaX = x - mLastMotionX; if (!mIsDragging) { if (Math.abs(deltaX) > mTouchSlop) { mIsDragging = true; } } if (mIsDragging) { mLastMotionX = x; if (mViewPager.isFakeDragging() || mViewPager.beginFakeDrag()) { mViewPager.fakeDragBy(deltaX); } } break; } case MotionEvent.ACTION_CANCEL: case MotionEvent.ACTION_UP: if (!mIsDragging) { final int count = mViewPager.getAdapter().getCount(); final int width = getWidth(); final float halfWidth = width / 2f; final float sixthWidth = width / 6f; if ((mCurrentPage > 0) && (ev.getX() < halfWidth - sixthWidth)) { if (action != MotionEvent.ACTION_CANCEL) { mViewPager.setCurrentItem(mCurrentPage - 1); } return true; } else if ((mCurrentPage < count - 1) && (ev.getX() > halfWidth + sixthWidth)) { if (action != MotionEvent.ACTION_CANCEL) { mViewPager.setCurrentItem(mCurrentPage + 1); } return true; } } mIsDragging = false; mActivePointerId = INVALID_POINTER; if (mViewPager.isFakeDragging()) mViewPager.endFakeDrag(); break; case MotionEventCompat.ACTION_POINTER_DOWN: { final int index = MotionEventCompat.getActionIndex(ev); mLastMotionX = MotionEventCompat.getX(ev, index); mActivePointerId = MotionEventCompat.getPointerId(ev, index); break; } case MotionEventCompat.ACTION_POINTER_UP: final int pointerIndex = MotionEventCompat.getActionIndex(ev); final int pointerId = MotionEventCompat.getPointerId(ev, pointerIndex); if (pointerId == mActivePointerId) { final int newPointerIndex = pointerIndex == 0 ? 1 : 0; mActivePointerId = MotionEventCompat.getPointerId(ev, newPointerIndex); } mLastMotionX = MotionEventCompat.getX(ev, MotionEventCompat.findPointerIndex(ev, mActivePointerId)); break; } return true; } @Override public void setViewPager(ViewPager view) { if (mViewPager == view) { return; } if (mViewPager != null) { mViewPager.setOnPageChangeListener(null); } if (view.getAdapter() == null) { throw new IllegalStateException("ViewPager does not have adapter instance."); } mViewPager = view; mViewPager.setOnPageChangeListener(this); invalidate(); } @Override public void setViewPager(ViewPager view, int initialPosition) { setViewPager(view); setCurrentItem(initialPosition); } @Override public void setCurrentItem(int item) { if (mViewPager == null) { throw new IllegalStateException("ViewPager has not been bound."); } mViewPager.setCurrentItem(item); mCurrentPage = item; invalidate(); } @Override public void notifyDataSetChanged() { invalidate(); } @Override public void onPageScrollStateChanged(int state) { mScrollState = state; if (mListener != null) { mListener.onPageScrollStateChanged(state); } } @Override public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { mCurrentPage = position; mPageOffset = positionOffset; invalidate(); if (mListener != null) { mListener.onPageScrolled(position, positionOffset, positionOffsetPixels); } } @Override public void onPageSelected(int position) { if (mSnap || mScrollState == ViewPager.SCROLL_STATE_IDLE) { mCurrentPage = position; mSnapPage = position; invalidate(); } if (mListener != null) { mListener.onPageSelected(position); } } @Override public void setOnPageChangeListener(ViewPager.OnPageChangeListener listener) { mListener = listener; } /* * (non-Javadoc) * * @see android.view.View#onMeasure(int, int) */ @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { if (mOrientation == HORIZONTAL) { setMeasuredDimension(measureLong(widthMeasureSpec), measureShort(heightMeasureSpec)); } else { setMeasuredDimension(measureShort(widthMeasureSpec), measureLong(heightMeasureSpec)); } } /** * Determines the width of this view * * @param measureSpec * A measureSpec packed into an int * @return The width of the view, honoring constraints from measureSpec */ private int measureLong(int measureSpec) { int result; int specMode = MeasureSpec.getMode(measureSpec); int specSize = MeasureSpec.getSize(measureSpec); if ((specMode == MeasureSpec.EXACTLY) || (mViewPager == null)) { //We were told how big to be result = specSize; } else { //Calculate the width according the views count final int count = mViewPager.getAdapter().getCount(); result = (int)(getPaddingLeft() + getPaddingRight() + (count * 2 * mRadius) + (count - 1) * mRadius + 1); //Respect AT_MOST value if that was what is called for by measureSpec if (specMode == MeasureSpec.AT_MOST) { result = Math.min(result, specSize); } } return result; } /** * Determines the height of this view * * @param measureSpec * A measureSpec packed into an int * @return The height of the view, honoring constraints from measureSpec */ private int measureShort(int measureSpec) { int result; int specMode = MeasureSpec.getMode(measureSpec); int specSize = MeasureSpec.getSize(measureSpec); if (specMode == MeasureSpec.EXACTLY) { //We were told how big to be result = specSize; } else { //Measure the height result = (int)(2 * mRadius + getPaddingTop() + getPaddingBottom() + 1); //Respect AT_MOST value if that was what is called for by measureSpec if (specMode == MeasureSpec.AT_MOST) { result = Math.min(result, specSize); } } return result; } @Override public void onRestoreInstanceState(Parcelable state) { SavedState savedState = (SavedState)state; super.onRestoreInstanceState(savedState.getSuperState()); mCurrentPage = savedState.currentPage; mSnapPage = savedState.currentPage; requestLayout(); } @Override public Parcelable onSaveInstanceState() { Parcelable superState = super.onSaveInstanceState(); SavedState savedState = new SavedState(superState); savedState.currentPage = mCurrentPage; return savedState; } static class SavedState extends BaseSavedState { int currentPage; public SavedState(Parcelable superState) { super(superState); } private SavedState(Parcel in) { super(in); currentPage = in.readInt(); } @Override public void writeToParcel(Parcel dest, int flags) { super.writeToParcel(dest, flags); dest.writeInt(currentPage); } @SuppressWarnings("UnusedDeclaration") public static final Creator CREATOR = new Creator() { @Override public SavedState createFromParcel(Parcel in) { return new SavedState(in); } @Override public SavedState[] newArray(int size) { return new SavedState[size]; } }; } } ================================================ FILE: app/src/main/java/viewpagerindicator/IconPageIndicator.java ================================================ /* * Copyright (C) 2011 The Android Open Source Project * Copyright (C) 2012 Jake Wharton * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package viewpagerindicator; import android.content.Context; import android.support.v4.view.PagerAdapter; import android.support.v4.view.ViewPager; import android.support.v4.view.ViewPager.OnPageChangeListener; import android.util.AttributeSet; import android.view.Gravity; import android.view.View; import android.widget.HorizontalScrollView; import android.widget.ImageView; import com.cjj.bb.R; import static android.view.ViewGroup.LayoutParams.FILL_PARENT; import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT; /** * This widget implements the dynamic action bar tab behavior that can change * across different configurations or circumstances. */ public class IconPageIndicator extends HorizontalScrollView implements PageIndicator { private final IcsLinearLayout mIconsLayout; private ViewPager mViewPager; private OnPageChangeListener mListener; private Runnable mIconSelector; private int mSelectedIndex; public IconPageIndicator(Context context) { this(context, null); } public IconPageIndicator(Context context, AttributeSet attrs) { super(context, attrs); setHorizontalScrollBarEnabled(false); mIconsLayout = new IcsLinearLayout(context, R.attr.vpiIconPageIndicatorStyle); addView(mIconsLayout, new LayoutParams(WRAP_CONTENT, FILL_PARENT, Gravity.CENTER)); } private void animateToIcon(final int position) { final View iconView = mIconsLayout.getChildAt(position); if (mIconSelector != null) { removeCallbacks(mIconSelector); } mIconSelector = new Runnable() { public void run() { final int scrollPos = iconView.getLeft() - (getWidth() - iconView.getWidth()) / 2; smoothScrollTo(scrollPos, 0); mIconSelector = null; } }; post(mIconSelector); } @Override public void onAttachedToWindow() { super.onAttachedToWindow(); if (mIconSelector != null) { // Re-post the selector we saved post(mIconSelector); } } @Override public void onDetachedFromWindow() { super.onDetachedFromWindow(); if (mIconSelector != null) { removeCallbacks(mIconSelector); } } @Override public void onPageScrollStateChanged(int arg0) { if (mListener != null) { mListener.onPageScrollStateChanged(arg0); } } @Override public void onPageScrolled(int arg0, float arg1, int arg2) { if (mListener != null) { mListener.onPageScrolled(arg0, arg1, arg2); } } @Override public void onPageSelected(int arg0) { setCurrentItem(arg0); if (mListener != null) { mListener.onPageSelected(arg0); } } @Override public void setViewPager(ViewPager view) { if (mViewPager == view) { return; } if (mViewPager != null) { mViewPager.setOnPageChangeListener(null); } PagerAdapter adapter = view.getAdapter(); if (adapter == null) { throw new IllegalStateException("ViewPager does not have adapter instance."); } mViewPager = view; view.setOnPageChangeListener(this); notifyDataSetChanged(); } public void notifyDataSetChanged() { mIconsLayout.removeAllViews(); IconPagerAdapter iconAdapter = (IconPagerAdapter) mViewPager.getAdapter(); int count = iconAdapter.getCount(); for (int i = 0; i < count; i++) { ImageView view = new ImageView(getContext(), null, R.attr.vpiIconPageIndicatorStyle); view.setImageResource(iconAdapter.getIconResId(i)); mIconsLayout.addView(view); } if (mSelectedIndex > count) { mSelectedIndex = count - 1; } setCurrentItem(mSelectedIndex); requestLayout(); } @Override public void setViewPager(ViewPager view, int initialPosition) { setViewPager(view); setCurrentItem(initialPosition); } @Override public void setCurrentItem(int item) { if (mViewPager == null) { throw new IllegalStateException("ViewPager has not been bound."); } mSelectedIndex = item; mViewPager.setCurrentItem(item); int tabCount = mIconsLayout.getChildCount(); for (int i = 0; i < tabCount; i++) { View child = mIconsLayout.getChildAt(i); boolean isSelected = (i == item); child.setSelected(isSelected); if (isSelected) { animateToIcon(item); } } } @Override public void setOnPageChangeListener(OnPageChangeListener listener) { mListener = listener; } } ================================================ FILE: app/src/main/java/viewpagerindicator/IconPagerAdapter.java ================================================ package viewpagerindicator; public interface IconPagerAdapter { /** * Get icon representing the page at {@code index} in the adapter. */ int getIconResId(int index); // From PagerAdapter int getCount(); } ================================================ FILE: app/src/main/java/viewpagerindicator/IcsLinearLayout.java ================================================ package viewpagerindicator; import android.content.Context; import android.content.res.TypedArray; import android.graphics.Canvas; import android.graphics.drawable.Drawable; import android.view.View; import android.widget.LinearLayout; /** * A simple extension of a regular linear layout that supports the divider API * of Android 4.0+. The dividers are added adjacent to the children by changing * their layout params. If you need to rely on the margins which fall in the * same orientation as the layout you should wrap the child in a simple * {@link android.widget.FrameLayout} so it can receive the margin. */ class IcsLinearLayout extends LinearLayout { private static final int[] LL = new int[] { /* 0 */ android.R.attr.divider, /* 1 */ android.R.attr.showDividers, /* 2 */ android.R.attr.dividerPadding, }; private static final int LL_DIVIDER = 0; private static final int LL_SHOW_DIVIDER = 1; private static final int LL_DIVIDER_PADDING = 2; private Drawable mDivider; private int mDividerWidth; private int mDividerHeight; private int mShowDividers; private int mDividerPadding; public IcsLinearLayout(Context context, int themeAttr) { super(context); TypedArray a = context.obtainStyledAttributes(null, LL, themeAttr, 0); setDividerDrawable(a.getDrawable(IcsLinearLayout.LL_DIVIDER)); mDividerPadding = a.getDimensionPixelSize(LL_DIVIDER_PADDING, 0); mShowDividers = a.getInteger(LL_SHOW_DIVIDER, SHOW_DIVIDER_NONE); a.recycle(); } public void setDividerDrawable(Drawable divider) { if (divider == mDivider) { return; } mDivider = divider; if (divider != null) { mDividerWidth = divider.getIntrinsicWidth(); mDividerHeight = divider.getIntrinsicHeight(); } else { mDividerWidth = 0; mDividerHeight = 0; } setWillNotDraw(divider == null); requestLayout(); } @Override protected void measureChildWithMargins(View child, int parentWidthMeasureSpec, int widthUsed, int parentHeightMeasureSpec, int heightUsed) { final int index = indexOfChild(child); final int orientation = getOrientation(); final LayoutParams params = (LayoutParams) child.getLayoutParams(); if (hasDividerBeforeChildAt(index)) { if (orientation == VERTICAL) { //Account for the divider by pushing everything up params.topMargin = mDividerHeight; } else { //Account for the divider by pushing everything left params.leftMargin = mDividerWidth; } } final int count = getChildCount(); if (index == count - 1) { if (hasDividerBeforeChildAt(count)) { if (orientation == VERTICAL) { params.bottomMargin = mDividerHeight; } else { params.rightMargin = mDividerWidth; } } } super.measureChildWithMargins(child, parentWidthMeasureSpec, widthUsed, parentHeightMeasureSpec, heightUsed); } @Override protected void onDraw(Canvas canvas) { if (mDivider != null) { if (getOrientation() == VERTICAL) { drawDividersVertical(canvas); } else { drawDividersHorizontal(canvas); } } super.onDraw(canvas); } private void drawDividersVertical(Canvas canvas) { final int count = getChildCount(); for (int i = 0; i < count; i++) { final View child = getChildAt(i); if (child != null && child.getVisibility() != GONE) { if (hasDividerBeforeChildAt(i)) { final LayoutParams lp = (LayoutParams) child.getLayoutParams(); final int top = child.getTop() - lp.topMargin/* - mDividerHeight*/; drawHorizontalDivider(canvas, top); } } } if (hasDividerBeforeChildAt(count)) { final View child = getChildAt(count - 1); int bottom = 0; if (child == null) { bottom = getHeight() - getPaddingBottom() - mDividerHeight; } else { //final LayoutParams lp = (LayoutParams) child.getLayoutParams(); bottom = child.getBottom()/* + lp.bottomMargin*/; } drawHorizontalDivider(canvas, bottom); } } private void drawDividersHorizontal(Canvas canvas) { final int count = getChildCount(); for (int i = 0; i < count; i++) { final View child = getChildAt(i); if (child != null && child.getVisibility() != GONE) { if (hasDividerBeforeChildAt(i)) { final LayoutParams lp = (LayoutParams) child.getLayoutParams(); final int left = child.getLeft() - lp.leftMargin/* - mDividerWidth*/; drawVerticalDivider(canvas, left); } } } if (hasDividerBeforeChildAt(count)) { final View child = getChildAt(count - 1); int right = 0; if (child == null) { right = getWidth() - getPaddingRight() - mDividerWidth; } else { //final LayoutParams lp = (LayoutParams) child.getLayoutParams(); right = child.getRight()/* + lp.rightMargin*/; } drawVerticalDivider(canvas, right); } } private void drawHorizontalDivider(Canvas canvas, int top) { mDivider.setBounds(getPaddingLeft() + mDividerPadding, top, getWidth() - getPaddingRight() - mDividerPadding, top + mDividerHeight); mDivider.draw(canvas); } private void drawVerticalDivider(Canvas canvas, int left) { mDivider.setBounds(left, getPaddingTop() + mDividerPadding, left + mDividerWidth, getHeight() - getPaddingBottom() - mDividerPadding); mDivider.draw(canvas); } private boolean hasDividerBeforeChildAt(int childIndex) { if (childIndex == 0 || childIndex == getChildCount()) { return false; } if ((mShowDividers & SHOW_DIVIDER_MIDDLE) != 0) { boolean hasVisibleViewBefore = false; for (int i = childIndex - 1; i >= 0; i--) { if (getChildAt(i).getVisibility() != GONE) { hasVisibleViewBefore = true; break; } } return hasVisibleViewBefore; } return false; } } ================================================ FILE: app/src/main/java/viewpagerindicator/LinePageIndicator.java ================================================ /* * Copyright (C) 2012 Jake Wharton * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package viewpagerindicator; import android.content.Context; import android.content.res.Resources; import android.content.res.TypedArray; import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.drawable.Drawable; import android.os.Parcel; import android.os.Parcelable; import android.support.v4.view.MotionEventCompat; import android.support.v4.view.ViewConfigurationCompat; import android.support.v4.view.ViewPager; import android.util.AttributeSet; import android.util.FloatMath; import android.view.MotionEvent; import android.view.View; import android.view.ViewConfiguration; import com.cjj.bb.R; /** * Draws a line for each page. The current page line is colored differently * than the unselected page lines. */ public class LinePageIndicator extends View implements PageIndicator { private static final int INVALID_POINTER = -1; private final Paint mPaintUnselected = new Paint(Paint.ANTI_ALIAS_FLAG); private final Paint mPaintSelected = new Paint(Paint.ANTI_ALIAS_FLAG); private ViewPager mViewPager; private ViewPager.OnPageChangeListener mListener; private int mCurrentPage; private boolean mCentered; private float mLineWidth; private float mGapWidth; private int mTouchSlop; private float mLastMotionX = -1; private int mActivePointerId = INVALID_POINTER; private boolean mIsDragging; public LinePageIndicator(Context context) { this(context, null); } public LinePageIndicator(Context context, AttributeSet attrs) { this(context, attrs, R.attr.vpiLinePageIndicatorStyle); } public LinePageIndicator(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); if (isInEditMode()) return; final Resources res = getResources(); //Load defaults from resources final int defaultSelectedColor = res.getColor(R.color.default_line_indicator_selected_color); final int defaultUnselectedColor = res.getColor(R.color.default_line_indicator_unselected_color); final float defaultLineWidth = res.getDimension(R.dimen.default_line_indicator_line_width); final float defaultGapWidth = res.getDimension(R.dimen.default_line_indicator_gap_width); final float defaultStrokeWidth = res.getDimension(R.dimen.default_line_indicator_stroke_width); final boolean defaultCentered = res.getBoolean(R.bool.default_line_indicator_centered); //Retrieve styles attributes TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.LinePageIndicator, defStyle, 0); mCentered = a.getBoolean(R.styleable.LinePageIndicator_centered, defaultCentered); mLineWidth = a.getDimension(R.styleable.LinePageIndicator_lineWidth, defaultLineWidth); mGapWidth = a.getDimension(R.styleable.LinePageIndicator_gapWidth, defaultGapWidth); setStrokeWidth(a.getDimension(R.styleable.LinePageIndicator_strokeWidth, defaultStrokeWidth)); mPaintUnselected.setColor(a.getColor(R.styleable.LinePageIndicator_unselectedColor, defaultUnselectedColor)); mPaintSelected.setColor(a.getColor(R.styleable.LinePageIndicator_selectedColor, defaultSelectedColor)); Drawable background = a.getDrawable(R.styleable.LinePageIndicator_android_background); if (background != null) { setBackgroundDrawable(background); } a.recycle(); final ViewConfiguration configuration = ViewConfiguration.get(context); mTouchSlop = ViewConfigurationCompat.getScaledPagingTouchSlop(configuration); } public void setCentered(boolean centered) { mCentered = centered; invalidate(); } public boolean isCentered() { return mCentered; } public void setUnselectedColor(int unselectedColor) { mPaintUnselected.setColor(unselectedColor); invalidate(); } public int getUnselectedColor() { return mPaintUnselected.getColor(); } public void setSelectedColor(int selectedColor) { mPaintSelected.setColor(selectedColor); invalidate(); } public int getSelectedColor() { return mPaintSelected.getColor(); } public void setLineWidth(float lineWidth) { mLineWidth = lineWidth; invalidate(); } public float getLineWidth() { return mLineWidth; } public void setStrokeWidth(float lineHeight) { mPaintSelected.setStrokeWidth(lineHeight); mPaintUnselected.setStrokeWidth(lineHeight); invalidate(); } public float getStrokeWidth() { return mPaintSelected.getStrokeWidth(); } public void setGapWidth(float gapWidth) { mGapWidth = gapWidth; invalidate(); } public float getGapWidth() { return mGapWidth; } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); if (mViewPager == null) { return; } final int count = mViewPager.getAdapter().getCount(); if (count == 0) { return; } if (mCurrentPage >= count) { setCurrentItem(count - 1); return; } final float lineWidthAndGap = mLineWidth + mGapWidth; final float indicatorWidth = (count * lineWidthAndGap) - mGapWidth; final float paddingTop = getPaddingTop(); final float paddingLeft = getPaddingLeft(); final float paddingRight = getPaddingRight(); float verticalOffset = paddingTop + ((getHeight() - paddingTop - getPaddingBottom()) / 2.0f); float horizontalOffset = paddingLeft; if (mCentered) { horizontalOffset += ((getWidth() - paddingLeft - paddingRight) / 2.0f) - (indicatorWidth / 2.0f); } //Draw stroked circles for (int i = 0; i < count; i++) { float dx1 = horizontalOffset + (i * lineWidthAndGap); float dx2 = dx1 + mLineWidth; canvas.drawLine(dx1, verticalOffset, dx2, verticalOffset, (i == mCurrentPage) ? mPaintSelected : mPaintUnselected); } } public boolean onTouchEvent(MotionEvent ev) { if (super.onTouchEvent(ev)) { return true; } if ((mViewPager == null) || (mViewPager.getAdapter().getCount() == 0)) { return false; } final int action = ev.getAction() & MotionEventCompat.ACTION_MASK; switch (action) { case MotionEvent.ACTION_DOWN: mActivePointerId = MotionEventCompat.getPointerId(ev, 0); mLastMotionX = ev.getX(); break; case MotionEvent.ACTION_MOVE: { final int activePointerIndex = MotionEventCompat.findPointerIndex(ev, mActivePointerId); final float x = MotionEventCompat.getX(ev, activePointerIndex); final float deltaX = x - mLastMotionX; if (!mIsDragging) { if (Math.abs(deltaX) > mTouchSlop) { mIsDragging = true; } } if (mIsDragging) { mLastMotionX = x; if (mViewPager.isFakeDragging() || mViewPager.beginFakeDrag()) { mViewPager.fakeDragBy(deltaX); } } break; } case MotionEvent.ACTION_CANCEL: case MotionEvent.ACTION_UP: if (!mIsDragging) { final int count = mViewPager.getAdapter().getCount(); final int width = getWidth(); final float halfWidth = width / 2f; final float sixthWidth = width / 6f; if ((mCurrentPage > 0) && (ev.getX() < halfWidth - sixthWidth)) { if (action != MotionEvent.ACTION_CANCEL) { mViewPager.setCurrentItem(mCurrentPage - 1); } return true; } else if ((mCurrentPage < count - 1) && (ev.getX() > halfWidth + sixthWidth)) { if (action != MotionEvent.ACTION_CANCEL) { mViewPager.setCurrentItem(mCurrentPage + 1); } return true; } } mIsDragging = false; mActivePointerId = INVALID_POINTER; if (mViewPager.isFakeDragging()) mViewPager.endFakeDrag(); break; case MotionEventCompat.ACTION_POINTER_DOWN: { final int index = MotionEventCompat.getActionIndex(ev); mLastMotionX = MotionEventCompat.getX(ev, index); mActivePointerId = MotionEventCompat.getPointerId(ev, index); break; } case MotionEventCompat.ACTION_POINTER_UP: final int pointerIndex = MotionEventCompat.getActionIndex(ev); final int pointerId = MotionEventCompat.getPointerId(ev, pointerIndex); if (pointerId == mActivePointerId) { final int newPointerIndex = pointerIndex == 0 ? 1 : 0; mActivePointerId = MotionEventCompat.getPointerId(ev, newPointerIndex); } mLastMotionX = MotionEventCompat.getX(ev, MotionEventCompat.findPointerIndex(ev, mActivePointerId)); break; } return true; } @Override public void setViewPager(ViewPager viewPager) { if (mViewPager == viewPager) { return; } if (mViewPager != null) { //Clear us from the old pager. mViewPager.setOnPageChangeListener(null); } if (viewPager.getAdapter() == null) { throw new IllegalStateException("ViewPager does not have adapter instance."); } mViewPager = viewPager; mViewPager.setOnPageChangeListener(this); invalidate(); } @Override public void setViewPager(ViewPager view, int initialPosition) { setViewPager(view); setCurrentItem(initialPosition); } @Override public void setCurrentItem(int item) { if (mViewPager == null) { throw new IllegalStateException("ViewPager has not been bound."); } mViewPager.setCurrentItem(item); mCurrentPage = item; invalidate(); } @Override public void notifyDataSetChanged() { invalidate(); } @Override public void onPageScrollStateChanged(int state) { if (mListener != null) { mListener.onPageScrollStateChanged(state); } } @Override public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { if (mListener != null) { mListener.onPageScrolled(position, positionOffset, positionOffsetPixels); } } @Override public void onPageSelected(int position) { mCurrentPage = position; invalidate(); if (mListener != null) { mListener.onPageSelected(position); } } @Override public void setOnPageChangeListener(ViewPager.OnPageChangeListener listener) { mListener = listener; } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { setMeasuredDimension(measureWidth(widthMeasureSpec), measureHeight(heightMeasureSpec)); } /** * Determines the width of this view * * @param measureSpec * A measureSpec packed into an int * @return The width of the view, honoring constraints from measureSpec */ private int measureWidth(int measureSpec) { float result; int specMode = MeasureSpec.getMode(measureSpec); int specSize = MeasureSpec.getSize(measureSpec); if ((specMode == MeasureSpec.EXACTLY) || (mViewPager == null)) { //We were told how big to be result = specSize; } else { //Calculate the width according the views count final int count = mViewPager.getAdapter().getCount(); result = getPaddingLeft() + getPaddingRight() + (count * mLineWidth) + ((count - 1) * mGapWidth); //Respect AT_MOST value if that was what is called for by measureSpec if (specMode == MeasureSpec.AT_MOST) { result = Math.min(result, specSize); } } return (int)FloatMath.ceil(result); } /** * Determines the height of this view * * @param measureSpec * A measureSpec packed into an int * @return The height of the view, honoring constraints from measureSpec */ private int measureHeight(int measureSpec) { float result; int specMode = MeasureSpec.getMode(measureSpec); int specSize = MeasureSpec.getSize(measureSpec); if (specMode == MeasureSpec.EXACTLY) { //We were told how big to be result = specSize; } else { //Measure the height result = mPaintSelected.getStrokeWidth() + getPaddingTop() + getPaddingBottom(); //Respect AT_MOST value if that was what is called for by measureSpec if (specMode == MeasureSpec.AT_MOST) { result = Math.min(result, specSize); } } return (int)FloatMath.ceil(result); } @Override public void onRestoreInstanceState(Parcelable state) { SavedState savedState = (SavedState)state; super.onRestoreInstanceState(savedState.getSuperState()); mCurrentPage = savedState.currentPage; requestLayout(); } @Override public Parcelable onSaveInstanceState() { Parcelable superState = super.onSaveInstanceState(); SavedState savedState = new SavedState(superState); savedState.currentPage = mCurrentPage; return savedState; } static class SavedState extends BaseSavedState { int currentPage; public SavedState(Parcelable superState) { super(superState); } private SavedState(Parcel in) { super(in); currentPage = in.readInt(); } @Override public void writeToParcel(Parcel dest, int flags) { super.writeToParcel(dest, flags); dest.writeInt(currentPage); } @SuppressWarnings("UnusedDeclaration") public static final Creator CREATOR = new Creator() { @Override public SavedState createFromParcel(Parcel in) { return new SavedState(in); } @Override public SavedState[] newArray(int size) { return new SavedState[size]; } }; } } ================================================ FILE: app/src/main/java/viewpagerindicator/PageIndicator.java ================================================ /* * Copyright (C) 2011 Patrik Akerfeldt * Copyright (C) 2011 Jake Wharton * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package viewpagerindicator; import android.support.v4.view.ViewPager; /** * A PageIndicator is responsible to show an visual indicator on the total views * number and the current visible view. */ public interface PageIndicator extends ViewPager.OnPageChangeListener { /** * Bind the indicator to a ViewPager. * * @param view */ void setViewPager(ViewPager view); /** * Bind the indicator to a ViewPager. * * @param view * @param initialPosition */ void setViewPager(ViewPager view, int initialPosition); /** *

Set the current page of both the ViewPager and indicator.

* *

This must be used if you need to set the page before * the views are drawn on screen (e.g., default start page).

* * @param item */ void setCurrentItem(int item); /** * Set a page change listener which will receive forwarded events. * * @param listener */ void setOnPageChangeListener(ViewPager.OnPageChangeListener listener); /** * Notify the indicator that the fragment list has changed. */ void notifyDataSetChanged(); } ================================================ FILE: app/src/main/java/viewpagerindicator/TabPageIndicator.java ================================================ /* * Copyright (C) 2011 The Android Open Source Project * Copyright (C) 2011 Jake Wharton * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package viewpagerindicator; import android.content.Context; import android.support.v4.view.PagerAdapter; import android.support.v4.view.ViewPager; import android.support.v4.view.ViewPager.OnPageChangeListener; import android.util.AttributeSet; import android.view.View; import android.view.ViewGroup; import android.widget.HorizontalScrollView; import android.widget.LinearLayout; import android.widget.TextView; import com.cjj.bb.R; import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT; /** * This widget implements the dynamic action bar tab behavior that can change * across different configurations or circumstances. */ public class TabPageIndicator extends HorizontalScrollView implements PageIndicator { /** Title text used when no title is provided by the adapter. */ private static final CharSequence EMPTY_TITLE = ""; /** * Interface for a callback when the selected tab has been reselected. */ public interface OnTabReselectedListener { /** * Callback when the selected tab has been reselected. * * @param position Position of the current center item. */ void onTabReselected(int position); } private Runnable mTabSelector; private final OnClickListener mTabClickListener = new OnClickListener() { public void onClick(View view) { TabView tabView = (TabView)view; final int oldSelected = mViewPager.getCurrentItem(); final int newSelected = tabView.getIndex(); mViewPager.setCurrentItem(newSelected); if (oldSelected == newSelected && mTabReselectedListener != null) { mTabReselectedListener.onTabReselected(newSelected); } } }; private final IcsLinearLayout mTabLayout; private ViewPager mViewPager; private ViewPager.OnPageChangeListener mListener; private int mMaxTabWidth; private int mSelectedTabIndex; private OnTabReselectedListener mTabReselectedListener; public TabPageIndicator(Context context) { this(context, null); } public TabPageIndicator(Context context, AttributeSet attrs) { super(context, attrs); setHorizontalScrollBarEnabled(false); mTabLayout = new IcsLinearLayout(context, R.attr.vpiTabPageIndicatorStyle); addView(mTabLayout, new ViewGroup.LayoutParams(WRAP_CONTENT, MATCH_PARENT)); } public void setOnTabReselectedListener(OnTabReselectedListener listener) { mTabReselectedListener = listener; } @Override public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { final int widthMode = MeasureSpec.getMode(widthMeasureSpec); final boolean lockedExpanded = widthMode == MeasureSpec.EXACTLY; setFillViewport(lockedExpanded); final int childCount = mTabLayout.getChildCount(); if (childCount > 1 && (widthMode == MeasureSpec.EXACTLY || widthMode == MeasureSpec.AT_MOST)) { if (childCount > 2) { mMaxTabWidth = (int)(MeasureSpec.getSize(widthMeasureSpec) * 0.4f); } else { mMaxTabWidth = MeasureSpec.getSize(widthMeasureSpec) / 2; } } else { mMaxTabWidth = -1; } final int oldWidth = getMeasuredWidth(); super.onMeasure(widthMeasureSpec, heightMeasureSpec); final int newWidth = getMeasuredWidth(); if (lockedExpanded && oldWidth != newWidth) { // Recenter the tab display if we're at a new (scrollable) size. setCurrentItem(mSelectedTabIndex); } } private void animateToTab(final int position) { final View tabView = mTabLayout.getChildAt(position); if (mTabSelector != null) { removeCallbacks(mTabSelector); } mTabSelector = new Runnable() { public void run() { final int scrollPos = tabView.getLeft() - (getWidth() - tabView.getWidth()) / 2; smoothScrollTo(scrollPos, 0); mTabSelector = null; } }; post(mTabSelector); } @Override public void onAttachedToWindow() { super.onAttachedToWindow(); if (mTabSelector != null) { // Re-post the selector we saved post(mTabSelector); } } @Override public void onDetachedFromWindow() { super.onDetachedFromWindow(); if (mTabSelector != null) { removeCallbacks(mTabSelector); } } private void addTab(int index, CharSequence text, int iconResId) { final TabView tabView = new TabView(getContext()); tabView.mIndex = index; tabView.setFocusable(true); tabView.setOnClickListener(mTabClickListener); tabView.setText(text); if (iconResId != 0) { tabView.setCompoundDrawablesWithIntrinsicBounds(iconResId, 0, 0, 0); } mTabLayout.addView(tabView, new LinearLayout.LayoutParams(0, MATCH_PARENT, 1)); } @Override public void onPageScrollStateChanged(int arg0) { if (mListener != null) { mListener.onPageScrollStateChanged(arg0); } } @Override public void onPageScrolled(int arg0, float arg1, int arg2) { if (mListener != null) { mListener.onPageScrolled(arg0, arg1, arg2); } } @Override public void onPageSelected(int arg0) { setCurrentItem(arg0); if (mListener != null) { mListener.onPageSelected(arg0); } } @Override public void setViewPager(ViewPager view) { if (mViewPager == view) { return; } if (mViewPager != null) { mViewPager.setOnPageChangeListener(null); } final PagerAdapter adapter = view.getAdapter(); if (adapter == null) { throw new IllegalStateException("ViewPager does not have adapter instance."); } mViewPager = view; view.setOnPageChangeListener(this); notifyDataSetChanged(); } public void notifyDataSetChanged() { mTabLayout.removeAllViews(); PagerAdapter adapter = mViewPager.getAdapter(); IconPagerAdapter iconAdapter = null; if (adapter instanceof IconPagerAdapter) { iconAdapter = (IconPagerAdapter)adapter; } final int count = adapter.getCount(); for (int i = 0; i < count; i++) { CharSequence title = adapter.getPageTitle(i); if (title == null) { title = EMPTY_TITLE; } int iconResId = 0; if (iconAdapter != null) { iconResId = iconAdapter.getIconResId(i); } addTab(i, title, iconResId); } if (mSelectedTabIndex > count) { mSelectedTabIndex = count - 1; } setCurrentItem(mSelectedTabIndex); requestLayout(); } @Override public void setViewPager(ViewPager view, int initialPosition) { setViewPager(view); setCurrentItem(initialPosition); } @Override public void setCurrentItem(int item) { if (mViewPager == null) { throw new IllegalStateException("ViewPager has not been bound."); } mSelectedTabIndex = item; mViewPager.setCurrentItem(item); final int tabCount = mTabLayout.getChildCount(); for (int i = 0; i < tabCount; i++) { final View child = mTabLayout.getChildAt(i); final boolean isSelected = (i == item); child.setSelected(isSelected); if (isSelected) { animateToTab(item); } } } @Override public void setOnPageChangeListener(OnPageChangeListener listener) { mListener = listener; } private class TabView extends TextView { private int mIndex; public TabView(Context context) { super(context, null, R.attr.vpiTabPageIndicatorStyle); } @Override public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); // Re-measure if we went beyond our maximum size. if (mMaxTabWidth > 0 && getMeasuredWidth() > mMaxTabWidth) { super.onMeasure(MeasureSpec.makeMeasureSpec(mMaxTabWidth, MeasureSpec.EXACTLY), heightMeasureSpec); } } public int getIndex() { return mIndex; } } } ================================================ FILE: app/src/main/java/viewpagerindicator/TitlePageIndicator.java ================================================ /* * Copyright (C) 2011 Jake Wharton * Copyright (C) 2011 Patrik Akerfeldt * Copyright (C) 2011 Francisco Figueiredo Jr. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package viewpagerindicator; import android.content.Context; import android.content.res.Resources; import android.content.res.TypedArray; import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.Path; import android.graphics.Rect; import android.graphics.Typeface; import android.graphics.drawable.Drawable; import android.os.Parcel; import android.os.Parcelable; import android.support.v4.view.MotionEventCompat; import android.support.v4.view.ViewConfigurationCompat; import android.support.v4.view.ViewPager; import android.util.AttributeSet; import android.view.MotionEvent; import android.view.View; import android.view.ViewConfiguration; import com.cjj.bb.R; import java.util.ArrayList; /** * A TitlePageIndicator is a PageIndicator which displays the title of left view * (if exist), the title of the current select view (centered) and the title of * the right view (if exist). When the user scrolls the ViewPager then titles are * also scrolled. */ public class TitlePageIndicator extends View implements PageIndicator { /** * Percentage indicating what percentage of the screen width away from * center should the underline be fully faded. A value of 0.25 means that * halfway between the center of the screen and an edge. */ private static final float SELECTION_FADE_PERCENTAGE = 0.25f; /** * Percentage indicating what percentage of the screen width away from * center should the selected text bold turn off. A value of 0.05 means * that 10% between the center and an edge. */ private static final float BOLD_FADE_PERCENTAGE = 0.05f; /** * Title text used when no title is provided by the adapter. */ private static final String EMPTY_TITLE = ""; /** * Interface for a callback when the center item has been clicked. */ public interface OnCenterItemClickListener { /** * Callback when the center item has been clicked. * * @param position Position of the current center item. */ void onCenterItemClick(int position); } public enum IndicatorStyle { None(0), Triangle(1), Underline(2); public final int value; private IndicatorStyle(int value) { this.value = value; } public static IndicatorStyle fromValue(int value) { for (IndicatorStyle style : IndicatorStyle.values()) { if (style.value == value) { return style; } } return null; } } public enum LinePosition { Bottom(0), Top(1); public final int value; private LinePosition(int value) { this.value = value; } public static LinePosition fromValue(int value) { for (LinePosition position : LinePosition.values()) { if (position.value == value) { return position; } } return null; } } private ViewPager mViewPager; private ViewPager.OnPageChangeListener mListener; private int mCurrentPage = -1; private float mPageOffset; private int mScrollState; private final Paint mPaintText = new Paint(); private boolean mBoldText; private int mColorText; private int mColorSelected; private Path mPath = new Path(); private final Rect mBounds = new Rect(); private final Paint mPaintFooterLine = new Paint(); private IndicatorStyle mFooterIndicatorStyle; private LinePosition mLinePosition; private final Paint mPaintFooterIndicator = new Paint(); private float mFooterIndicatorHeight; private float mFooterIndicatorUnderlinePadding; private float mFooterPadding; private float mTitlePadding; private float mTopPadding; /** Left and right side padding for not active view titles. */ private float mClipPadding; private float mFooterLineHeight; private static final int INVALID_POINTER = -1; private int mTouchSlop; private float mLastMotionX = -1; private int mActivePointerId = INVALID_POINTER; private boolean mIsDragging; private OnCenterItemClickListener mCenterItemClickListener; public TitlePageIndicator(Context context) { this(context, null); } public TitlePageIndicator(Context context, AttributeSet attrs) { this(context, attrs, R.attr.vpiTitlePageIndicatorStyle); } public TitlePageIndicator(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); if (isInEditMode()) return; //Load defaults from resources final Resources res = getResources(); final int defaultFooterColor = res.getColor(R.color.default_title_indicator_footer_color); final float defaultFooterLineHeight = res.getDimension(R.dimen.default_title_indicator_footer_line_height); final int defaultFooterIndicatorStyle = res.getInteger(R.integer.default_title_indicator_footer_indicator_style); final float defaultFooterIndicatorHeight = res.getDimension(R.dimen.default_title_indicator_footer_indicator_height); final float defaultFooterIndicatorUnderlinePadding = res.getDimension(R.dimen.default_title_indicator_footer_indicator_underline_padding); final float defaultFooterPadding = res.getDimension(R.dimen.default_title_indicator_footer_padding); final int defaultLinePosition = res.getInteger(R.integer.default_title_indicator_line_position); final int defaultSelectedColor = res.getColor(R.color.default_title_indicator_selected_color); final boolean defaultSelectedBold = res.getBoolean(R.bool.default_title_indicator_selected_bold); final int defaultTextColor = res.getColor(R.color.default_title_indicator_text_color); final float defaultTextSize = res.getDimension(R.dimen.default_title_indicator_text_size); final float defaultTitlePadding = res.getDimension(R.dimen.default_title_indicator_title_padding); final float defaultClipPadding = res.getDimension(R.dimen.default_title_indicator_clip_padding); final float defaultTopPadding = res.getDimension(R.dimen.default_title_indicator_top_padding); //Retrieve styles attributes TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.TitlePageIndicator, defStyle, 0); //Retrieve the colors to be used for this view and apply them. mFooterLineHeight = a.getDimension(R.styleable.TitlePageIndicator_footerLineHeight, defaultFooterLineHeight); mFooterIndicatorStyle = IndicatorStyle.fromValue(a.getInteger(R.styleable.TitlePageIndicator_footerIndicatorStyle, defaultFooterIndicatorStyle)); mFooterIndicatorHeight = a.getDimension(R.styleable.TitlePageIndicator_footerIndicatorHeight, defaultFooterIndicatorHeight); mFooterIndicatorUnderlinePadding = a.getDimension(R.styleable.TitlePageIndicator_footerIndicatorUnderlinePadding, defaultFooterIndicatorUnderlinePadding); mFooterPadding = a.getDimension(R.styleable.TitlePageIndicator_footerPadding, defaultFooterPadding); mLinePosition = LinePosition.fromValue(a.getInteger(R.styleable.TitlePageIndicator_linePosition, defaultLinePosition)); mTopPadding = a.getDimension(R.styleable.TitlePageIndicator_topPadding, defaultTopPadding); mTitlePadding = a.getDimension(R.styleable.TitlePageIndicator_titlePadding, defaultTitlePadding); mClipPadding = a.getDimension(R.styleable.TitlePageIndicator_clipPadding, defaultClipPadding); mColorSelected = a.getColor(R.styleable.TitlePageIndicator_selectedColor, defaultSelectedColor); mColorText = a.getColor(R.styleable.TitlePageIndicator_android_textColor, defaultTextColor); mBoldText = a.getBoolean(R.styleable.TitlePageIndicator_selectedBold, defaultSelectedBold); final float textSize = a.getDimension(R.styleable.TitlePageIndicator_android_textSize, defaultTextSize); final int footerColor = a.getColor(R.styleable.TitlePageIndicator_footerColor, defaultFooterColor); mPaintText.setTextSize(textSize); mPaintText.setAntiAlias(true); mPaintFooterLine.setStyle(Paint.Style.FILL_AND_STROKE); mPaintFooterLine.setStrokeWidth(mFooterLineHeight); mPaintFooterLine.setColor(footerColor); mPaintFooterIndicator.setStyle(Paint.Style.FILL_AND_STROKE); mPaintFooterIndicator.setColor(footerColor); Drawable background = a.getDrawable(R.styleable.TitlePageIndicator_android_background); if (background != null) { setBackgroundDrawable(background); } a.recycle(); final ViewConfiguration configuration = ViewConfiguration.get(context); mTouchSlop = ViewConfigurationCompat.getScaledPagingTouchSlop(configuration); } public int getFooterColor() { return mPaintFooterLine.getColor(); } public void setFooterColor(int footerColor) { mPaintFooterLine.setColor(footerColor); mPaintFooterIndicator.setColor(footerColor); invalidate(); } public float getFooterLineHeight() { return mFooterLineHeight; } public void setFooterLineHeight(float footerLineHeight) { mFooterLineHeight = footerLineHeight; mPaintFooterLine.setStrokeWidth(mFooterLineHeight); invalidate(); } public float getFooterIndicatorHeight() { return mFooterIndicatorHeight; } public void setFooterIndicatorHeight(float footerTriangleHeight) { mFooterIndicatorHeight = footerTriangleHeight; invalidate(); } public float getFooterIndicatorPadding() { return mFooterPadding; } public void setFooterIndicatorPadding(float footerIndicatorPadding) { mFooterPadding = footerIndicatorPadding; invalidate(); } public IndicatorStyle getFooterIndicatorStyle() { return mFooterIndicatorStyle; } public void setFooterIndicatorStyle(IndicatorStyle indicatorStyle) { mFooterIndicatorStyle = indicatorStyle; invalidate(); } public LinePosition getLinePosition() { return mLinePosition; } public void setLinePosition(LinePosition linePosition) { mLinePosition = linePosition; invalidate(); } public int getSelectedColor() { return mColorSelected; } public void setSelectedColor(int selectedColor) { mColorSelected = selectedColor; invalidate(); } public boolean isSelectedBold() { return mBoldText; } public void setSelectedBold(boolean selectedBold) { mBoldText = selectedBold; invalidate(); } public int getTextColor() { return mColorText; } public void setTextColor(int textColor) { mPaintText.setColor(textColor); mColorText = textColor; invalidate(); } public float getTextSize() { return mPaintText.getTextSize(); } public void setTextSize(float textSize) { mPaintText.setTextSize(textSize); invalidate(); } public float getTitlePadding() { return this.mTitlePadding; } public void setTitlePadding(float titlePadding) { mTitlePadding = titlePadding; invalidate(); } public float getTopPadding() { return this.mTopPadding; } public void setTopPadding(float topPadding) { mTopPadding = topPadding; invalidate(); } public float getClipPadding() { return this.mClipPadding; } public void setClipPadding(float clipPadding) { mClipPadding = clipPadding; invalidate(); } public void setTypeface(Typeface typeface) { mPaintText.setTypeface(typeface); invalidate(); } public Typeface getTypeface() { return mPaintText.getTypeface(); } /* * (non-Javadoc) * * @see android.view.View#onDraw(android.graphics.Canvas) */ @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); if (mViewPager == null) { return; } final int count = mViewPager.getAdapter().getCount(); if (count == 0) { return; } // mCurrentPage is -1 on first start and after orientation changed. If so, retrieve the correct index from viewpager. if (mCurrentPage == -1 && mViewPager != null) { mCurrentPage = mViewPager.getCurrentItem(); } //Calculate views bounds ArrayList bounds = calculateAllBounds(mPaintText); final int boundsSize = bounds.size(); //Make sure we're on a page that still exists if (mCurrentPage >= boundsSize) { setCurrentItem(boundsSize - 1); return; } final int countMinusOne = count - 1; final float halfWidth = getWidth() / 2f; final int left = getLeft(); final float leftClip = left + mClipPadding; final int width = getWidth(); int height = getHeight(); final int right = left + width; final float rightClip = right - mClipPadding; int page = mCurrentPage; float offsetPercent; if (mPageOffset <= 0.5) { offsetPercent = mPageOffset; } else { page += 1; offsetPercent = 1 - mPageOffset; } final boolean currentSelected = (offsetPercent <= SELECTION_FADE_PERCENTAGE); final boolean currentBold = (offsetPercent <= BOLD_FADE_PERCENTAGE); final float selectedPercent = (SELECTION_FADE_PERCENTAGE - offsetPercent) / SELECTION_FADE_PERCENTAGE; //Verify if the current view must be clipped to the screen Rect curPageBound = bounds.get(mCurrentPage); float curPageWidth = curPageBound.right - curPageBound.left; if (curPageBound.left < leftClip) { //Try to clip to the screen (left side) clipViewOnTheLeft(curPageBound, curPageWidth, left); } if (curPageBound.right > rightClip) { //Try to clip to the screen (right side) clipViewOnTheRight(curPageBound, curPageWidth, right); } //Left views starting from the current position if (mCurrentPage > 0) { for (int i = mCurrentPage - 1; i >= 0; i--) { Rect bound = bounds.get(i); //Is left side is outside the screen if (bound.left < leftClip) { int w = bound.right - bound.left; //Try to clip to the screen (left side) clipViewOnTheLeft(bound, w, left); //Except if there's an intersection with the right view Rect rightBound = bounds.get(i + 1); //Intersection if (bound.right + mTitlePadding > rightBound.left) { bound.left = (int) (rightBound.left - w - mTitlePadding); bound.right = bound.left + w; } } } } //Right views starting from the current position if (mCurrentPage < countMinusOne) { for (int i = mCurrentPage + 1 ; i < count; i++) { Rect bound = bounds.get(i); //If right side is outside the screen if (bound.right > rightClip) { int w = bound.right - bound.left; //Try to clip to the screen (right side) clipViewOnTheRight(bound, w, right); //Except if there's an intersection with the left view Rect leftBound = bounds.get(i - 1); //Intersection if (bound.left - mTitlePadding < leftBound.right) { bound.left = (int) (leftBound.right + mTitlePadding); bound.right = bound.left + w; } } } } //Now draw views int colorTextAlpha = mColorText >>> 24; for (int i = 0; i < count; i++) { //Get the title Rect bound = bounds.get(i); //Only if one side is visible if ((bound.left > left && bound.left < right) || (bound.right > left && bound.right < right)) { final boolean currentPage = (i == page); final CharSequence pageTitle = getTitle(i); //Only set bold if we are within bounds mPaintText.setFakeBoldText(currentPage && currentBold && mBoldText); //Draw text as unselected mPaintText.setColor(mColorText); if(currentPage && currentSelected) { //Fade out/in unselected text as the selected text fades in/out mPaintText.setAlpha(colorTextAlpha - (int)(colorTextAlpha * selectedPercent)); } //Except if there's an intersection with the right view if (i < boundsSize - 1) { Rect rightBound = bounds.get(i + 1); //Intersection if (bound.right + mTitlePadding > rightBound.left) { int w = bound.right - bound.left; bound.left = (int) (rightBound.left - w - mTitlePadding); bound.right = bound.left + w; } } canvas.drawText(pageTitle, 0, pageTitle.length(), bound.left, bound.bottom + mTopPadding, mPaintText); //If we are within the selected bounds draw the selected text if (currentPage && currentSelected) { mPaintText.setColor(mColorSelected); mPaintText.setAlpha((int)((mColorSelected >>> 24) * selectedPercent)); canvas.drawText(pageTitle, 0, pageTitle.length(), bound.left, bound.bottom + mTopPadding, mPaintText); } } } //If we want the line on the top change height to zero and invert the line height to trick the drawing code float footerLineHeight = mFooterLineHeight; float footerIndicatorLineHeight = mFooterIndicatorHeight; if (mLinePosition == LinePosition.Top) { height = 0; footerLineHeight = -footerLineHeight; footerIndicatorLineHeight = -footerIndicatorLineHeight; } //Draw the footer line mPath.reset(); mPath.moveTo(0, height - footerLineHeight / 2f); mPath.lineTo(width, height - footerLineHeight / 2f); mPath.close(); canvas.drawPath(mPath, mPaintFooterLine); float heightMinusLine = height - footerLineHeight; switch (mFooterIndicatorStyle) { case Triangle: mPath.reset(); mPath.moveTo(halfWidth, heightMinusLine - footerIndicatorLineHeight); mPath.lineTo(halfWidth + footerIndicatorLineHeight, heightMinusLine); mPath.lineTo(halfWidth - footerIndicatorLineHeight, heightMinusLine); mPath.close(); canvas.drawPath(mPath, mPaintFooterIndicator); break; case Underline: if (!currentSelected || page >= boundsSize) { break; } Rect underlineBounds = bounds.get(page); final float rightPlusPadding = underlineBounds.right + mFooterIndicatorUnderlinePadding; final float leftMinusPadding = underlineBounds.left - mFooterIndicatorUnderlinePadding; final float heightMinusLineMinusIndicator = heightMinusLine - footerIndicatorLineHeight; mPath.reset(); mPath.moveTo(leftMinusPadding, heightMinusLine); mPath.lineTo(rightPlusPadding, heightMinusLine); mPath.lineTo(rightPlusPadding, heightMinusLineMinusIndicator); mPath.lineTo(leftMinusPadding, heightMinusLineMinusIndicator); mPath.close(); mPaintFooterIndicator.setAlpha((int)(0xFF * selectedPercent)); canvas.drawPath(mPath, mPaintFooterIndicator); mPaintFooterIndicator.setAlpha(0xFF); break; } } public boolean onTouchEvent(MotionEvent ev) { if (super.onTouchEvent(ev)) { return true; } if ((mViewPager == null) || (mViewPager.getAdapter().getCount() == 0)) { return false; } final int action = ev.getAction() & MotionEventCompat.ACTION_MASK; switch (action) { case MotionEvent.ACTION_DOWN: mActivePointerId = MotionEventCompat.getPointerId(ev, 0); mLastMotionX = ev.getX(); break; case MotionEvent.ACTION_MOVE: { final int activePointerIndex = MotionEventCompat.findPointerIndex(ev, mActivePointerId); final float x = MotionEventCompat.getX(ev, activePointerIndex); final float deltaX = x - mLastMotionX; if (!mIsDragging) { if (Math.abs(deltaX) > mTouchSlop) { mIsDragging = true; } } if (mIsDragging) { mLastMotionX = x; if (mViewPager.isFakeDragging() || mViewPager.beginFakeDrag()) { mViewPager.fakeDragBy(deltaX); } } break; } case MotionEvent.ACTION_CANCEL: case MotionEvent.ACTION_UP: if (!mIsDragging) { final int count = mViewPager.getAdapter().getCount(); final int width = getWidth(); final float halfWidth = width / 2f; final float sixthWidth = width / 6f; final float leftThird = halfWidth - sixthWidth; final float rightThird = halfWidth + sixthWidth; final float eventX = ev.getX(); if (eventX < leftThird) { if (mCurrentPage > 0) { if (action != MotionEvent.ACTION_CANCEL) { mViewPager.setCurrentItem(mCurrentPage - 1); } return true; } } else if (eventX > rightThird) { if (mCurrentPage < count - 1) { if (action != MotionEvent.ACTION_CANCEL) { mViewPager.setCurrentItem(mCurrentPage + 1); } return true; } } else { //Middle third if (mCenterItemClickListener != null && action != MotionEvent.ACTION_CANCEL) { mCenterItemClickListener.onCenterItemClick(mCurrentPage); } } } mIsDragging = false; mActivePointerId = INVALID_POINTER; if (mViewPager.isFakeDragging()) mViewPager.endFakeDrag(); break; case MotionEventCompat.ACTION_POINTER_DOWN: { final int index = MotionEventCompat.getActionIndex(ev); mLastMotionX = MotionEventCompat.getX(ev, index); mActivePointerId = MotionEventCompat.getPointerId(ev, index); break; } case MotionEventCompat.ACTION_POINTER_UP: final int pointerIndex = MotionEventCompat.getActionIndex(ev); final int pointerId = MotionEventCompat.getPointerId(ev, pointerIndex); if (pointerId == mActivePointerId) { final int newPointerIndex = pointerIndex == 0 ? 1 : 0; mActivePointerId = MotionEventCompat.getPointerId(ev, newPointerIndex); } mLastMotionX = MotionEventCompat.getX(ev, MotionEventCompat.findPointerIndex(ev, mActivePointerId)); break; } return true; } /** * Set bounds for the right textView including clip padding. * * @param curViewBound * current bounds. * @param curViewWidth * width of the view. */ private void clipViewOnTheRight(Rect curViewBound, float curViewWidth, int right) { curViewBound.right = (int) (right - mClipPadding); curViewBound.left = (int) (curViewBound.right - curViewWidth); } /** * Set bounds for the left textView including clip padding. * * @param curViewBound * current bounds. * @param curViewWidth * width of the view. */ private void clipViewOnTheLeft(Rect curViewBound, float curViewWidth, int left) { curViewBound.left = (int) (left + mClipPadding); curViewBound.right = (int) (mClipPadding + curViewWidth); } /** * Calculate views bounds and scroll them according to the current index * * @param paint * @return */ private ArrayList calculateAllBounds(Paint paint) { ArrayList list = new ArrayList(); //For each views (If no values then add a fake one) final int count = mViewPager.getAdapter().getCount(); final int width = getWidth(); final int halfWidth = width / 2; for (int i = 0; i < count; i++) { Rect bounds = calcBounds(i, paint); int w = bounds.right - bounds.left; int h = bounds.bottom - bounds.top; bounds.left = (int)(halfWidth - (w / 2f) + ((i - mCurrentPage - mPageOffset) * width)); bounds.right = bounds.left + w; bounds.top = 0; bounds.bottom = h; list.add(bounds); } return list; } /** * Calculate the bounds for a view's title * * @param index * @param paint * @return */ private Rect calcBounds(int index, Paint paint) { //Calculate the text bounds Rect bounds = new Rect(); CharSequence title = getTitle(index); bounds.right = (int) paint.measureText(title, 0, title.length()); bounds.bottom = (int) (paint.descent() - paint.ascent()); return bounds; } @Override public void setViewPager(ViewPager view) { if (mViewPager == view) { return; } if (mViewPager != null) { mViewPager.setOnPageChangeListener(null); } if (view.getAdapter() == null) { throw new IllegalStateException("ViewPager does not have adapter instance."); } mViewPager = view; mViewPager.setOnPageChangeListener(this); invalidate(); } @Override public void setViewPager(ViewPager view, int initialPosition) { setViewPager(view); setCurrentItem(initialPosition); } @Override public void notifyDataSetChanged() { invalidate(); } /** * Set a callback listener for the center item click. * * @param listener Callback instance. */ public void setOnCenterItemClickListener(OnCenterItemClickListener listener) { mCenterItemClickListener = listener; } @Override public void setCurrentItem(int item) { if (mViewPager == null) { throw new IllegalStateException("ViewPager has not been bound."); } mViewPager.setCurrentItem(item); mCurrentPage = item; invalidate(); } @Override public void onPageScrollStateChanged(int state) { mScrollState = state; if (mListener != null) { mListener.onPageScrollStateChanged(state); } } @Override public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { mCurrentPage = position; mPageOffset = positionOffset; invalidate(); if (mListener != null) { mListener.onPageScrolled(position, positionOffset, positionOffsetPixels); } } @Override public void onPageSelected(int position) { if (mScrollState == ViewPager.SCROLL_STATE_IDLE) { mCurrentPage = position; invalidate(); } if (mListener != null) { mListener.onPageSelected(position); } } @Override public void setOnPageChangeListener(ViewPager.OnPageChangeListener listener) { mListener = listener; } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { //Measure our width in whatever mode specified final int measuredWidth = MeasureSpec.getSize(widthMeasureSpec); //Determine our height float height; final int heightSpecMode = MeasureSpec.getMode(heightMeasureSpec); if (heightSpecMode == MeasureSpec.EXACTLY) { //We were told how big to be height = MeasureSpec.getSize(heightMeasureSpec); } else { //Calculate the text bounds mBounds.setEmpty(); mBounds.bottom = (int) (mPaintText.descent() - mPaintText.ascent()); height = mBounds.bottom - mBounds.top + mFooterLineHeight + mFooterPadding + mTopPadding; if (mFooterIndicatorStyle != IndicatorStyle.None) { height += mFooterIndicatorHeight; } } final int measuredHeight = (int)height; setMeasuredDimension(measuredWidth, measuredHeight); } @Override public void onRestoreInstanceState(Parcelable state) { SavedState savedState = (SavedState)state; super.onRestoreInstanceState(savedState.getSuperState()); mCurrentPage = savedState.currentPage; requestLayout(); } @Override public Parcelable onSaveInstanceState() { Parcelable superState = super.onSaveInstanceState(); SavedState savedState = new SavedState(superState); savedState.currentPage = mCurrentPage; return savedState; } static class SavedState extends BaseSavedState { int currentPage; public SavedState(Parcelable superState) { super(superState); } private SavedState(Parcel in) { super(in); currentPage = in.readInt(); } @Override public void writeToParcel(Parcel dest, int flags) { super.writeToParcel(dest, flags); dest.writeInt(currentPage); } @SuppressWarnings("UnusedDeclaration") public static final Creator CREATOR = new Creator() { @Override public SavedState createFromParcel(Parcel in) { return new SavedState(in); } @Override public SavedState[] newArray(int size) { return new SavedState[size]; } }; } private CharSequence getTitle(int i) { CharSequence title = mViewPager.getAdapter().getPageTitle(i); if (title == null) { title = EMPTY_TITLE; } return title; } } ================================================ FILE: app/src/main/java/viewpagerindicator/UnderlinePageIndicator.java ================================================ /* * Copyright (C) 2012 Jake Wharton * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package viewpagerindicator; import android.content.Context; import android.content.res.Resources; import android.content.res.TypedArray; import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.drawable.Drawable; import android.os.Parcel; import android.os.Parcelable; import android.support.v4.view.MotionEventCompat; import android.support.v4.view.ViewConfigurationCompat; import android.support.v4.view.ViewPager; import android.util.AttributeSet; import android.view.MotionEvent; import android.view.View; import android.view.ViewConfiguration; import com.cjj.bb.R; /** * Draws a line for each page. The current page line is colored differently * than the unselected page lines. */ public class UnderlinePageIndicator extends View implements PageIndicator { private static final int INVALID_POINTER = -1; private static final int FADE_FRAME_MS = 30; private final Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG); private boolean mFades; private int mFadeDelay; private int mFadeLength; private int mFadeBy; private ViewPager mViewPager; private ViewPager.OnPageChangeListener mListener; private int mScrollState; private int mCurrentPage; private float mPositionOffset; private int mTouchSlop; private float mLastMotionX = -1; private int mActivePointerId = INVALID_POINTER; private boolean mIsDragging; private final Runnable mFadeRunnable = new Runnable() { @Override public void run() { if (!mFades) return; final int alpha = Math.max(mPaint.getAlpha() - mFadeBy, 0); mPaint.setAlpha(alpha); invalidate(); if (alpha > 0) { postDelayed(this, FADE_FRAME_MS); } } }; public UnderlinePageIndicator(Context context) { this(context, null); } public UnderlinePageIndicator(Context context, AttributeSet attrs) { this(context, attrs, R.attr.vpiUnderlinePageIndicatorStyle); } public UnderlinePageIndicator(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); if (isInEditMode()) return; final Resources res = getResources(); //Load defaults from resources final boolean defaultFades = res.getBoolean(R.bool.default_underline_indicator_fades); final int defaultFadeDelay = res.getInteger(R.integer.default_underline_indicator_fade_delay); final int defaultFadeLength = res.getInteger(R.integer.default_underline_indicator_fade_length); final int defaultSelectedColor = res.getColor(R.color.default_underline_indicator_selected_color); //Retrieve styles attributes TypedArray a = context.obtainStyledAttributes(attrs,R.styleable.UnderlinePageIndicator, defStyle, 0); setFades(a.getBoolean(R.styleable.UnderlinePageIndicator_fades, defaultFades)); setSelectedColor(a.getColor(R.styleable.UnderlinePageIndicator_selectedColor, defaultSelectedColor)); setFadeDelay(a.getInteger(R.styleable.UnderlinePageIndicator_fadeDelay, defaultFadeDelay)); setFadeLength(a.getInteger(R.styleable.UnderlinePageIndicator_fadeLength, defaultFadeLength)); Drawable background = a.getDrawable(R.styleable.UnderlinePageIndicator_android_background); if (background != null) { setBackgroundDrawable(background); } a.recycle(); final ViewConfiguration configuration = ViewConfiguration.get(context); mTouchSlop = ViewConfigurationCompat.getScaledPagingTouchSlop(configuration); } public boolean getFades() { return mFades; } public void setFades(boolean fades) { if (fades != mFades) { mFades = fades; if (fades) { post(mFadeRunnable); } else { removeCallbacks(mFadeRunnable); mPaint.setAlpha(0xFF); invalidate(); } } } public int getFadeDelay() { return mFadeDelay; } public void setFadeDelay(int fadeDelay) { mFadeDelay = fadeDelay; } public int getFadeLength() { return mFadeLength; } public void setFadeLength(int fadeLength) { mFadeLength = fadeLength; mFadeBy = 0xFF / (mFadeLength / FADE_FRAME_MS); } public int getSelectedColor() { return mPaint.getColor(); } public void setSelectedColor(int selectedColor) { mPaint.setColor(selectedColor); invalidate(); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); if (mViewPager == null) { return; } final int count = mViewPager.getAdapter().getCount(); if (count == 0) { return; } if (mCurrentPage >= count) { setCurrentItem(count - 1); return; } final int paddingLeft = getPaddingLeft(); final float pageWidth = (getWidth() - paddingLeft - getPaddingRight()) / (1f * count); final float left = paddingLeft + pageWidth * (mCurrentPage + mPositionOffset); final float right = left + pageWidth; final float top = getPaddingTop(); final float bottom = getHeight() - getPaddingBottom(); canvas.drawRect(left, top, right, bottom, mPaint); } public boolean onTouchEvent(MotionEvent ev) { if (super.onTouchEvent(ev)) { return true; } if ((mViewPager == null) || (mViewPager.getAdapter().getCount() == 0)) { return false; } final int action = ev.getAction() & MotionEventCompat.ACTION_MASK; switch (action) { case MotionEvent.ACTION_DOWN: mActivePointerId = MotionEventCompat.getPointerId(ev, 0); mLastMotionX = ev.getX(); break; case MotionEvent.ACTION_MOVE: { final int activePointerIndex = MotionEventCompat.findPointerIndex(ev, mActivePointerId); final float x = MotionEventCompat.getX(ev, activePointerIndex); final float deltaX = x - mLastMotionX; if (!mIsDragging) { if (Math.abs(deltaX) > mTouchSlop) { mIsDragging = true; } } if (mIsDragging) { mLastMotionX = x; if (mViewPager.isFakeDragging() || mViewPager.beginFakeDrag()) { mViewPager.fakeDragBy(deltaX); } } break; } case MotionEvent.ACTION_CANCEL: case MotionEvent.ACTION_UP: if (!mIsDragging) { final int count = mViewPager.getAdapter().getCount(); final int width = getWidth(); final float halfWidth = width / 2f; final float sixthWidth = width / 6f; if ((mCurrentPage > 0) && (ev.getX() < halfWidth - sixthWidth)) { if (action != MotionEvent.ACTION_CANCEL) { mViewPager.setCurrentItem(mCurrentPage - 1); } return true; } else if ((mCurrentPage < count - 1) && (ev.getX() > halfWidth + sixthWidth)) { if (action != MotionEvent.ACTION_CANCEL) { mViewPager.setCurrentItem(mCurrentPage + 1); } return true; } } mIsDragging = false; mActivePointerId = INVALID_POINTER; if (mViewPager.isFakeDragging()) mViewPager.endFakeDrag(); break; case MotionEventCompat.ACTION_POINTER_DOWN: { final int index = MotionEventCompat.getActionIndex(ev); mLastMotionX = MotionEventCompat.getX(ev, index); mActivePointerId = MotionEventCompat.getPointerId(ev, index); break; } case MotionEventCompat.ACTION_POINTER_UP: final int pointerIndex = MotionEventCompat.getActionIndex(ev); final int pointerId = MotionEventCompat.getPointerId(ev, pointerIndex); if (pointerId == mActivePointerId) { final int newPointerIndex = pointerIndex == 0 ? 1 : 0; mActivePointerId = MotionEventCompat.getPointerId(ev, newPointerIndex); } mLastMotionX = MotionEventCompat.getX(ev, MotionEventCompat.findPointerIndex(ev, mActivePointerId)); break; } return true; } @Override public void setViewPager(ViewPager viewPager) { if (mViewPager == viewPager) { return; } if (mViewPager != null) { //Clear us from the old pager. mViewPager.setOnPageChangeListener(null); } if (viewPager.getAdapter() == null) { throw new IllegalStateException("ViewPager does not have adapter instance."); } mViewPager = viewPager; mViewPager.setOnPageChangeListener(this); invalidate(); post(new Runnable() { @Override public void run() { if (mFades) { post(mFadeRunnable); } } }); } @Override public void setViewPager(ViewPager view, int initialPosition) { setViewPager(view); setCurrentItem(initialPosition); } @Override public void setCurrentItem(int item) { if (mViewPager == null) { throw new IllegalStateException("ViewPager has not been bound."); } mViewPager.setCurrentItem(item); mCurrentPage = item; invalidate(); } @Override public void notifyDataSetChanged() { invalidate(); } @Override public void onPageScrollStateChanged(int state) { mScrollState = state; if (mListener != null) { mListener.onPageScrollStateChanged(state); } } @Override public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { mCurrentPage = position; mPositionOffset = positionOffset; if (mFades) { if (positionOffsetPixels > 0) { removeCallbacks(mFadeRunnable); mPaint.setAlpha(0xFF); } else if (mScrollState != ViewPager.SCROLL_STATE_DRAGGING) { postDelayed(mFadeRunnable, mFadeDelay); } } invalidate(); if (mListener != null) { mListener.onPageScrolled(position, positionOffset, positionOffsetPixels); } } @Override public void onPageSelected(int position) { if (mScrollState == ViewPager.SCROLL_STATE_IDLE) { mCurrentPage = position; mPositionOffset = 0; invalidate(); mFadeRunnable.run(); } if (mListener != null) { mListener.onPageSelected(position); } } @Override public void setOnPageChangeListener(ViewPager.OnPageChangeListener listener) { mListener = listener; } @Override public void onRestoreInstanceState(Parcelable state) { SavedState savedState = (SavedState)state; super.onRestoreInstanceState(savedState.getSuperState()); mCurrentPage = savedState.currentPage; requestLayout(); } @Override public Parcelable onSaveInstanceState() { Parcelable superState = super.onSaveInstanceState(); SavedState savedState = new SavedState(superState); savedState.currentPage = mCurrentPage; return savedState; } static class SavedState extends BaseSavedState { int currentPage; public SavedState(Parcelable superState) { super(superState); } private SavedState(Parcel in) { super(in); currentPage = in.readInt(); } @Override public void writeToParcel(Parcel dest, int flags) { super.writeToParcel(dest, flags); dest.writeInt(currentPage); } @SuppressWarnings("UnusedDeclaration") public static final Creator CREATOR = new Creator() { @Override public SavedState createFromParcel(Parcel in) { return new SavedState(in); } @Override public SavedState[] newArray(int size) { return new SavedState[size]; } }; } } ================================================ FILE: app/src/main/res/anim/bili_anim.xml ================================================ ================================================ FILE: app/src/main/res/anim/push_left_in.xml ================================================ ================================================ FILE: app/src/main/res/anim/push_no.xml ================================================ ================================================ FILE: app/src/main/res/anim/slide_in_bottom.xml ================================================ ================================================ FILE: app/src/main/res/anim/slide_in_top.xml ================================================ ================================================ FILE: app/src/main/res/anim/slide_out_bottom.xml ================================================ ================================================ FILE: app/src/main/res/anim/slide_out_top.xml ================================================ ================================================ FILE: app/src/main/res/color/vpi__dark_theme.xml ================================================ ================================================ FILE: app/src/main/res/color/vpi__light_theme.xml ================================================ ================================================ FILE: app/src/main/res/drawable/back_btn.xml ================================================ ================================================ FILE: app/src/main/res/drawable/base_action_bar_action_more_selector.xml ================================================ ================================================ FILE: app/src/main/res/drawable/card_background.xml ================================================ ================================================ FILE: app/src/main/res/drawable/comment_btn.xml ================================================ ================================================ FILE: app/src/main/res/drawable/corner.xml ================================================ ================================================ FILE: app/src/main/res/drawable/dot_focused.xml ================================================ ================================================ FILE: app/src/main/res/drawable/dot_normal.xml ================================================ ================================================ FILE: app/src/main/res/drawable/focus_show.xml ================================================ ================================================ FILE: app/src/main/res/drawable/home_btn_bg.xml ================================================ ================================================ FILE: app/src/main/res/drawable/image_corner.xml ================================================ ================================================ FILE: app/src/main/res/drawable/list_selector.xml ================================================ ================================================ FILE: app/src/main/res/drawable/normal_show.xml ================================================ ================================================ FILE: app/src/main/res/drawable/progressbar_large.xml ================================================ ================================================ FILE: app/src/main/res/drawable/selector_tabtext.xml ================================================ ================================================ FILE: app/src/main/res/drawable/tab_indicator.xml ================================================ ================================================ FILE: app/src/main/res/drawable/vpi__tab_indicator.xml ================================================ ================================================ FILE: app/src/main/res/drawable-xhdpi/mediacontroller_btn_bg.xml ================================================ ================================================ FILE: app/src/main/res/layout/activity_main.xml ================================================ ================================================ FILE: app/src/main/res/layout/activity_video.xml ================================================ ================================================ FILE: app/src/main/res/layout/activity_video_info.xml ================================================ ================================================ FILE: app/src/main/res/layout/area_item.xml ================================================ ================================================ FILE: app/src/main/res/layout/back_head.xml ================================================ ================================================ FILE: app/src/main/res/layout/banner.xml ================================================ ================================================ FILE: app/src/main/res/layout/bili_videoview.xml ================================================ ================================================ FILE: app/src/main/res/layout/bili_webview.xml ================================================ ================================================ FILE: app/src/main/res/layout/bili_webview_head.xml ================================================ ================================================ FILE: app/src/main/res/layout/brightness_volumn.xml ================================================ ================================================ FILE: app/src/main/res/layout/card_layout.xml ================================================ ================================================ FILE: app/src/main/res/layout/donghua_tab.xml ================================================ ================================================ FILE: app/src/main/res/layout/fragment_donghua.xml ================================================ ================================================ FILE: app/src/main/res/layout/fragment_gamecenter.xml ================================================ ================================================ FILE: app/src/main/res/layout/fragment_homepage.xml ================================================ ================================================ FILE: app/src/main/res/layout/fragment_main.xml ================================================ ================================================ FILE: app/src/main/res/layout/fragment_online.xml ================================================ ================================================ FILE: app/src/main/res/layout/fragment_online_item.xml ================================================ ================================================ FILE: app/src/main/res/layout/fragment_subarea.xml ================================================ ================================================ FILE: app/src/main/res/layout/fragment_videoinfo.xml ================================================