├── .gitignore ├── .idea ├── compiler.xml ├── copyright │ └── profiles_settings.xml ├── encodings.xml ├── gradle.xml ├── inspectionProfiles │ ├── Project_Default.xml │ └── profiles_settings.xml ├── misc.xml ├── modules.xml └── runConfigurations.xml ├── app ├── .gitignore ├── build.gradle ├── libs │ ├── multiwindow-v1.3.2.jar │ └── sdk-v1.0.0.jar ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── mayi │ │ └── douyu │ │ └── ExampleInstrumentedTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── mayi │ │ │ └── douyu │ │ │ ├── api │ │ │ ├── ApiManager.java │ │ │ ├── DouyuRoomService.java │ │ │ ├── DouyuService.java │ │ │ ├── HuYaService.java │ │ │ ├── PandaRoomService.java │ │ │ └── PandaService.java │ │ │ ├── base │ │ │ ├── App.java │ │ │ ├── BaseActivity.java │ │ │ └── BaseRecyclerAdapter.java │ │ │ ├── entity │ │ │ ├── DYClassify.java │ │ │ ├── DYDetails.java │ │ │ ├── DYResponse.java │ │ │ ├── DYRoom.java │ │ │ ├── DYSearchDetails.java │ │ │ ├── HYClassify.java │ │ │ ├── HYDetails.java │ │ │ ├── HYResponse.java │ │ │ ├── HYRoom.java │ │ │ ├── PDClassify.java │ │ │ ├── PDDetails.java │ │ │ ├── PDResponse.java │ │ │ ├── PDRoom.java │ │ │ └── User.java │ │ │ ├── ijkplayer │ │ │ ├── MediaPlayerService.java │ │ │ ├── Settings.java │ │ │ └── widget │ │ │ │ ├── media │ │ │ │ ├── AndroidMediaController.java │ │ │ │ ├── FileMediaDataSource.java │ │ │ │ ├── IMediaController.java │ │ │ │ ├── IRenderView.java │ │ │ │ ├── IjkVideoView.java │ │ │ │ ├── InfoHudViewHolder.java │ │ │ │ ├── MeasureHelper.java │ │ │ │ ├── MediaPlayerCompat.java │ │ │ │ ├── SurfaceRenderView.java │ │ │ │ ├── TableLayoutBinder.java │ │ │ │ └── TextureRenderView.java │ │ │ │ └── preference │ │ │ │ └── IjkListPreference.java │ │ │ ├── mvpbase │ │ │ ├── BasePresenter.java │ │ │ ├── BasePresenterImpl.java │ │ │ ├── BaseRequestView.java │ │ │ ├── BaseView.java │ │ │ ├── MVPBaseActivity.java │ │ │ └── MVPBaseFragment.java │ │ │ ├── service │ │ │ └── FloatingPlayService.java │ │ │ ├── ui │ │ │ ├── about │ │ │ │ ├── AboutActivity.java │ │ │ │ ├── AboutAdapter.java │ │ │ │ └── LibsAdapter.java │ │ │ ├── main │ │ │ │ ├── CustomErrorActivity.java │ │ │ │ ├── MainActivity.java │ │ │ │ ├── MainFragmentAdapter.java │ │ │ │ ├── SplashActivity.java │ │ │ │ ├── douyu │ │ │ │ │ ├── LiveAdapter.java │ │ │ │ │ ├── LiveContract.java │ │ │ │ │ ├── LiveFragment.java │ │ │ │ │ └── LivePresenter.java │ │ │ │ ├── huya │ │ │ │ │ ├── LiveAdapter.java │ │ │ │ │ ├── LiveContract.java │ │ │ │ │ ├── LiveFragment.java │ │ │ │ │ └── LivePresenter.java │ │ │ │ └── panda │ │ │ │ │ ├── LiveAdapter.java │ │ │ │ │ ├── LiveContract.java │ │ │ │ │ ├── LiveFragment.java │ │ │ │ │ └── LivePresenter.java │ │ │ ├── search │ │ │ │ ├── SearchActivity.java │ │ │ │ ├── SearchAdapter.java │ │ │ │ ├── SearchContract.java │ │ │ │ └── SearchPresenter.java │ │ │ ├── test │ │ │ │ ├── LoginActivity.java │ │ │ │ ├── LoginContract.java │ │ │ │ └── LoginPresenter.java │ │ │ └── video │ │ │ │ ├── full │ │ │ │ ├── FullVideoActivity.java │ │ │ │ ├── FullVideoContract.java │ │ │ │ └── FullVideoPresenter.java │ │ │ │ └── half │ │ │ │ ├── HalfVideoActivity.java │ │ │ │ ├── HalfVideoContract.java │ │ │ │ └── HalfVideoPresenter.java │ │ │ ├── util │ │ │ ├── AnimUtils.java │ │ │ ├── AppManager.java │ │ │ ├── ColorUtils.java │ │ │ ├── ImeUtils.java │ │ │ ├── InstanceUtils.java │ │ │ ├── MD5.java │ │ │ ├── VideoUrlUtils.java │ │ │ ├── ViewUtils.java │ │ │ ├── rx │ │ │ │ ├── RxBus.java │ │ │ │ └── RxResultHelper.java │ │ │ └── transition │ │ │ │ ├── FabTransform.java │ │ │ │ ├── GravityArcMotion.java │ │ │ │ └── StartAnimatable.java │ │ │ └── widget │ │ │ ├── CustomSizeFrameLayout.java │ │ │ ├── CustomSizeImageView.java │ │ │ ├── ElasticDragDismissFrameLayout.java │ │ │ ├── FloatWindow.java │ │ │ ├── InkPageIndicator.java │ │ │ ├── ScrollAwareFABBehaviorDefault.java │ │ │ └── help │ │ │ └── BaseOnScrollListener.java │ └── res │ │ ├── anim │ │ ├── fade_in.xml │ │ └── fade_out.xml │ │ ├── animator │ │ ├── searchback_hide_arrow_head.xml │ │ ├── searchback_hide_circle.xml │ │ ├── searchback_show_arrow_head.xml │ │ ├── searchback_show_circle.xml │ │ ├── searchback_stem_back_to_search.xml │ │ └── searchback_stem_search_to_back.xml │ │ ├── drawable-v21 │ │ ├── ic_menu_camera.xml │ │ ├── ic_menu_gallery.xml │ │ ├── ic_menu_manage.xml │ │ ├── ic_menu_send.xml │ │ ├── ic_menu_share.xml │ │ └── ic_menu_slideshow.xml │ │ ├── drawable │ │ ├── avd_back_to_search.xml │ │ ├── avd_search_to_back.xml │ │ ├── background_btn_stream_normal.xml │ │ ├── background_btn_stream_pressed.xml │ │ ├── background_iv_circle.xml │ │ ├── background_tv_name.xml │ │ ├── background_tv_title.xml │ │ ├── bg_live_item.xml │ │ ├── ic_android.xml │ │ ├── ic_arrow_back_padded.xml │ │ ├── ic_avatar_default.xml │ │ ├── ic_avatar_normal.xml │ │ ├── ic_avatar_pressed.xml │ │ ├── ic_back_arrow_normal.xml │ │ ├── ic_back_arrow_pressed.xml │ │ ├── ic_camera.xml │ │ ├── ic_clear_black_24dp.xml │ │ ├── ic_computer.xml │ │ ├── ic_danmu_off_normal.xml │ │ ├── ic_danmu_off_pressed.xml │ │ ├── ic_danmu_on_normal.xml │ │ ├── ic_danmu_on_normal_dark.xml │ │ ├── ic_danmu_on_pressed.xml │ │ ├── ic_empty.xml │ │ ├── ic_expand_close.xml │ │ ├── ic_expand_open.xml │ │ ├── ic_explore_default.xml │ │ ├── ic_explore_normal.xml │ │ ├── ic_explore_pressed.xml │ │ ├── ic_fullscreen_exit_normal.xml │ │ ├── ic_fullscreen_exit_pressed.xml │ │ ├── ic_fullscreen_normal.xml │ │ ├── ic_fullscreen_pressed.xml │ │ ├── ic_introduction.xml │ │ ├── ic_live_normal.xml │ │ ├── ic_live_placeholder.xml │ │ ├── ic_live_pressed.xml │ │ ├── ic_pause_normal.xml │ │ ├── ic_pause_pressed.xml │ │ ├── ic_play_arrow_normal.xml │ │ ├── ic_play_arrow_pressed.xml │ │ ├── ic_refresh_normal.xml │ │ ├── ic_refresh_pressed.xml │ │ ├── ic_school.xml │ │ ├── ic_search_24dp.xml │ │ ├── ic_texture_black_24dp.xml │ │ ├── ic_user.xml │ │ ├── ic_user_normal.xml │ │ ├── ic_user_pressed.xml │ │ ├── ic_visitor.xml │ │ ├── searchback_back.xml │ │ ├── searchback_search.xml │ │ ├── selector_btn_back.xml │ │ ├── selector_btn_danmu_off.xml │ │ ├── selector_btn_danmu_on.xml │ │ ├── selector_btn_fullscreen.xml │ │ ├── selector_btn_fullscreen_exit.xml │ │ ├── selector_btn_pause.xml │ │ ├── selector_btn_play.xml │ │ ├── selector_btn_refresh.xml │ │ ├── selector_btn_stream.xml │ │ └── side_nav_bar.xml │ │ ├── layout │ │ ├── activity_about.xml │ │ ├── activity_custom_error.xml │ │ ├── activity_full_video.xml │ │ ├── activity_half_video.xml │ │ ├── activity_login.xml │ │ ├── activity_main.xml │ │ ├── activity_search.xml │ │ ├── activity_splash.xml │ │ ├── app_bar_main.xml │ │ ├── connectionless_layout.xml │ │ ├── failed_layout.xml │ │ ├── fragment_live.xml │ │ ├── item_bottom_loading.xml │ │ ├── item_classify.xml │ │ ├── item_library.xml │ │ ├── item_live.xml │ │ ├── layout_about_info.xml │ │ ├── layout_about_support.xml │ │ ├── layout_play.xml │ │ ├── loading_layout.xml │ │ ├── nav_header_main.xml │ │ ├── none_layout.xml │ │ ├── table_media_info.xml │ │ ├── table_media_info_row1.xml │ │ ├── table_media_info_row2.xml │ │ ├── table_media_info_section.xml │ │ ├── toolbar_view.xml │ │ └── window_float.xml │ │ ├── menu │ │ ├── activity_main_bottom.xml │ │ ├── activity_main_drawer.xml │ │ └── main.xml │ │ ├── mipmap-hdpi │ │ └── ic_launcher.png │ │ ├── mipmap-mdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xhdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xxhdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xxxhdpi │ │ └── ic_launcher.png │ │ ├── transition │ │ ├── about_enter.xml │ │ ├── about_return.xml │ │ ├── about_return_downward.xml │ │ ├── auto.xml │ │ ├── search_shared_enter.xml │ │ └── search_shared_return.xml │ │ ├── values-v21 │ │ └── styles.xml │ │ ├── values-w820dp │ │ ├── attrs_paging_indicator.xml │ │ └── dimens.xml │ │ └── values │ │ ├── attrs.xml │ │ ├── attrs_costom_size_image.xml │ │ ├── attrs_elastic_drag_dismiss_frame_layout.xml │ │ ├── attrs_fab_transform.xml │ │ ├── attrs_start_animatable.xml │ │ ├── colors.xml │ │ ├── dimens.xml │ │ ├── drawables.xml │ │ ├── searchback.xml │ │ ├── strings.xml │ │ ├── strings_pref.xml │ │ └── styles.xml │ └── test │ └── java │ └── com │ └── mayi │ └── douyu │ └── ExampleUnitTest.java ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/workspace.xml 5 | /.idea/libraries 6 | .DS_Store 7 | /build 8 | /captures 9 | .externalNativeBuild 10 | -------------------------------------------------------------------------------- /.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /.idea/copyright/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /.idea/encodings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 18 | 19 | -------------------------------------------------------------------------------- /.idea/inspectionProfiles/Project_Default.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | -------------------------------------------------------------------------------- /.idea/inspectionProfiles/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 19 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 46 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /.idea/runConfigurations.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/libs/multiwindow-v1.3.2.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yugai/DouYu-Android/9d66864e5cc04b37d728916e877676ea8584677a/app/libs/multiwindow-v1.3.2.jar -------------------------------------------------------------------------------- /app/libs/sdk-v1.0.0.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yugai/DouYu-Android/9d66864e5cc04b37d728916e877676ea8584677a/app/libs/sdk-v1.0.0.jar -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in /Users/yugai/Library/Android/sdk/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more DYDetails, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | -------------------------------------------------------------------------------- /app/src/androidTest/java/com/mayi/douyu/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package com.mayi.douyu; 2 | 3 | import android.content.Context; 4 | import android.support.test.InstrumentationRegistry; 5 | import android.support.test.runner.AndroidJUnit4; 6 | 7 | import org.junit.Test; 8 | import org.junit.runner.RunWith; 9 | 10 | import static org.junit.Assert.*; 11 | 12 | /** 13 | * Instrumentation test, which will execute on an Android device. 14 | * 15 | * @see Testing documentation 16 | */ 17 | @RunWith(AndroidJUnit4.class) 18 | public class ExampleInstrumentedTest { 19 | @Test 20 | public void useAppContext() throws Exception { 21 | // Context of the app under test. 22 | Context appContext = InstrumentationRegistry.getTargetContext(); 23 | 24 | assertEquals("com.mayi.douyu", appContext.getPackageName()); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /app/src/main/java/com/mayi/douyu/api/DouyuRoomService.java: -------------------------------------------------------------------------------- 1 | package com.mayi.douyu.api; 2 | 3 | import com.mayi.douyu.entity.DYResponse; 4 | import com.mayi.douyu.entity.DYDetails; 5 | 6 | import retrofit2.http.Field; 7 | import retrofit2.http.FormUrlEncoded; 8 | import retrofit2.http.POST; 9 | import retrofit2.http.Path; 10 | import rx.Observable; 11 | 12 | /** 13 | * 作者 by yugai 时间 16/11/30. 14 | * * 邮箱 784787081@qq.com 15 | */ 16 | 17 | public interface DouyuRoomService { 18 | String URL="http://www.douyu.com/"; 19 | @FormUrlEncoded 20 | @POST("lapi/live/getPlay/{roomId}") 21 | Observable> getRoomUrl(@Path("roomId") String id, 22 | @Field("cdn") String cdn, 23 | @Field("rate") String rate, 24 | @Field("tt") String tt, 25 | @Field("did") String did, 26 | @Field("sign") String sign); 27 | } 28 | -------------------------------------------------------------------------------- /app/src/main/java/com/mayi/douyu/api/DouyuService.java: -------------------------------------------------------------------------------- 1 | package com.mayi.douyu.api; 2 | 3 | import com.mayi.douyu.entity.DYClassify; 4 | import com.mayi.douyu.entity.DYResponse; 5 | import com.mayi.douyu.entity.DYRoom; 6 | import com.mayi.douyu.entity.DYSearchDetails; 7 | 8 | import java.util.List; 9 | 10 | import retrofit2.http.GET; 11 | import retrofit2.http.POST; 12 | import retrofit2.http.Path; 13 | import retrofit2.http.Query; 14 | import rx.Observable; 15 | 16 | /** 17 | * 作者 by yugai 时间 16/11/24. 18 | * * 邮箱 784787081@qq.com 19 | */ 20 | 21 | public interface DouyuService { 22 | String URL="http://capi.douyucdn.cn/api/v1/"; 23 | int PAGE_SIZE=10; 24 | @POST("live") 25 | Observable>> getRoomList(@Query("limit") int limit, @Query("offset") int offset); 26 | 27 | @GET("getColumnDetail?shortName=game") 28 | Observable>> getClassify(); 29 | 30 | @GET("searchNew/{text}/1?limit=1&offset=0") 31 | Observable> search(@Path("text") String text); 32 | } 33 | -------------------------------------------------------------------------------- /app/src/main/java/com/mayi/douyu/api/HuYaService.java: -------------------------------------------------------------------------------- 1 | package com.mayi.douyu.api; 2 | 3 | import com.mayi.douyu.entity.HYClassify; 4 | import com.mayi.douyu.entity.HYDetails; 5 | import com.mayi.douyu.entity.HYResponse; 6 | import com.mayi.douyu.entity.HYRoom; 7 | 8 | import java.util.List; 9 | 10 | import okhttp3.ResponseBody; 11 | import retrofit2.http.GET; 12 | import retrofit2.http.POST; 13 | import retrofit2.http.Query; 14 | import rx.Observable; 15 | 16 | /** 17 | * 作者 by yugai 时间 17/1/18. 18 | * * 邮箱 784787081@qq.com 19 | */ 20 | 21 | public interface HuYaService { 22 | String URL="http://phone.huya.com/"; 23 | 24 | @POST("api/game") 25 | Observable>> getRoomList(@Query("gameId") int gameId, @Query("page") int page); 26 | 27 | @POST("/api/liveinfo") 28 | Observable> getRoomInfo(@Query("sid") int sid, @Query("subsid") long subsid); 29 | 30 | @GET("api/game") 31 | Observable>> getClassify(); 32 | 33 | } 34 | -------------------------------------------------------------------------------- /app/src/main/java/com/mayi/douyu/api/PandaRoomService.java: -------------------------------------------------------------------------------- 1 | package com.mayi.douyu.api; 2 | 3 | import com.mayi.douyu.entity.PDDetails; 4 | import com.mayi.douyu.entity.PDResponse; 5 | 6 | import retrofit2.http.POST; 7 | import retrofit2.http.Query; 8 | import rx.Observable; 9 | 10 | /** 11 | * 作者 by yugai 时间 17/1/17. 12 | * * 邮箱 784787081@qq.com 13 | */ 14 | 15 | public interface PandaRoomService { 16 | String URL="http://www.panda.tv/"; 17 | @POST("api_room_v2") 18 | Observable> getRoomDetails(@Query("roomid")String roomId); 19 | } 20 | -------------------------------------------------------------------------------- /app/src/main/java/com/mayi/douyu/api/PandaService.java: -------------------------------------------------------------------------------- 1 | package com.mayi.douyu.api; 2 | 3 | import com.mayi.douyu.entity.PDClassify; 4 | import com.mayi.douyu.entity.PDDetails; 5 | import com.mayi.douyu.entity.PDResponse; 6 | import com.mayi.douyu.entity.PDRoom; 7 | 8 | import java.util.List; 9 | 10 | import retrofit2.http.FormUrlEncoded; 11 | import retrofit2.http.GET; 12 | import retrofit2.http.POST; 13 | import retrofit2.http.Path; 14 | import retrofit2.http.Query; 15 | import rx.Observable; 16 | 17 | /** 18 | * 作者 by yugai 时间 16/12/21. 19 | * * 邮箱 784787081@qq.com 20 | */ 21 | 22 | public interface PandaService { 23 | String URL="http://static.api.m.panda.tv/"; 24 | 25 | @POST("android_hd/alllist_.json") 26 | Observable> getRoomList(@Query("pageno")int page); 27 | 28 | @GET("android_hd/cate.json") 29 | Observable>> getClassify(); 30 | } 31 | -------------------------------------------------------------------------------- /app/src/main/java/com/mayi/douyu/base/App.java: -------------------------------------------------------------------------------- 1 | package com.mayi.douyu.base; 2 | 3 | import android.app.Application; 4 | import android.content.Context; 5 | import android.support.multidex.MultiDex; 6 | 7 | import com.mayi.douyu.ui.main.CustomErrorActivity; 8 | 9 | import cat.ereza.customactivityoncrash.CustomActivityOnCrash; 10 | 11 | /** 12 | * 作者 by yugai 时间 16/10/26. 13 | * * 邮箱 784787081@qq.com 14 | */ 15 | 16 | public class App extends Application { 17 | private static final String TAG = "App"; 18 | @Override 19 | public void onCreate() { 20 | super.onCreate(); 21 | CustomActivityOnCrash.install(this); 22 | // CustomActivityOnCrash.setErrorActivityClass(CustomErrorActivity.class); 23 | } 24 | 25 | @Override 26 | protected void attachBaseContext(Context base) { 27 | super.attachBaseContext(base); 28 | MultiDex.install(this); 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /app/src/main/java/com/mayi/douyu/base/BaseActivity.java: -------------------------------------------------------------------------------- 1 | package com.mayi.douyu.base; 2 | 3 | 4 | import android.os.Bundle; 5 | import android.support.annotation.Nullable; 6 | 7 | import com.mayi.douyu.util.AppManager; 8 | import com.trello.rxlifecycle.components.support.RxAppCompatActivity; 9 | 10 | /** 11 | * 作者 by yugai 时间 16/10/31. 12 | * * 邮箱 784787081@qq.com 13 | */ 14 | 15 | public abstract class BaseActivity extends RxAppCompatActivity { 16 | @Override 17 | protected void onCreate(@Nullable Bundle savedInstanceState) { 18 | super.onCreate(savedInstanceState); 19 | setContentView(getLayout()); 20 | AppManager.getAppManager().addActivity(this); 21 | } 22 | 23 | @Override 24 | protected void onDestroy() { 25 | super.onDestroy(); 26 | AppManager.getAppManager().removeActivity(this); 27 | } 28 | 29 | protected abstract int getLayout(); 30 | } 31 | -------------------------------------------------------------------------------- /app/src/main/java/com/mayi/douyu/entity/DYResponse.java: -------------------------------------------------------------------------------- 1 | package com.mayi.douyu.entity; 2 | 3 | /** 4 | * 作者 by yugai 时间 16/11/24. 5 | * * 邮箱 784787081@qq.com 6 | */ 7 | 8 | public class DYResponse { 9 | public static final int SUCCESS_CODE = 0; 10 | public int error; 11 | public String msg="请求失败"; 12 | public T data; 13 | 14 | public boolean success(){ 15 | return error==SUCCESS_CODE; 16 | } 17 | 18 | public int getError() { 19 | return error; 20 | } 21 | 22 | public String getMsg() { 23 | return msg; 24 | } 25 | 26 | public T getData() { 27 | return data; 28 | } 29 | 30 | @Override 31 | public String toString() { 32 | return "DYResponse{" + 33 | "error=" + error + 34 | ", msg='" + msg + '\'' + 35 | ", data=" + data + 36 | '}'; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /app/src/main/java/com/mayi/douyu/entity/HYClassify.java: -------------------------------------------------------------------------------- 1 | package com.mayi.douyu.entity; 2 | 3 | /** 4 | * 作者 by yugai 时间 17/2/5. 5 | * * 邮箱 784787081@qq.com 6 | */ 7 | 8 | public class HYClassify { 9 | 10 | /** 11 | * gameId : 1 12 | * gameName : 英雄联盟 13 | * imgUrl : http://img.huya.com/cdnimage/game/1.jpg 14 | * imgSmallUrl : http://img.huya.com/cdnimage/game/phone1.jpg 15 | * imgBigUrl : http://img.huya.com/cdnimage/game/1-S.jpg 16 | * liveCount : 680 17 | * userCount : 1442516 18 | */ 19 | 20 | private int gameId; 21 | private String gameName; 22 | private String imgUrl; 23 | private String imgSmallUrl; 24 | private String imgBigUrl; 25 | private int liveCount; 26 | private int userCount; 27 | 28 | public int getGameId() { 29 | return gameId; 30 | } 31 | 32 | public void setGameId(int gameId) { 33 | this.gameId = gameId; 34 | } 35 | 36 | public String getGameName() { 37 | return gameName; 38 | } 39 | 40 | public void setGameName(String gameName) { 41 | this.gameName = gameName; 42 | } 43 | 44 | public String getImgUrl() { 45 | return imgUrl; 46 | } 47 | 48 | public void setImgUrl(String imgUrl) { 49 | this.imgUrl = imgUrl; 50 | } 51 | 52 | public String getImgSmallUrl() { 53 | return imgSmallUrl; 54 | } 55 | 56 | public void setImgSmallUrl(String imgSmallUrl) { 57 | this.imgSmallUrl = imgSmallUrl; 58 | } 59 | 60 | public String getImgBigUrl() { 61 | return imgBigUrl; 62 | } 63 | 64 | public void setImgBigUrl(String imgBigUrl) { 65 | this.imgBigUrl = imgBigUrl; 66 | } 67 | 68 | public int getLiveCount() { 69 | return liveCount; 70 | } 71 | 72 | public void setLiveCount(int liveCount) { 73 | this.liveCount = liveCount; 74 | } 75 | 76 | public int getUserCount() { 77 | return userCount; 78 | } 79 | 80 | public void setUserCount(int userCount) { 81 | this.userCount = userCount; 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /app/src/main/java/com/mayi/douyu/entity/HYResponse.java: -------------------------------------------------------------------------------- 1 | package com.mayi.douyu.entity; 2 | 3 | /** 4 | * 作者 by yugai 时间 17/1/18. 5 | * * 邮箱 784787081@qq.com 6 | */ 7 | 8 | public class HYResponse { 9 | public static final int SUCCESS_CODE = 0; 10 | public int pageSize; 11 | public String message="请求失败"; 12 | public T data; 13 | public int code; 14 | 15 | 16 | public boolean success(){ 17 | return code==SUCCESS_CODE; 18 | } 19 | 20 | 21 | public int getCode() { 22 | return code; 23 | } 24 | 25 | public void setCode(int code) { 26 | this.code = code; 27 | } 28 | 29 | public T getData() { 30 | return data; 31 | } 32 | 33 | public void setData(T data) { 34 | this.data = data; 35 | } 36 | 37 | public int getPageSize() { 38 | return pageSize; 39 | } 40 | 41 | public void setPageSize(int pageSize) { 42 | this.pageSize = pageSize; 43 | } 44 | 45 | public String getMessage() { 46 | return message; 47 | } 48 | 49 | public void setMessage(String message) { 50 | this.message = message; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /app/src/main/java/com/mayi/douyu/entity/PDClassify.java: -------------------------------------------------------------------------------- 1 | package com.mayi.douyu.entity; 2 | 3 | /** 4 | * 作者 by yugai 时间 17/2/5. 5 | * * 邮箱 784787081@qq.com 6 | */ 7 | 8 | public class PDClassify { 9 | 10 | /** 11 | * cname : ???? 12 | * ename : lol 13 | * img : http://i9.pdim.gs/23e529ba353b33c2f70e6d60f6be4c29.jpeg 14 | * ext : 1000 15 | * status : 1 16 | * cdn_rate : 0 17 | */ 18 | 19 | private String cname; 20 | private String ename; 21 | private String img; 22 | private String ext; 23 | private String status; 24 | private String cdn_rate; 25 | 26 | public String getCname() { 27 | return cname; 28 | } 29 | 30 | public void setCname(String cname) { 31 | this.cname = cname; 32 | } 33 | 34 | public String getEname() { 35 | return ename; 36 | } 37 | 38 | public void setEname(String ename) { 39 | this.ename = ename; 40 | } 41 | 42 | public String getImg() { 43 | return img; 44 | } 45 | 46 | public void setImg(String img) { 47 | this.img = img; 48 | } 49 | 50 | public String getExt() { 51 | return ext; 52 | } 53 | 54 | public void setExt(String ext) { 55 | this.ext = ext; 56 | } 57 | 58 | public String getStatus() { 59 | return status; 60 | } 61 | 62 | public void setStatus(String status) { 63 | this.status = status; 64 | } 65 | 66 | public String getCdn_rate() { 67 | return cdn_rate; 68 | } 69 | 70 | public void setCdn_rate(String cdn_rate) { 71 | this.cdn_rate = cdn_rate; 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /app/src/main/java/com/mayi/douyu/entity/PDResponse.java: -------------------------------------------------------------------------------- 1 | package com.mayi.douyu.entity; 2 | 3 | /** 4 | * 作者 by yugai 时间 16/12/23. 5 | * * 邮箱 784787081@qq.com 6 | */ 7 | 8 | public class PDResponse { 9 | public enum DataType{ 10 | ITEMS,ROOM 11 | } 12 | public static final int SUCCESS_CODE = 0; 13 | public int errno; 14 | public String errmsg; 15 | public T data; 16 | 17 | public boolean success(){ 18 | return errno==SUCCESS_CODE; 19 | } 20 | 21 | public String getErrmsg() { 22 | return errmsg; 23 | } 24 | 25 | public void setErrmsg(String errmsg) { 26 | this.errmsg = errmsg; 27 | } 28 | 29 | public int getErrno() { 30 | return errno; 31 | } 32 | 33 | public void setErrno(int errno) { 34 | this.errno = errno; 35 | } 36 | 37 | public T getData() { 38 | return data; 39 | } 40 | 41 | public void setData(T data) { 42 | this.data = data; 43 | } 44 | 45 | @Override 46 | public String toString() { 47 | return "PDResponse{" + 48 | "errno=" + errno + 49 | ", errmsg='" + errmsg + '\'' + 50 | ", data=" + data + 51 | '}'; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /app/src/main/java/com/mayi/douyu/ijkplayer/MediaPlayerService.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 Zhang Rui 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.mayi.douyu.ijkplayer; 18 | 19 | import android.app.Service; 20 | import android.content.Context; 21 | import android.content.Intent; 22 | import android.os.IBinder; 23 | import android.support.annotation.Nullable; 24 | 25 | import tv.danmaku.ijk.media.player.IMediaPlayer; 26 | 27 | public class MediaPlayerService extends Service { 28 | private static IMediaPlayer sMediaPlayer; 29 | 30 | public static Intent newIntent(Context context) { 31 | Intent intent = new Intent(context, MediaPlayerService.class); 32 | return intent; 33 | } 34 | 35 | public static void intentToStart(Context context) { 36 | context.startService(newIntent(context)); 37 | } 38 | 39 | public static void intentToStop(Context context) { 40 | context.stopService(newIntent(context)); 41 | } 42 | 43 | @Nullable 44 | @Override 45 | public IBinder onBind(Intent intent) { 46 | return null; 47 | } 48 | 49 | public static void setMediaPlayer(IMediaPlayer mp) { 50 | if (sMediaPlayer != null && sMediaPlayer != mp) { 51 | if (sMediaPlayer.isPlaying()) 52 | sMediaPlayer.stop(); 53 | sMediaPlayer.release(); 54 | sMediaPlayer = null; 55 | } 56 | sMediaPlayer = mp; 57 | } 58 | 59 | public static IMediaPlayer getMediaPlayer() { 60 | return sMediaPlayer; 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /app/src/main/java/com/mayi/douyu/ijkplayer/widget/media/AndroidMediaController.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 Zhang Rui 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.mayi.douyu.ijkplayer.widget.media; 18 | 19 | import android.content.Context; 20 | import android.support.annotation.NonNull; 21 | import android.support.annotation.Nullable; 22 | import android.support.v7.app.ActionBar; 23 | import android.util.AttributeSet; 24 | import android.view.View; 25 | import android.widget.MediaController; 26 | 27 | import java.util.ArrayList; 28 | 29 | public class AndroidMediaController extends MediaController implements IMediaController { 30 | private ActionBar mActionBar; 31 | 32 | public AndroidMediaController(Context context, AttributeSet attrs) { 33 | super(context, attrs); 34 | initView(context); 35 | } 36 | 37 | public AndroidMediaController(Context context, boolean useFastForward) { 38 | super(context, useFastForward); 39 | initView(context); 40 | } 41 | 42 | public AndroidMediaController(Context context) { 43 | super(context); 44 | initView(context); 45 | } 46 | 47 | private void initView(Context context) { 48 | } 49 | 50 | public void setSupportActionBar(@Nullable ActionBar actionBar) { 51 | mActionBar = actionBar; 52 | if (isShowing()) { 53 | actionBar.show(); 54 | } else { 55 | actionBar.hide(); 56 | } 57 | } 58 | 59 | @Override 60 | public void show() { 61 | super.show(); 62 | if (mActionBar != null) 63 | mActionBar.show(); 64 | } 65 | 66 | @Override 67 | public void hide() { 68 | super.hide(); 69 | if (mActionBar != null) 70 | mActionBar.hide(); 71 | for (View view : mShowOnceArray) 72 | view.setVisibility(View.GONE); 73 | mShowOnceArray.clear(); 74 | } 75 | 76 | //---------- 77 | // Extends 78 | //---------- 79 | private ArrayList mShowOnceArray = new ArrayList(); 80 | 81 | public void showOnce(@NonNull View view) { 82 | mShowOnceArray.add(view); 83 | view.setVisibility(View.VISIBLE); 84 | show(); 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /app/src/main/java/com/mayi/douyu/ijkplayer/widget/media/FileMediaDataSource.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 Zhang Rui 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.mayi.douyu.ijkplayer.widget.media; 18 | 19 | import java.io.File; 20 | import java.io.IOException; 21 | import java.io.RandomAccessFile; 22 | 23 | import tv.danmaku.ijk.media.player.misc.IMediaDataSource; 24 | 25 | public class FileMediaDataSource implements IMediaDataSource { 26 | private RandomAccessFile mFile; 27 | private long mFileSize; 28 | 29 | public FileMediaDataSource(File file) throws IOException { 30 | mFile = new RandomAccessFile(file, "r"); 31 | mFileSize = mFile.length(); 32 | } 33 | 34 | @Override 35 | public int readAt(long position, byte[] buffer, int offset, int size) throws IOException { 36 | if (mFile.getFilePointer() != position) 37 | mFile.seek(position); 38 | 39 | if (size == 0) 40 | return 0; 41 | 42 | return mFile.read(buffer, 0, size); 43 | } 44 | 45 | @Override 46 | public long getSize() throws IOException { 47 | return mFileSize; 48 | } 49 | 50 | @Override 51 | public void close() throws IOException { 52 | mFileSize = 0; 53 | mFile.close(); 54 | mFile = null; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /app/src/main/java/com/mayi/douyu/ijkplayer/widget/media/IMediaController.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 Zhang Rui 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.mayi.douyu.ijkplayer.widget.media; 18 | 19 | import android.view.View; 20 | import android.widget.MediaController; 21 | 22 | public interface IMediaController { 23 | void hide(); 24 | 25 | boolean isShowing(); 26 | 27 | void setAnchorView(View view); 28 | 29 | void setEnabled(boolean enabled); 30 | 31 | void setMediaPlayer(MediaController.MediaPlayerControl player); 32 | 33 | void show(int timeout); 34 | 35 | void show(); 36 | 37 | //---------- 38 | // Extends 39 | //---------- 40 | void showOnce(View view); 41 | } 42 | -------------------------------------------------------------------------------- /app/src/main/java/com/mayi/douyu/ijkplayer/widget/media/IRenderView.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 Zhang Rui 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.mayi.douyu.ijkplayer.widget.media; 18 | 19 | import android.graphics.SurfaceTexture; 20 | import android.support.annotation.NonNull; 21 | import android.support.annotation.Nullable; 22 | import android.view.Surface; 23 | import android.view.SurfaceHolder; 24 | import android.view.View; 25 | 26 | import tv.danmaku.ijk.media.player.IMediaPlayer; 27 | 28 | public interface IRenderView { 29 | int AR_ASPECT_FIT_PARENT = 0; // without clip 30 | int AR_ASPECT_FILL_PARENT = 1; // may clip 31 | int AR_ASPECT_WRAP_CONTENT = 2; 32 | int AR_MATCH_PARENT = 3; 33 | int AR_16_9_FIT_PARENT = 4; 34 | int AR_4_3_FIT_PARENT = 5; 35 | 36 | View getView(); 37 | 38 | boolean shouldWaitForResize(); 39 | 40 | void setVideoSize(int videoWidth, int videoHeight); 41 | 42 | void setVideoSampleAspectRatio(int videoSarNum, int videoSarDen); 43 | 44 | void setVideoRotation(int degree); 45 | 46 | void setAspectRatio(int aspectRatio); 47 | 48 | void addRenderCallback(@NonNull IRenderCallback callback); 49 | 50 | void removeRenderCallback(@NonNull IRenderCallback callback); 51 | 52 | interface ISurfaceHolder { 53 | void bindToMediaPlayer(IMediaPlayer mp); 54 | 55 | @NonNull 56 | IRenderView getRenderView(); 57 | 58 | @Nullable 59 | SurfaceHolder getSurfaceHolder(); 60 | 61 | @Nullable 62 | Surface openSurface(); 63 | 64 | @Nullable 65 | SurfaceTexture getSurfaceTexture(); 66 | } 67 | 68 | interface IRenderCallback { 69 | /** 70 | * @param holder 71 | * @param width could be 0 72 | * @param height could be 0 73 | */ 74 | void onSurfaceCreated(@NonNull ISurfaceHolder holder, int width, int height); 75 | 76 | /** 77 | * @param holder 78 | * @param format could be 0 79 | * @param width 80 | * @param height 81 | */ 82 | void onSurfaceChanged(@NonNull ISurfaceHolder holder, int format, int width, int height); 83 | 84 | void onSurfaceDestroyed(@NonNull ISurfaceHolder holder); 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /app/src/main/java/com/mayi/douyu/mvpbase/BasePresenter.java: -------------------------------------------------------------------------------- 1 | package com.mayi.douyu.mvpbase; 2 | 3 | /** 4 | * 作者 by yugai 时间 16/10/31. 5 | * * 邮箱 784787081@qq.com 6 | */ 7 | 8 | public interface BasePresenter { 9 | void attachView(V view); 10 | 11 | void detachView(); 12 | } 13 | -------------------------------------------------------------------------------- /app/src/main/java/com/mayi/douyu/mvpbase/BasePresenterImpl.java: -------------------------------------------------------------------------------- 1 | package com.mayi.douyu.mvpbase; 2 | 3 | /** 4 | * 作者 by yugai 时间 16/11/1. 5 | * * 邮箱 784787081@qq.com 6 | */ 7 | 8 | public class BasePresenterImpl implements BasePresenter{ 9 | protected V mView; 10 | @Override 11 | public void attachView(V view) { 12 | mView=view; 13 | } 14 | 15 | @Override 16 | public void detachView() { 17 | mView=null; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /app/src/main/java/com/mayi/douyu/mvpbase/BaseRequestView.java: -------------------------------------------------------------------------------- 1 | package com.mayi.douyu.mvpbase; 2 | 3 | /** 4 | * 作者 by yugai 时间 16/10/31. 5 | * * 邮箱 784787081@qq.com 6 | */ 7 | 8 | public interface BaseRequestView extends BaseView{ 9 | void onRequestError(String msg); 10 | void onRequestEnd(); 11 | } 12 | -------------------------------------------------------------------------------- /app/src/main/java/com/mayi/douyu/mvpbase/BaseView.java: -------------------------------------------------------------------------------- 1 | package com.mayi.douyu.mvpbase; 2 | 3 | import android.content.Context; 4 | 5 | /** 6 | * 作者 by yugai 时间 16/10/31. 7 | * * 邮箱 784787081@qq.com 8 | */ 9 | 10 | public interface BaseView { 11 | Context getContext(); 12 | } 13 | -------------------------------------------------------------------------------- /app/src/main/java/com/mayi/douyu/mvpbase/MVPBaseActivity.java: -------------------------------------------------------------------------------- 1 | package com.mayi.douyu.mvpbase; 2 | 3 | import android.content.Context; 4 | import android.os.Bundle; 5 | import android.support.annotation.Nullable; 6 | 7 | import com.mayi.douyu.base.BaseActivity; 8 | import com.mayi.douyu.util.InstanceUtils; 9 | 10 | /** 11 | * 作者 by yugai 时间 16/10/31. 12 | * * 邮箱 784787081@qq.com 13 | */ 14 | 15 | public abstract class MVPBaseActivity> extends BaseActivity implements BaseView{ 16 | public T mPresenter; 17 | @Override 18 | protected void onCreate(@Nullable Bundle savedInstanceState) { 19 | super.onCreate(savedInstanceState); 20 | mPresenter= InstanceUtils.getInstance(this,1); 21 | mPresenter.attachView((V) this); 22 | } 23 | 24 | @Override 25 | protected void onDestroy() { 26 | super.onDestroy(); 27 | if (mPresenter!=null) 28 | mPresenter.detachView(); 29 | } 30 | 31 | @Override 32 | public Context getContext(){ 33 | return this; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /app/src/main/java/com/mayi/douyu/mvpbase/MVPBaseFragment.java: -------------------------------------------------------------------------------- 1 | package com.mayi.douyu.mvpbase; 2 | 3 | import android.content.Context; 4 | import android.os.Bundle; 5 | import android.support.annotation.Nullable; 6 | import android.support.v4.app.Fragment; 7 | import android.view.LayoutInflater; 8 | import android.view.View; 9 | import android.view.ViewGroup; 10 | import android.view.animation.Animation; 11 | import android.view.animation.AnimationUtils; 12 | 13 | import com.mayi.douyu.R; 14 | import com.mayi.douyu.util.InstanceUtils; 15 | 16 | /** 17 | * 作者 by yugai 时间 16/11/2. 18 | * * 邮箱 784787081@qq.com 19 | */ 20 | 21 | public abstract class MVPBaseFragment> extends Fragment implements BaseView{ 22 | public T mPresenter; 23 | public View root; 24 | @Override 25 | public void onCreate(@Nullable Bundle savedInstanceState) { 26 | super.onCreate(savedInstanceState); 27 | mPresenter= InstanceUtils.getInstance(this,1); 28 | mPresenter.attachView((V) this); 29 | } 30 | 31 | @Nullable 32 | @Override 33 | public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { 34 | View root=inflater.inflate(getLayout(),container,false); 35 | this.root=root; 36 | return root; 37 | } 38 | 39 | @Override 40 | public void onDestroy() { 41 | super.onDestroy(); 42 | if (mPresenter!=null) 43 | mPresenter.detachView(); 44 | } 45 | 46 | public abstract int getLayout(); 47 | @Override 48 | public Context getContext() { 49 | return super.getContext(); 50 | } 51 | 52 | 53 | /** 54 | * Called when a fragment will be displayed 55 | */ 56 | public void willBeDisplayed() { 57 | // Do what you want here, for example animate the content 58 | if ( root!= null) { 59 | Animation fadeIn = AnimationUtils.loadAnimation(getActivity(), R.anim.fade_in); 60 | root.startAnimation(fadeIn); 61 | } 62 | } 63 | 64 | /** 65 | * Called when a fragment will be hidden 66 | */ 67 | public void willBeHidden() { 68 | if (root != null) { 69 | Animation fadeOut = AnimationUtils.loadAnimation(getActivity(), R.anim.fade_out); 70 | root.startAnimation(fadeOut); 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /app/src/main/java/com/mayi/douyu/service/FloatingPlayService.java: -------------------------------------------------------------------------------- 1 | package com.mayi.douyu.service; 2 | 3 | import android.app.Service; 4 | import android.content.Intent; 5 | import android.os.Binder; 6 | import android.os.IBinder; 7 | import android.support.annotation.Nullable; 8 | import android.util.Log; 9 | import android.view.LayoutInflater; 10 | import android.view.View; 11 | 12 | import com.mayi.douyu.R; 13 | import com.mayi.douyu.api.ApiManager; 14 | import com.mayi.douyu.entity.DYDetails; 15 | import com.mayi.douyu.widget.FloatWindow; 16 | 17 | import rx.functions.Action1; 18 | 19 | /** 20 | * 作者 by yugai 时间 17/1/24. 21 | * * 邮箱 784787081@qq.com 22 | */ 23 | 24 | public class FloatingPlayService extends Service{ 25 | private static final String TAG = "FloatingPlayService"; 26 | FloatWindow mFloatWindow; 27 | MyBinder mBinder; 28 | private String roomId; 29 | @Nullable 30 | @Override 31 | public IBinder onBind(Intent intent) { 32 | return mBinder; 33 | } 34 | 35 | @Override 36 | public void onCreate() { 37 | super.onCreate(); 38 | mBinder=new MyBinder(); 39 | mFloatWindow=new FloatWindow(this); 40 | View floatView= LayoutInflater.from(this).inflate(R.layout.window_float,null); 41 | mFloatWindow.setContentView(floatView); 42 | } 43 | 44 | @Override 45 | public int onStartCommand(Intent intent, int flags, int startId) { 46 | return super.onStartCommand(intent, flags, startId); 47 | } 48 | 49 | 50 | @Override 51 | public void onDestroy() { 52 | super.onDestroy(); 53 | } 54 | 55 | public void show(){ 56 | mFloatWindow.show(); 57 | getVideoUrl(); 58 | 59 | } 60 | public void dismiss(){ 61 | mFloatWindow.dismiss(); 62 | mFloatWindow.stop(); 63 | } 64 | 65 | public class MyBinder extends Binder { 66 | public void startPlay(String roomId){ 67 | FloatingPlayService.this.roomId=roomId; 68 | show(); 69 | } 70 | public void closePlay(){ 71 | dismiss(); 72 | } 73 | } 74 | 75 | /** 76 | * 获取直播url 77 | */ 78 | private void getVideoUrl() { 79 | ApiManager.getInstance().getRoomUrl(roomId) 80 | .subscribe(new Action1() { 81 | @Override 82 | public void call(DYDetails dyDetails) { 83 | mFloatWindow.start(dyDetails.getRtmp_url() + "/" + dyDetails.getRtmp_live()); 84 | } 85 | }); 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /app/src/main/java/com/mayi/douyu/ui/about/AboutActivity.java: -------------------------------------------------------------------------------- 1 | package com.mayi.douyu.ui.about; 2 | 3 | import android.os.Bundle; 4 | import android.support.v4.view.ViewPager; 5 | import android.transition.TransitionInflater; 6 | 7 | import com.mayi.douyu.R; 8 | import com.mayi.douyu.base.BaseActivity; 9 | import com.mayi.douyu.widget.ElasticDragDismissFrameLayout; 10 | import com.mayi.douyu.widget.InkPageIndicator; 11 | 12 | import butterknife.Bind; 13 | import butterknife.ButterKnife; 14 | 15 | /** 16 | * 作者 by yugai 时间 17/2/6. 17 | * * 邮箱 784787081@qq.com 18 | */ 19 | 20 | public class AboutActivity extends BaseActivity { 21 | @Bind(R.id.pager) 22 | ViewPager mPager; 23 | @Bind(R.id.indicator) 24 | InkPageIndicator mIndicator; 25 | @Bind(R.id.draggable_frame) 26 | ElasticDragDismissFrameLayout mDraggableFrame; 27 | 28 | @Override 29 | protected int getLayout() { 30 | return R.layout.activity_about; 31 | } 32 | 33 | @Override 34 | protected void onCreate(Bundle savedInstanceState) { 35 | super.onCreate(savedInstanceState); 36 | // TODO: add setContentView(...) invocation 37 | ButterKnife.bind(this); 38 | mPager.setAdapter(new AboutAdapter(AboutActivity.this)); 39 | mPager.setPageMargin(getResources().getDimensionPixelSize(R.dimen.spacing_normal)); 40 | mIndicator.setViewPager(mPager); 41 | 42 | mDraggableFrame.addListener( 43 | new ElasticDragDismissFrameLayout.SystemChromeFader(this) { 44 | @Override 45 | public void onDragDismissed() { 46 | // if we drag dismiss downward then the default reversal of the enter 47 | // transition would slide content upward which looks weird. So reverse it. 48 | if (mDraggableFrame.getTranslationY() > 0) { 49 | getWindow().setReturnTransition( 50 | TransitionInflater.from(AboutActivity.this) 51 | .inflateTransition(R.transition.about_return_downward)); 52 | } 53 | finishAfterTransition(); 54 | } 55 | }); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /app/src/main/java/com/mayi/douyu/ui/about/AboutAdapter.java: -------------------------------------------------------------------------------- 1 | package com.mayi.douyu.ui.about; 2 | 3 | import android.content.Context; 4 | import android.support.v4.view.PagerAdapter; 5 | import android.support.v7.widget.LinearLayoutManager; 6 | import android.support.v7.widget.RecyclerView; 7 | import android.text.Layout; 8 | import android.text.SpannableString; 9 | import android.text.Spanned; 10 | import android.text.TextUtils; 11 | import android.text.style.AlignmentSpan; 12 | import android.view.LayoutInflater; 13 | import android.view.View; 14 | import android.view.ViewGroup; 15 | 16 | import com.mayi.douyu.R; 17 | 18 | import java.security.InvalidParameterException; 19 | 20 | import butterknife.ButterKnife; 21 | 22 | /** 23 | * 作者 by yugai 时间 17/2/6. 24 | * * 邮箱 784787081@qq.com 25 | */ 26 | 27 | public class AboutAdapter extends PagerAdapter{ 28 | Context mContext; 29 | View info,libs; 30 | 31 | private LayoutInflater layoutInflater; 32 | public AboutAdapter(Context context) { 33 | mContext = context; 34 | layoutInflater = LayoutInflater.from(mContext); 35 | } 36 | 37 | @Override 38 | public int getCount() { 39 | return 2; 40 | } 41 | 42 | @Override 43 | public Object instantiateItem(ViewGroup collection, int position) { 44 | View layout = getPage(position, collection); 45 | collection.addView(layout); 46 | return layout; 47 | } 48 | 49 | @Override 50 | public boolean isViewFromObject(View view, Object object) { 51 | return view == object; 52 | } 53 | 54 | @Override 55 | public void destroyItem(ViewGroup collection, int position, Object view) { 56 | collection.removeView((View) view); 57 | } 58 | 59 | private View getPage(int position, ViewGroup parent) { 60 | switch (position) { 61 | case 0: 62 | if (info==null){ 63 | info=layoutInflater.inflate(R.layout.layout_about_info,parent,false); 64 | } 65 | return info; 66 | case 1: 67 | if (libs==null){ 68 | libs=layoutInflater.inflate(R.layout.layout_about_support,parent,false); 69 | RecyclerView mRvLibs= (RecyclerView) libs.findViewById(R.id.rv_libs); 70 | mRvLibs.setLayoutManager(new LinearLayoutManager(mContext)); 71 | mRvLibs.setAdapter(new LibsAdapter(mContext)); 72 | } 73 | return libs; 74 | } 75 | throw new InvalidParameterException(); 76 | } 77 | 78 | 79 | } 80 | -------------------------------------------------------------------------------- /app/src/main/java/com/mayi/douyu/ui/main/MainFragmentAdapter.java: -------------------------------------------------------------------------------- 1 | package com.mayi.douyu.ui.main; 2 | 3 | import android.support.v4.app.Fragment; 4 | import android.support.v4.app.FragmentManager; 5 | import android.support.v4.app.FragmentPagerAdapter; 6 | import android.view.ViewGroup; 7 | 8 | import com.mayi.douyu.mvpbase.MVPBaseFragment; 9 | 10 | import java.util.ArrayList; 11 | 12 | /** 13 | * 作者 by yugai 时间 16/11/3. 14 | * * 邮箱 784787081@qq.com 15 | */ 16 | 17 | public class MainFragmentAdapter extends FragmentPagerAdapter { 18 | 19 | private ArrayList fragments = new ArrayList<>(); 20 | private MVPBaseFragment currentFragment; 21 | 22 | public MainFragmentAdapter(FragmentManager fm) { 23 | super(fm); 24 | fragments.clear(); 25 | fragments.add(com.mayi.douyu.ui.main.douyu.LiveFragment.newInstance()); 26 | fragments.add(com.mayi.douyu.ui.main.panda.LiveFragment.newInstance()); 27 | fragments.add(com.mayi.douyu.ui.main.huya.LiveFragment.newInstance()); 28 | } 29 | 30 | @Override 31 | public Fragment getItem(int position) { 32 | return fragments.get(position); 33 | } 34 | 35 | @Override 36 | public int getCount() { 37 | return fragments.size(); 38 | } 39 | 40 | @Override 41 | public void setPrimaryItem(ViewGroup container, int position, Object object) { 42 | if (getCurrentFragment() != object) { 43 | currentFragment = ((MVPBaseFragment) object); 44 | } 45 | super.setPrimaryItem(container, position, object); 46 | } 47 | 48 | /** 49 | * Get the current fragment 50 | */ 51 | public MVPBaseFragment getCurrentFragment() { 52 | return currentFragment; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /app/src/main/java/com/mayi/douyu/ui/main/SplashActivity.java: -------------------------------------------------------------------------------- 1 | package com.mayi.douyu.ui.main; 2 | 3 | import android.os.Bundle; 4 | import android.support.annotation.Nullable; 5 | import android.support.v7.app.AppCompatActivity; 6 | import android.view.KeyEvent; 7 | import android.view.WindowManager; 8 | 9 | import com.mayi.douyu.R; 10 | import com.mayi.douyu.base.BaseActivity; 11 | 12 | 13 | /** 14 | * 作者 by yugai 时间 16/10/24. 15 | * * 邮箱 784787081@qq.com 16 | */ 17 | 18 | public class SplashActivity extends BaseActivity { 19 | @Override 20 | protected void onCreate(@Nullable Bundle savedInstanceState) { 21 | super.onCreate(savedInstanceState); 22 | getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, 23 | WindowManager.LayoutParams.FLAG_FULLSCREEN); 24 | } 25 | 26 | @Override 27 | protected int getLayout() { 28 | return R.layout.activity_splash; 29 | } 30 | 31 | /** 32 | * 屏蔽物理返回按钮 33 | * @param keyCode 34 | * @param event 35 | * @return 36 | */ 37 | @Override 38 | public boolean onKeyDown(int keyCode, KeyEvent event) { 39 | if (keyCode == KeyEvent.KEYCODE_BACK) { 40 | return true; 41 | } 42 | return super.onKeyDown(keyCode, event); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /app/src/main/java/com/mayi/douyu/ui/main/douyu/LiveAdapter.java: -------------------------------------------------------------------------------- 1 | package com.mayi.douyu.ui.main.douyu; 2 | 3 | import android.app.Activity; 4 | import android.support.v7.widget.RecyclerView; 5 | import android.view.LayoutInflater; 6 | import android.view.View; 7 | import android.view.ViewGroup; 8 | import android.widget.TextView; 9 | 10 | import com.bumptech.glide.Glide; 11 | import com.mayi.douyu.R; 12 | import com.mayi.douyu.base.BaseRecyclerAdapter; 13 | import com.mayi.douyu.entity.DYRoom; 14 | import com.mayi.douyu.widget.CustomSizeImageView; 15 | 16 | import butterknife.Bind; 17 | import butterknife.ButterKnife; 18 | import de.hdodenhof.circleimageview.CircleImageView; 19 | 20 | /** 21 | * 作者 by yugai 时间 16/11/3. 22 | * * 邮箱 784787081@qq.com 23 | */ 24 | 25 | public class LiveAdapter extends BaseRecyclerAdapter { 26 | Activity mContext; 27 | OnItemClickListener mOnItemClickListener; 28 | 29 | 30 | public LiveAdapter(Activity context, OnItemClickListener onItemClickListener) { 31 | this.mContext = context; 32 | this.mOnItemClickListener = onItemClickListener; 33 | } 34 | 35 | @Override 36 | public void onBindItemViewHolder(RecyclerView.ViewHolder holder, final DYRoom data, final int position) { 37 | final Holder roomHolder = (Holder) holder; 38 | Glide.with(mContext).load(data.getVertical_src()).into(roomHolder.mIvRoomSrc); 39 | Glide.with(mContext).load(data.getAvatar()).into(roomHolder.mAvatar); 40 | roomHolder.mNickname.setText(data.getNickname()); 41 | roomHolder.mTvRoomTitle.setText(data.getRoom_name()); 42 | roomHolder.itemView.setOnClickListener(new View.OnClickListener() { 43 | @Override 44 | public void onClick(View view) { 45 | mOnItemClickListener.onItemClick(data.getRoom_id()); 46 | } 47 | }); 48 | } 49 | 50 | @Override 51 | public RecyclerView.ViewHolder onCreateItemViewHolder(ViewGroup parent, int viewType) { 52 | return new Holder(LayoutInflater.from(mContext).inflate(R.layout.item_live, parent, false)); 53 | } 54 | 55 | static class Holder extends RecyclerView.ViewHolder { 56 | @Bind(R.id.avatar) 57 | CircleImageView mAvatar; 58 | @Bind(R.id.nickname) 59 | TextView mNickname; 60 | @Bind(R.id.tv_room_title) 61 | TextView mTvRoomTitle; 62 | @Bind(R.id.iv_room_src) 63 | CustomSizeImageView mIvRoomSrc; 64 | 65 | public Holder(View itemView) { 66 | super(itemView); 67 | ButterKnife.bind(this, itemView); 68 | } 69 | } 70 | 71 | public interface OnItemClickListener { 72 | void onItemClick(String roomId); 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /app/src/main/java/com/mayi/douyu/ui/main/douyu/LiveContract.java: -------------------------------------------------------------------------------- 1 | package com.mayi.douyu.ui.main.douyu; 2 | 3 | 4 | import com.mayi.douyu.entity.DYRoom; 5 | import com.mayi.douyu.mvpbase.BasePresenter; 6 | import com.mayi.douyu.mvpbase.BaseRequestView; 7 | 8 | import java.util.List; 9 | 10 | /** 11 | * 作者 by yugai 时间 16/11/3. 12 | * * 邮箱 784787081@qq.com 13 | */ 14 | 15 | public class LiveContract { 16 | interface View extends BaseRequestView{ 17 | void onRequestData(List DYRooms); 18 | void onRefreshData(List DYRooms); 19 | } 20 | interface Presenter extends BasePresenter { 21 | void getListData(boolean forceUpdate); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /app/src/main/java/com/mayi/douyu/ui/main/douyu/LivePresenter.java: -------------------------------------------------------------------------------- 1 | package com.mayi.douyu.ui.main.douyu; 2 | 3 | import android.util.Log; 4 | 5 | import com.mayi.douyu.api.ApiManager; 6 | import com.mayi.douyu.api.DouyuService; 7 | import com.mayi.douyu.entity.DYRoom; 8 | import com.mayi.douyu.mvpbase.BasePresenterImpl; 9 | 10 | import java.util.List; 11 | 12 | import rx.Subscriber; 13 | 14 | /** 15 | * 作者 by yugai 时间 16/11/3. 16 | * * 邮箱 784787081@qq.com 17 | */ 18 | 19 | public class LivePresenter extends BasePresenterImpl implements LiveContract.Presenter{ 20 | private static final String TAG = "LivePresenter"; 21 | private int page=0; 22 | 23 | @Override 24 | public void getListData(final boolean forceUpdate) { 25 | if (forceUpdate){ 26 | page=0; 27 | }else{ 28 | page+= DouyuService.PAGE_SIZE; 29 | } 30 | Log.i(TAG, "getListData: "+page); 31 | ApiManager.getInstance().getDYList(page). 32 | subscribe(new Subscriber>() { 33 | @Override 34 | public void onCompleted() { 35 | Log.i(TAG, "onCompleted: "); 36 | mView.onRequestEnd(); 37 | } 38 | 39 | @Override 40 | public void onError(Throwable e) { 41 | Log.i(TAG, "onError: "); 42 | mView.onRequestError(e.getMessage()); 43 | } 44 | 45 | @Override 46 | public void onNext(List DYRooms) { 47 | for (DYRoom DYRoom : DYRooms) { 48 | Log.i(TAG, "onNext: "+ DYRoom); 49 | } 50 | if (forceUpdate){ 51 | mView.onRefreshData(DYRooms); 52 | }else{ 53 | mView.onRequestData(DYRooms); 54 | } 55 | } 56 | }) ; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /app/src/main/java/com/mayi/douyu/ui/main/huya/LiveAdapter.java: -------------------------------------------------------------------------------- 1 | package com.mayi.douyu.ui.main.huya; 2 | 3 | import android.content.Context; 4 | import android.support.v7.widget.RecyclerView; 5 | import android.util.Log; 6 | import android.view.LayoutInflater; 7 | import android.view.View; 8 | import android.view.ViewGroup; 9 | 10 | import com.bumptech.glide.Glide; 11 | import com.mayi.douyu.R; 12 | import com.mayi.douyu.base.BaseRecyclerAdapter; 13 | import com.mayi.douyu.entity.HYRoom; 14 | import com.mayi.douyu.widget.CustomSizeImageView; 15 | 16 | import butterknife.Bind; 17 | import butterknife.ButterKnife; 18 | 19 | /** 20 | * 作者 by yugai 时间 17/1/18. 21 | * * 邮箱 784787081@qq.com 22 | */ 23 | 24 | public class LiveAdapter extends BaseRecyclerAdapter{ 25 | private static final String TAG = "LiveAdapter"; 26 | Context mContext; 27 | OnItemClickListener mOnItemClickListener; 28 | 29 | public LiveAdapter(Context context, OnItemClickListener onItemClickListener) { 30 | mContext = context; 31 | mOnItemClickListener = onItemClickListener; 32 | } 33 | 34 | @Override 35 | public void onBindItemViewHolder(RecyclerView.ViewHolder holder, final HYRoom data, int position) { 36 | Holder roomHolder= (Holder) holder; 37 | Log.i(TAG, "onBindItemViewHolder: "+data); 38 | Glide.with(mContext).load(data.getSnapshot()).into(roomHolder.mIvRoomSrc); 39 | roomHolder.itemView.setOnClickListener(new View.OnClickListener() { 40 | @Override 41 | public void onClick(View view) { 42 | if (mOnItemClickListener!=null)mOnItemClickListener.onItemClick(data.getSid(),data.getSubSid()); 43 | } 44 | }); 45 | } 46 | 47 | @Override 48 | public RecyclerView.ViewHolder onCreateItemViewHolder(ViewGroup parent, int viewType) { 49 | return new Holder(LayoutInflater.from(mContext).inflate(R.layout.item_live, parent, false)); 50 | } 51 | 52 | static class Holder extends RecyclerView.ViewHolder{ 53 | @Bind(R.id.iv_room_src) 54 | CustomSizeImageView mIvRoomSrc; 55 | public Holder(View itemView) { 56 | super(itemView); 57 | ButterKnife.bind(this, itemView); 58 | } 59 | } 60 | public interface OnItemClickListener { 61 | void onItemClick(int sid,long subsid); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /app/src/main/java/com/mayi/douyu/ui/main/huya/LiveContract.java: -------------------------------------------------------------------------------- 1 | package com.mayi.douyu.ui.main.huya; 2 | 3 | import com.mayi.douyu.entity.DYRoom; 4 | import com.mayi.douyu.entity.HYRoom; 5 | import com.mayi.douyu.mvpbase.BasePresenter; 6 | import com.mayi.douyu.mvpbase.BaseRequestView; 7 | 8 | import java.util.List; 9 | 10 | /** 11 | * 作者 by yugai 时间 17/1/18. 12 | * * 邮箱 784787081@qq.com 13 | */ 14 | 15 | public class LiveContract { 16 | interface View extends BaseRequestView { 17 | void onRequestData(List rooms); 18 | void onRefreshData(List rooms); 19 | } 20 | interface Presenter extends BasePresenter { 21 | void getListData(boolean forceUpdate); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /app/src/main/java/com/mayi/douyu/ui/main/huya/LivePresenter.java: -------------------------------------------------------------------------------- 1 | package com.mayi.douyu.ui.main.huya; 2 | 3 | import com.mayi.douyu.api.ApiManager; 4 | import com.mayi.douyu.entity.HYRoom; 5 | import com.mayi.douyu.mvpbase.BasePresenterImpl; 6 | 7 | import java.util.List; 8 | 9 | import rx.Subscriber; 10 | 11 | /** 12 | * 作者 by yugai 时间 17/1/18. 13 | * * 邮箱 784787081@qq.com 14 | */ 15 | 16 | public class LivePresenter extends BasePresenterImpl implements LiveContract.Presenter { 17 | int page = 0; 18 | int gameId = 1; 19 | 20 | @Override 21 | public void getListData(final boolean forceUpdate) { 22 | if (forceUpdate) { 23 | page = 0; 24 | } else { 25 | page++; 26 | } 27 | ApiManager.getInstance().getHYList(gameId, page) 28 | .subscribe(new Subscriber>() { 29 | @Override 30 | public void onCompleted() { 31 | mView.onRequestEnd(); 32 | } 33 | 34 | @Override 35 | public void onError(Throwable e) { 36 | mView.onRequestError(e.getMessage()); 37 | } 38 | 39 | @Override 40 | public void onNext(List rooms) { 41 | if (forceUpdate) { 42 | mView.onRefreshData(rooms); 43 | } else { 44 | mView.onRequestData(rooms); 45 | } 46 | } 47 | }); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /app/src/main/java/com/mayi/douyu/ui/main/panda/LiveAdapter.java: -------------------------------------------------------------------------------- 1 | package com.mayi.douyu.ui.main.panda; 2 | 3 | import android.content.Context; 4 | import android.support.v7.widget.RecyclerView; 5 | import android.view.LayoutInflater; 6 | import android.view.View; 7 | import android.view.ViewGroup; 8 | 9 | import com.bumptech.glide.Glide; 10 | import com.mayi.douyu.R; 11 | import com.mayi.douyu.base.BaseRecyclerAdapter; 12 | import com.mayi.douyu.entity.PDRoom; 13 | import com.mayi.douyu.widget.CustomSizeImageView; 14 | 15 | import butterknife.Bind; 16 | import butterknife.ButterKnife; 17 | 18 | /** 19 | * 作者 by yugai 时间 16/11/3. 20 | * * 邮箱 784787081@qq.com 21 | */ 22 | 23 | public class LiveAdapter extends BaseRecyclerAdapter { 24 | Context mContext; 25 | OnItemClickListener mOnItemClickListener; 26 | 27 | public LiveAdapter(Context context,OnItemClickListener onItemClickListener) { 28 | this.mContext = context; 29 | this.mOnItemClickListener=onItemClickListener; 30 | } 31 | 32 | @Override 33 | public void onBindItemViewHolder(RecyclerView.ViewHolder holder, final PDRoom.Room data, final int position) { 34 | Holder roomHolder= (Holder) holder; 35 | Glide.with(mContext).load(data.getPictures().getImg()).into(roomHolder.mIvRoomSrc); 36 | roomHolder.itemView.setOnClickListener(new View.OnClickListener() { 37 | @Override 38 | public void onClick(View view) { 39 | mOnItemClickListener.onItemClick(data.getId()); 40 | } 41 | }); 42 | } 43 | 44 | @Override 45 | public RecyclerView.ViewHolder onCreateItemViewHolder(ViewGroup parent, int viewType) { 46 | return new Holder(LayoutInflater.from(mContext).inflate(R.layout.item_live, parent, false)); 47 | } 48 | 49 | static class Holder extends RecyclerView.ViewHolder { 50 | @Bind(R.id.iv_room_src) 51 | CustomSizeImageView mIvRoomSrc; 52 | public Holder(View itemView) { 53 | super(itemView); 54 | ButterKnife.bind(this, itemView); 55 | } 56 | } 57 | 58 | public interface OnItemClickListener { 59 | void onItemClick(String roomId); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /app/src/main/java/com/mayi/douyu/ui/main/panda/LiveContract.java: -------------------------------------------------------------------------------- 1 | package com.mayi.douyu.ui.main.panda; 2 | 3 | 4 | import com.mayi.douyu.entity.PDRoom; 5 | import com.mayi.douyu.mvpbase.BasePresenter; 6 | import com.mayi.douyu.mvpbase.BaseRequestView; 7 | 8 | import java.util.List; 9 | 10 | /** 11 | * 作者 by yugai 时间 16/11/3. 12 | * * 邮箱 784787081@qq.com 13 | */ 14 | 15 | public class LiveContract { 16 | interface View extends BaseRequestView{ 17 | void onRequestData(List pdRooms); 18 | void onRefreshData(List pdRooms); 19 | } 20 | interface Presenter extends BasePresenter { 21 | void getListData(boolean forceUpdate); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /app/src/main/java/com/mayi/douyu/ui/main/panda/LivePresenter.java: -------------------------------------------------------------------------------- 1 | package com.mayi.douyu.ui.main.panda; 2 | 3 | import android.util.Log; 4 | 5 | import com.mayi.douyu.api.ApiManager; 6 | import com.mayi.douyu.api.DouyuService; 7 | import com.mayi.douyu.entity.PDRoom; 8 | import com.mayi.douyu.mvpbase.BasePresenterImpl; 9 | 10 | import java.util.List; 11 | 12 | import rx.Subscriber; 13 | 14 | /** 15 | * 作者 by yugai 时间 16/11/3. 16 | * * 邮箱 784787081@qq.com 17 | */ 18 | 19 | public class LivePresenter extends BasePresenterImpl implements LiveContract.Presenter { 20 | private static final String TAG = "LivePresenter"; 21 | int page = 0; 22 | 23 | @Override 24 | public void getListData(final boolean forceUpdate) { 25 | if (forceUpdate) { 26 | page = 0; 27 | } else { 28 | page++; 29 | } 30 | ApiManager.getInstance().getPDList(page) 31 | .subscribe(new Subscriber() { 32 | @Override 33 | public void onCompleted() { 34 | mView.onRequestEnd(); 35 | } 36 | 37 | @Override 38 | public void onError(Throwable e) { 39 | mView.onRequestError(e.getMessage()); 40 | } 41 | 42 | @Override 43 | public void onNext(PDRoom pdRoom) { 44 | if (forceUpdate){ 45 | mView.onRefreshData(pdRoom.getItems()); 46 | }else{ 47 | mView.onRequestData(pdRoom.getItems()); 48 | } 49 | } 50 | }); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /app/src/main/java/com/mayi/douyu/ui/search/SearchAdapter.java: -------------------------------------------------------------------------------- 1 | package com.mayi.douyu.ui.search; 2 | 3 | import android.content.Context; 4 | import android.support.v7.widget.RecyclerView; 5 | import android.view.LayoutInflater; 6 | import android.view.View; 7 | import android.view.ViewGroup; 8 | import android.widget.TextView; 9 | 10 | import com.bumptech.glide.Glide; 11 | import com.mayi.douyu.R; 12 | import com.mayi.douyu.base.BaseRecyclerAdapter; 13 | import com.mayi.douyu.entity.DYSearchDetails; 14 | import com.mayi.douyu.ui.main.douyu.LiveAdapter; 15 | import com.mayi.douyu.widget.CustomSizeImageView; 16 | 17 | import butterknife.Bind; 18 | import butterknife.ButterKnife; 19 | import de.hdodenhof.circleimageview.CircleImageView; 20 | 21 | /** 22 | * 作者 by yugai 时间 17/2/5. 23 | * * 邮箱 784787081@qq.com 24 | */ 25 | 26 | public class SearchAdapter extends BaseRecyclerAdapter { 27 | Context mContext; 28 | LiveAdapter.OnItemClickListener mOnItemClickListener; 29 | 30 | public SearchAdapter(Context context, LiveAdapter.OnItemClickListener onItemClickListener) { 31 | mContext = context; 32 | mOnItemClickListener = onItemClickListener; 33 | } 34 | 35 | @Override 36 | public void onBindItemViewHolder(RecyclerView.ViewHolder holder, final DYSearchDetails.RoomEntity data, int position) { 37 | final Holder roomHolder = (Holder) holder; 38 | Glide.with(mContext).load(data.getVertical_src()).into(roomHolder.mIvRoomSrc); 39 | Glide.with(mContext).load(data.getAvatar()).into(roomHolder.mAvatar); 40 | roomHolder.mNickname.setText(data.getNickname()); 41 | roomHolder.mTvRoomTitle.setText(data.getRoom_name()); 42 | roomHolder.itemView.setOnClickListener(new View.OnClickListener() { 43 | @Override 44 | public void onClick(View view) { 45 | mOnItemClickListener.onItemClick(data.getRoom_id()); 46 | } 47 | }); 48 | } 49 | 50 | @Override 51 | public RecyclerView.ViewHolder onCreateItemViewHolder(ViewGroup parent, int viewType) { 52 | return new Holder(LayoutInflater.from(mContext).inflate(R.layout.item_live, parent, false)); 53 | } 54 | 55 | static class Holder extends RecyclerView.ViewHolder { 56 | @Bind(R.id.avatar) 57 | CircleImageView mAvatar; 58 | @Bind(R.id.nickname) 59 | TextView mNickname; 60 | @Bind(R.id.tv_room_title) 61 | TextView mTvRoomTitle; 62 | @Bind(R.id.iv_room_src) 63 | CustomSizeImageView mIvRoomSrc; 64 | public Holder(View itemView) { 65 | super(itemView); 66 | ButterKnife.bind(this,itemView); 67 | } 68 | } 69 | public interface OnItemClickListener { 70 | void onItemClick(String roomId); 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /app/src/main/java/com/mayi/douyu/ui/search/SearchContract.java: -------------------------------------------------------------------------------- 1 | package com.mayi.douyu.ui.search; 2 | 3 | import com.mayi.douyu.entity.DYSearchDetails; 4 | import com.mayi.douyu.mvpbase.BasePresenter; 5 | import com.mayi.douyu.mvpbase.BaseRequestView; 6 | import com.mayi.douyu.mvpbase.BaseView; 7 | 8 | import java.util.List; 9 | 10 | /** 11 | * 作者 by yugai 时间 17/1/19. 12 | * * 邮箱 784787081@qq.com 13 | */ 14 | 15 | public class SearchContract { 16 | interface View extends BaseRequestView{ 17 | void onSearchRequest(List roomEntities); 18 | } 19 | interface Presenter extends BasePresenter{ 20 | void search(String text); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /app/src/main/java/com/mayi/douyu/ui/search/SearchPresenter.java: -------------------------------------------------------------------------------- 1 | package com.mayi.douyu.ui.search; 2 | 3 | import com.mayi.douyu.api.ApiManager; 4 | import com.mayi.douyu.entity.DYSearchDetails; 5 | import com.mayi.douyu.mvpbase.BasePresenterImpl; 6 | 7 | import rx.Subscriber; 8 | 9 | /** 10 | * 作者 by yugai 时间 17/1/19. 11 | * * 邮箱 784787081@qq.com 12 | */ 13 | 14 | public class SearchPresenter extends BasePresenterImpl implements SearchContract.Presenter{ 15 | 16 | @Override 17 | public void search(String text) { 18 | ApiManager.getInstance().search(text) 19 | .subscribe(new Subscriber() { 20 | @Override 21 | public void onCompleted() { 22 | mView.onRequestEnd(); 23 | } 24 | 25 | @Override 26 | public void onError(Throwable e) { 27 | mView.onRequestError(e.getMessage()); 28 | } 29 | 30 | @Override 31 | public void onNext(DYSearchDetails dySearchDetails) { 32 | mView.onSearchRequest(dySearchDetails.getRoom()); 33 | } 34 | }); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /app/src/main/java/com/mayi/douyu/ui/test/LoginActivity.java: -------------------------------------------------------------------------------- 1 | package com.mayi.douyu.ui.test; 2 | 3 | import android.os.Bundle; 4 | import android.widget.Button; 5 | import android.widget.EditText; 6 | import android.widget.Toast; 7 | 8 | import com.mayi.douyu.R; 9 | import com.mayi.douyu.mvpbase.MVPBaseActivity; 10 | 11 | import butterknife.Bind; 12 | import butterknife.ButterKnife; 13 | import butterknife.OnClick; 14 | 15 | /** 16 | * 作者 by yugai 时间 16/11/1. 17 | * * 邮箱 784787081@qq.com 18 | */ 19 | 20 | public class LoginActivity extends MVPBaseActivity implements LoginContract.View { 21 | @Bind(R.id.et_name) 22 | EditText mEtName; 23 | @Bind(R.id.et_password) 24 | EditText mEtPassword; 25 | @Bind(R.id.bt_login) 26 | Button mBtLogin; 27 | 28 | 29 | @Override 30 | protected int getLayout() { 31 | return R.layout.activity_login; 32 | } 33 | 34 | @Override 35 | protected void onCreate(Bundle savedInstanceState) { 36 | super.onCreate(savedInstanceState); 37 | // TODO: add setContentView(...) invocation 38 | ButterKnife.bind(this); 39 | } 40 | 41 | @Override 42 | public void onLoginSuccess() { 43 | Toast.makeText(this, "登陆成功", Toast.LENGTH_SHORT).show(); 44 | } 45 | 46 | @Override 47 | public void onLoginFail() { 48 | Toast.makeText(this, "登陆失败", Toast.LENGTH_SHORT).show(); 49 | } 50 | 51 | @OnClick(R.id.bt_login) 52 | public void onClick() { 53 | mPresenter.login(this,mEtName.getText().toString(),mEtPassword.getText().toString()); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /app/src/main/java/com/mayi/douyu/ui/test/LoginContract.java: -------------------------------------------------------------------------------- 1 | package com.mayi.douyu.ui.test; 2 | 3 | import android.content.Context; 4 | 5 | import com.mayi.douyu.mvpbase.BasePresenter; 6 | import com.mayi.douyu.mvpbase.BaseView; 7 | 8 | /** 9 | * 作者 by yugai 时间 16/11/1. 10 | * * 邮箱 784787081@qq.com 11 | */ 12 | 13 | public class LoginContract { 14 | interface View extends BaseView { 15 | void onLoginSuccess(); 16 | void onLoginFail(); 17 | } 18 | 19 | interface Presenter extends BasePresenter { 20 | void login(Context context, String userName, String loginToken); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /app/src/main/java/com/mayi/douyu/ui/test/LoginPresenter.java: -------------------------------------------------------------------------------- 1 | package com.mayi.douyu.ui.test; 2 | 3 | import android.content.Context; 4 | 5 | import com.mayi.douyu.mvpbase.BasePresenterImpl; 6 | import com.mayi.douyu.util.rx.RxBus; 7 | 8 | /** 9 | * 作者 by yugai 时间 16/11/1. 10 | * * 邮箱 784787081@qq.com 11 | */ 12 | 13 | public class LoginPresenter extends BasePresenterImpl implements LoginContract.Presenter{ 14 | @Override 15 | public void login(Context context, String userName, String password) { 16 | if (userName.equals("784787081")&&password.equals("123456")){ 17 | mView.onLoginSuccess(); 18 | }else{ 19 | mView.onLoginFail(); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /app/src/main/java/com/mayi/douyu/ui/video/full/FullVideoContract.java: -------------------------------------------------------------------------------- 1 | package com.mayi.douyu.ui.video.full; 2 | 3 | import com.mayi.douyu.mvpbase.BasePresenter; 4 | import com.mayi.douyu.mvpbase.BaseRequestView; 5 | import com.yugai.danmu.message.ChatMsg; 6 | 7 | /** 8 | * 作者 by yugai 时间 16/11/29. 9 | * * 邮箱 784787081@qq.com 10 | */ 11 | 12 | public class FullVideoContract { 13 | interface View extends BaseRequestView{ 14 | void onRequestData(String url); 15 | void receiveMessage(ChatMsg message); 16 | } 17 | interface Presenter extends BasePresenter{ 18 | void getDouyuVideo(String roomId); 19 | void getPandaVideo(String roomId); 20 | void getHuYaVideo(int sid,long subsid); 21 | void connectDanMu(String roomId); 22 | void closeDanMu(); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /app/src/main/java/com/mayi/douyu/ui/video/half/HalfVideoActivity.java: -------------------------------------------------------------------------------- 1 | package com.mayi.douyu.ui.video.half; 2 | 3 | import android.content.Context; 4 | import android.content.Intent; 5 | 6 | import com.mayi.douyu.R; 7 | import com.mayi.douyu.mvpbase.MVPBaseActivity; 8 | import com.mayi.douyu.ui.video.full.FullVideoActivity; 9 | 10 | /** 11 | * 作者 by yugai 时间 16/12/13. 12 | * * 邮箱 784787081@qq.com 13 | */ 14 | 15 | public class HalfVideoActivity extends MVPBaseActivity implements HalfVideoContract.View{ 16 | 17 | 18 | public static void startActivity(Context context) { 19 | Intent intent = new Intent(context, HalfVideoActivity.class); 20 | context.startActivity(intent); 21 | } 22 | 23 | @Override 24 | protected int getLayout() { 25 | return R.layout.activity_half_video; 26 | } 27 | 28 | @Override 29 | public void onRequestError(String msg) { 30 | 31 | } 32 | 33 | @Override 34 | public void onRequestEnd() { 35 | 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /app/src/main/java/com/mayi/douyu/ui/video/half/HalfVideoContract.java: -------------------------------------------------------------------------------- 1 | package com.mayi.douyu.ui.video.half; 2 | 3 | import com.mayi.douyu.mvpbase.BasePresenter; 4 | import com.mayi.douyu.mvpbase.BaseRequestView; 5 | 6 | /** 7 | * 作者 by yugai 时间 16/12/13. 8 | * * 邮箱 784787081@qq.com 9 | */ 10 | 11 | public class HalfVideoContract { 12 | interface View extends BaseRequestView{ 13 | 14 | } 15 | interface Presenter extends BasePresenter{ 16 | 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /app/src/main/java/com/mayi/douyu/ui/video/half/HalfVideoPresenter.java: -------------------------------------------------------------------------------- 1 | package com.mayi.douyu.ui.video.half; 2 | 3 | import com.mayi.douyu.mvpbase.BasePresenterImpl; 4 | 5 | /** 6 | * 作者 by yugai 时间 16/12/13. 7 | * * 邮箱 784787081@qq.com 8 | */ 9 | 10 | public class HalfVideoPresenter extends BasePresenterImpl implements HalfVideoContract.Presenter { 11 | 12 | } 13 | -------------------------------------------------------------------------------- /app/src/main/java/com/mayi/douyu/util/AppManager.java: -------------------------------------------------------------------------------- 1 | package com.mayi.douyu.util; 2 | 3 | import android.app.Activity; 4 | 5 | import java.util.Stack; 6 | 7 | /** 8 | * 作者 by yugai 时间 16/10/31. 9 | * * 邮箱 784787081@qq.com 10 | */ 11 | 12 | public class AppManager { 13 | private static Stack activityStack; 14 | private static AppManager mInstance; 15 | 16 | private AppManager() { 17 | } 18 | 19 | 20 | public static AppManager getAppManager() { 21 | if (mInstance == null) { 22 | synchronized (AppManager.class) { 23 | if (mInstance == null) { 24 | mInstance = new AppManager(); 25 | } 26 | } 27 | } 28 | return mInstance; 29 | } 30 | 31 | public void addActivity(Activity activity) { 32 | if (activityStack == null) { 33 | activityStack = new Stack<>(); 34 | } 35 | activityStack.add(activity); 36 | } 37 | 38 | public void removeActivity(Activity activity) { 39 | if (activity != null && activityStack.contains(activity)) { 40 | activityStack.remove(activity); 41 | } 42 | } 43 | 44 | 45 | public Activity curremtActivity() { 46 | Activity activity = activityStack.lastElement(); 47 | return activity; 48 | } 49 | 50 | 51 | public void finishActivity(Activity activity) { 52 | if (activity != null && activityStack.contains(activity) && !activity.isFinishing()) { 53 | activityStack.remove(activity); 54 | activity.finish(); 55 | } 56 | } 57 | 58 | public void finishAllActivity() { 59 | for (int i = 0, size = activityStack.size(); i < size; i++) { 60 | if (null != activityStack.get(i)) { 61 | activityStack.get(i).finish(); 62 | } 63 | } 64 | activityStack.clear(); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /app/src/main/java/com/mayi/douyu/util/ImeUtils.java: -------------------------------------------------------------------------------- 1 | package com.mayi.douyu.util; 2 | 3 | import android.content.Context; 4 | import android.os.ResultReceiver; 5 | import android.support.annotation.NonNull; 6 | import android.view.View; 7 | import android.view.inputmethod.InputMethodManager; 8 | 9 | import java.lang.reflect.Method; 10 | 11 | /** 12 | * 作者 by yugai 时间 17/1/20. 13 | * * 邮箱 784787081@qq.com 14 | */ 15 | 16 | public class ImeUtils { 17 | private ImeUtils() { } 18 | 19 | public static void showIme(@NonNull View view) { 20 | InputMethodManager imm = (InputMethodManager) view.getContext().getSystemService 21 | (Context.INPUT_METHOD_SERVICE); 22 | // the public methods don't seem to work for me, so… reflection. 23 | try { 24 | Method showSoftInputUnchecked = InputMethodManager.class.getMethod( 25 | "showSoftInputUnchecked", int.class, ResultReceiver.class); 26 | showSoftInputUnchecked.setAccessible(true); 27 | showSoftInputUnchecked.invoke(imm, 0, null); 28 | } catch (Exception e) { 29 | // ho hum 30 | } 31 | } 32 | 33 | public static void hideIme(@NonNull View view) { 34 | InputMethodManager imm = (InputMethodManager) view.getContext().getSystemService(Context 35 | .INPUT_METHOD_SERVICE); 36 | imm.hideSoftInputFromWindow(view.getWindowToken(), 0); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /app/src/main/java/com/mayi/douyu/util/InstanceUtils.java: -------------------------------------------------------------------------------- 1 | package com.mayi.douyu.util; 2 | 3 | import java.lang.reflect.ParameterizedType; 4 | 5 | /** 6 | * 作者 by yugai 时间 16/11/1. 7 | * * 邮箱 784787081@qq.com 8 | * from https://github.com/north2014/T-MVP/blob/master/app/src/main/java/com/base/util/InstanceUtil.java 9 | */ 10 | 11 | public class InstanceUtils { 12 | /** 13 | * 通过实例工厂去实例化相应类 14 | * 15 | * @param o 带泛型的对象 16 | * @param i 需要实例化的对象在泛型中的位置 17 | * @param 返回实例的泛型类型 18 | * @return 19 | */ 20 | public static T getInstance(Object o, int i) { 21 | try { 22 | return ((Class) ((ParameterizedType) (o.getClass() 23 | .getGenericSuperclass())).getActualTypeArguments()[i]) 24 | .newInstance(); 25 | } catch (InstantiationException e) { 26 | e.printStackTrace(); 27 | } catch (IllegalAccessException e) { 28 | e.printStackTrace(); 29 | } catch (ClassCastException e) { 30 | e.printStackTrace(); 31 | } 32 | return null; 33 | } 34 | 35 | public static Class forName(String className) { 36 | try { 37 | return Class.forName(className); 38 | } catch (ClassNotFoundException e) { 39 | e.printStackTrace(); 40 | } 41 | return null; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /app/src/main/java/com/mayi/douyu/util/MD5.java: -------------------------------------------------------------------------------- 1 | package com.mayi.douyu.util; 2 | 3 | import java.security.MessageDigest; 4 | import java.security.NoSuchAlgorithmException; 5 | 6 | /** 7 | * 作者 by yugai 时间 16/11/25. 8 | * * 邮箱 784787081@qq.com 9 | */ 10 | 11 | public class MD5 { 12 | public static String strToMd5Low32(String str) { 13 | StringBuilder builder = new StringBuilder(); 14 | try { 15 | MessageDigest md5 = MessageDigest.getInstance("MD5"); 16 | md5.update(str.getBytes()); 17 | byte[] bytes = md5.digest(); 18 | for (byte b : bytes) { 19 | int digital = b&0xff; 20 | if (digital < 16) 21 | builder.append(0); 22 | builder.append(Integer.toHexString(digital)); 23 | } 24 | } catch (NoSuchAlgorithmException e) { 25 | e.printStackTrace(); 26 | } 27 | return builder.toString().toLowerCase(); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /app/src/main/java/com/mayi/douyu/util/VideoUrlUtils.java: -------------------------------------------------------------------------------- 1 | package com.mayi.douyu.util; 2 | 3 | import android.util.Log; 4 | 5 | import com.google.gson.Gson; 6 | import com.mayi.douyu.entity.DYDetails; 7 | 8 | import org.json.JSONException; 9 | import org.json.JSONObject; 10 | 11 | import java.io.IOException; 12 | import java.util.UUID; 13 | 14 | import okhttp3.Call; 15 | import okhttp3.Callback; 16 | import okhttp3.FormBody; 17 | import okhttp3.OkHttpClient; 18 | import okhttp3.Request; 19 | import okhttp3.RequestBody; 20 | import okhttp3.Response; 21 | 22 | /** 23 | * 作者 by yugai 时间 16/11/29. 24 | * * 邮箱 784787081@qq.com 25 | */ 26 | 27 | public class VideoUrlUtils { 28 | public static void getDouyuRoomParams(int roomId, final VideoRequest videoRequest) { 29 | long time = System.currentTimeMillis()/(1000*60); 30 | String did = UUID.randomUUID().toString().toUpperCase(); 31 | did = did.replace("-", ""); 32 | String str = roomId + did + "A12Svb&%1UUmf@hC" + time; 33 | String sign = MD5.strToMd5Low32(str); 34 | 35 | 36 | Log.i("Tag", "getDouyuRoomParams: "+str+"-----"+sign+"-----"+did); 37 | 38 | 39 | 40 | OkHttpClient mOkHttpClient=new OkHttpClient(); 41 | RequestBody formBody = new FormBody.Builder() 42 | .add("cdn", "ws") 43 | .add("rate", "0") 44 | .add("tt", String.valueOf(time)) 45 | .add("did", did) 46 | .add("sign", sign) 47 | .build(); 48 | 49 | Request request = new Request.Builder() 50 | .url("http://www.douyu.com/lapi/live/getPlay/"+roomId) 51 | .post(formBody) 52 | .build(); 53 | Log.i("Tag", "http://www.douyu.com/lapi/live/getPlay/"+roomId+"?cdn=ws&rate=0&tt="+String.valueOf(time)+"&did="+did+"&sign="+sign); 54 | Call call = mOkHttpClient.newCall(request); 55 | call.enqueue(new Callback() { 56 | @Override 57 | public void onFailure(Call call, IOException e) { 58 | 59 | } 60 | 61 | @Override 62 | public void onResponse(Call call, Response response) throws IOException { 63 | try { 64 | String str = response.body().string(); 65 | Log.i("Tag", str); 66 | Gson gson=new Gson(); 67 | JSONObject json=new JSONObject(str); 68 | DYDetails detail=gson.fromJson(json.getString("data"),DYDetails.class); 69 | String url = detail.getRtmp_url() + "/" + detail.getRtmp_live(); 70 | videoRequest.onRequestUrl(url); 71 | } catch (JSONException e) { 72 | e.printStackTrace(); 73 | } 74 | 75 | } 76 | 77 | }); 78 | } 79 | public interface VideoRequest{ 80 | void onRequestUrl(String url); 81 | void onFailure(); 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /app/src/main/java/com/mayi/douyu/util/rx/RxBus.java: -------------------------------------------------------------------------------- 1 | package com.mayi.douyu.util.rx; 2 | 3 | import android.support.annotation.NonNull; 4 | import android.util.Log; 5 | 6 | 7 | import java.util.ArrayList; 8 | import java.util.Collection; 9 | import java.util.List; 10 | import java.util.concurrent.ConcurrentHashMap; 11 | 12 | import rx.Observable; 13 | import rx.android.schedulers.AndroidSchedulers; 14 | import rx.functions.Action1; 15 | import rx.subjects.PublishSubject; 16 | import rx.subjects.SerializedSubject; 17 | import rx.subjects.Subject; 18 | 19 | /** 20 | * 用RxJava实现的EventBus 21 | * 22 | * @author baixiaokang 23 | */ 24 | public class RxBus { 25 | private static volatile RxBus defaultInstance; 26 | 27 | private final Subject bus; 28 | // PublishSubject只会把在订阅发生的时间点之后来自原始Observable的数据发射给观察者 29 | public RxBus() { 30 | bus = new SerializedSubject<>(PublishSubject.create()); 31 | } 32 | // 单例RxBus 33 | public static RxBus getDefault() { 34 | if (defaultInstance == null) { 35 | synchronized (RxBus.class) { 36 | if (defaultInstance == null) { 37 | defaultInstance = new RxBus(); 38 | } 39 | } 40 | } 41 | return defaultInstance ; 42 | } 43 | // 发送一个新的事件 44 | public void post (Object o) { 45 | bus.onNext(o); 46 | } 47 | // 根据传递的 eventType 类型返回特定类型(eventType)的 被观察者 48 | public Observable toObservable (Class eventType) { 49 | return bus.ofType(eventType); 50 | // 这里感谢小鄧子的提醒: ofType = filter + cast 51 | // return bus.filter(new Func1() { 52 | // @Override 53 | // public Boolean call(Object o) { 54 | // return eventType.isInstance(o); 55 | // } 56 | // }) .cast(eventType); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /app/src/main/java/com/mayi/douyu/widget/CustomSizeFrameLayout.java: -------------------------------------------------------------------------------- 1 | package com.mayi.douyu.widget; 2 | 3 | import android.content.Context; 4 | import android.util.AttributeSet; 5 | import android.util.Log; 6 | import android.view.Display; 7 | import android.view.WindowManager; 8 | import android.widget.FrameLayout; 9 | 10 | /** 11 | * 作者 by yugai 时间 16/12/13. 12 | * * 邮箱 784787081@qq.com 13 | */ 14 | 15 | public class CustomSizeFrameLayout extends FrameLayout { 16 | private static final String TAG = "CustomSizeFrameLayout"; 17 | public CustomSizeFrameLayout(Context context) { 18 | super(context); 19 | } 20 | 21 | public CustomSizeFrameLayout(Context context, AttributeSet attrs, int defStyleAttr) { 22 | super(context, attrs, defStyleAttr); 23 | } 24 | 25 | public CustomSizeFrameLayout(Context context, AttributeSet attrs) { 26 | super(context, attrs); 27 | } 28 | 29 | @Override 30 | protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 31 | super.onMeasure(widthMeasureSpec, heightMeasureSpec); 32 | int widthSize = MeasureSpec.getSize(widthMeasureSpec); 33 | int heightSize = MeasureSpec.getSize(heightMeasureSpec); 34 | 35 | WindowManager manager = (WindowManager) getContext() 36 | .getSystemService(Context.WINDOW_SERVICE); 37 | Display display = manager.getDefaultDisplay(); 38 | 39 | Log.i(TAG, "onMeasure: "+display.getHeight()+"---------"+display.getWidth()); 40 | 41 | setMeasuredDimension(widthSize, widthSize*display.getWidth()/display.getHeight()); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /app/src/main/java/com/mayi/douyu/widget/CustomSizeImageView.java: -------------------------------------------------------------------------------- 1 | package com.mayi.douyu.widget; 2 | 3 | import android.content.Context; 4 | import android.content.res.TypedArray; 5 | import android.util.AttributeSet; 6 | import android.util.Log; 7 | import android.widget.ImageView; 8 | 9 | import com.mayi.douyu.R; 10 | 11 | /** 12 | * 作者 by yugai 时间 16/11/25. 13 | * * 邮箱 784787081@qq.com 14 | */ 15 | 16 | public class CustomSizeImageView extends ImageView{ 17 | private static final String TAG = "CustomSizeImageView"; 18 | enum ImageSizeType{ 19 | HOME(16,9),OTHER(16,9); 20 | int w,h; 21 | ImageSizeType(int w,int h) { 22 | this.w=w; 23 | this.h=h; 24 | } 25 | } 26 | ImageSizeType mImageSizeType=ImageSizeType.HOME; 27 | public CustomSizeImageView(Context context) { 28 | super(context); 29 | } 30 | 31 | public CustomSizeImageView(Context context, AttributeSet attrs) { 32 | super(context, attrs); 33 | } 34 | 35 | public CustomSizeImageView(Context context, AttributeSet attrs, int defStyleAttr) { 36 | super(context, attrs, defStyleAttr); 37 | TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.CustomSizeImageView, defStyleAttr, 0); 38 | switch (a.getInt(R.styleable.CustomSizeImageView_imageSizeType,0)){ 39 | case 0: 40 | mImageSizeType=ImageSizeType.HOME; 41 | break; 42 | case 1: 43 | mImageSizeType=ImageSizeType.OTHER; 44 | break; 45 | } 46 | } 47 | 48 | @Override 49 | protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 50 | super.onMeasure(widthMeasureSpec, heightMeasureSpec); 51 | int widthSize = MeasureSpec.getSize(widthMeasureSpec); 52 | int heightSize = MeasureSpec.getSize(heightMeasureSpec); 53 | 54 | if (widthSize>heightSize){ 55 | heightSize=widthSize*mImageSizeType.h/mImageSizeType.w; 56 | }else{ 57 | widthSize=heightSize*mImageSizeType.w/mImageSizeType.h; 58 | } 59 | Log.i(TAG, "onMeasure: "+widthSize+"-"+heightSize); 60 | setMeasuredDimension(widthSize, heightSize); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /app/src/main/java/com/mayi/douyu/widget/ScrollAwareFABBehaviorDefault.java: -------------------------------------------------------------------------------- 1 | package com.mayi.douyu.widget; 2 | 3 | import android.content.Context; 4 | import android.support.design.widget.CoordinatorLayout; 5 | import android.support.design.widget.FloatingActionButton; 6 | import android.support.v4.view.ViewCompat; 7 | import android.util.AttributeSet; 8 | import android.view.View; 9 | 10 | /** 11 | * 作者 by yugai 时间 16/11/3. 12 | * * 邮箱 784787081@qq.com 13 | */ 14 | 15 | public class ScrollAwareFABBehaviorDefault extends FloatingActionButton.Behavior{ 16 | 17 | public ScrollAwareFABBehaviorDefault(Context context, AttributeSet attrs) { 18 | super(); 19 | } 20 | 21 | @Override 22 | public boolean onStartNestedScroll(final CoordinatorLayout coordinatorLayout, final FloatingActionButton child, 23 | final View directTargetChild, final View target, final int nestedScrollAxes) { 24 | // Ensure we react to vertical scrolling 25 | return nestedScrollAxes == ViewCompat.SCROLL_AXIS_VERTICAL 26 | || super.onStartNestedScroll(coordinatorLayout, child, directTargetChild, target, nestedScrollAxes); 27 | } 28 | 29 | @Override 30 | public void onNestedScroll(final CoordinatorLayout coordinatorLayout, final FloatingActionButton child, 31 | final View target, final int dxConsumed, final int dyConsumed, 32 | final int dxUnconsumed, final int dyUnconsumed) { 33 | super.onNestedScroll(coordinatorLayout, child, target, dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed); 34 | if (dyConsumed > 0 && child.getVisibility() == View.VISIBLE) { 35 | // User scrolled down and the FAB is currently visible -> hide the FAB 36 | child.hide(); 37 | } else if (dyConsumed < 0 && child.getVisibility() != View.VISIBLE) { 38 | // User scrolled up and the FAB is currently not visible -> show the FAB 39 | child.show(); 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /app/src/main/java/com/mayi/douyu/widget/help/BaseOnScrollListener.java: -------------------------------------------------------------------------------- 1 | package com.mayi.douyu.widget.help; 2 | 3 | import android.support.v7.widget.LinearLayoutManager; 4 | import android.support.v7.widget.RecyclerView; 5 | 6 | /** 7 | * 作者 by yugai 时间 16/11/25. 8 | * * 邮箱 784787081@qq.com 9 | */ 10 | 11 | public abstract class BaseOnScrollListener extends RecyclerView.OnScrollListener { 12 | protected int lastVisibleItem; 13 | 14 | @Override 15 | public void onScrolled(RecyclerView recyclerView, int dx, int dy) { 16 | super.onScrolled(recyclerView, dx, dy); 17 | lastVisibleItem = ((LinearLayoutManager)recyclerView.getLayoutManager()).findLastVisibleItemPosition(); 18 | 19 | } 20 | 21 | @Override 22 | public void onScrollStateChanged(RecyclerView recyclerView, int newState) { 23 | super.onScrollStateChanged(recyclerView, newState); 24 | if (newState == RecyclerView.SCROLL_STATE_IDLE 25 | && lastVisibleItem + 1 == recyclerView.getAdapter().getItemCount()) { 26 | onLoadMore(); 27 | } 28 | } 29 | 30 | public abstract void onLoadMore(); 31 | } 32 | -------------------------------------------------------------------------------- /app/src/main/res/anim/fade_in.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 11 | 12 | 16 | 17 | -------------------------------------------------------------------------------- /app/src/main/res/anim/fade_out.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/animator/searchback_hide_arrow_head.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 25 | -------------------------------------------------------------------------------- /app/src/main/res/animator/searchback_hide_circle.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 25 | -------------------------------------------------------------------------------- /app/src/main/res/animator/searchback_show_arrow_head.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 21 | 22 | 23 | 28 | 29 | 30 | 37 | 38 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /app/src/main/res/animator/searchback_show_circle.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 21 | 22 | 23 | 28 | 29 | 30 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /app/src/main/res/animator/searchback_stem_back_to_search.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 21 | 22 | 28 | 29 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /app/src/main/res/animator/searchback_stem_search_to_back.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 21 | 22 | 28 | 29 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-v21/ic_menu_camera.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 12 | 13 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-v21/ic_menu_gallery.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-v21/ic_menu_manage.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-v21/ic_menu_send.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-v21/ic_menu_share.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-v21/ic_menu_slideshow.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/avd_back_to_search.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 21 | 22 | 25 | 26 | 29 | 30 | 33 | 34 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/avd_search_to_back.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 21 | 22 | 25 | 26 | 29 | 30 | 33 | 34 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/background_btn_stream_normal.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/background_btn_stream_pressed.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/background_iv_circle.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 7 | 8 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/background_tv_name.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 8 | 10 | 15 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/background_tv_title.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 8 | 10 | 15 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/bg_live_item.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 8 | 9 | 10 | 11 | 12 | 13 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_android.xml: -------------------------------------------------------------------------------- 1 | 6 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_arrow_back_padded.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 12 | 13 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_avatar_default.xml: -------------------------------------------------------------------------------- 1 | 6 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_avatar_normal.xml: -------------------------------------------------------------------------------- 1 | 6 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_avatar_pressed.xml: -------------------------------------------------------------------------------- 1 | 6 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_back_arrow_normal.xml: -------------------------------------------------------------------------------- 1 | 6 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_back_arrow_pressed.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_camera.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 12 | 13 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_clear_black_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_computer.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_danmu_off_normal.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_danmu_off_pressed.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_danmu_on_normal.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_danmu_on_normal_dark.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_danmu_on_pressed.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_empty.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_expand_close.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_expand_open.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_explore_default.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_explore_normal.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_explore_pressed.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_fullscreen_exit_normal.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_fullscreen_exit_pressed.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_fullscreen_normal.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_fullscreen_pressed.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_introduction.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_live_normal.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_live_placeholder.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_live_pressed.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_pause_normal.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_pause_pressed.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_play_arrow_normal.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_play_arrow_pressed.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_refresh_normal.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_refresh_pressed.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_school.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_search_24dp.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_texture_black_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_user.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_user_normal.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_user_pressed.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_visitor.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/searchback_back.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 24 | 25 | 32 | 33 | 39 | 40 | 46 | 47 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/searchback_search.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 24 | 25 | 32 | 33 | 39 | 40 | 46 | 47 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/selector_btn_back.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/selector_btn_danmu_off.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/selector_btn_danmu_on.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/selector_btn_fullscreen.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/selector_btn_fullscreen_exit.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/selector_btn_pause.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/selector_btn_play.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/selector_btn_refresh.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/selector_btn_stream.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/side_nav_bar.xml: -------------------------------------------------------------------------------- 1 | 3 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_about.xml: -------------------------------------------------------------------------------- 1 | 2 | 10 | 11 | 15 | 16 | 24 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_custom_error.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 12 | 13 | 18 | 19 | 24 | 25 | 31 | 32 | 38 | 39 | 40 | 46 | 47 | 48 | 49 |