Commit e3d87fb50a8f22e7e0fa002b3373b8c6de48e363

Authored by 杨帅
1 parent 146a809a

1 封装视频库

Showing 72 changed files with 574 additions and 5011 deletions
.idea/gradle.xml
@@ -3,11 +3,33 @@ @@ -3,11 +3,33 @@
3 <component name="GradleSettings"> 3 <component name="GradleSettings">
4 <option name="linkedExternalProjectsSettings"> 4 <option name="linkedExternalProjectsSettings">
5 <GradleProjectSettings> 5 <GradleProjectSettings>
6 - <compositeConfiguration>  
7 - <compositeBuild compositeDefinitionSource="SCRIPT" />  
8 - </compositeConfiguration>  
9 <option name="distributionType" value="DEFAULT_WRAPPED" /> 6 <option name="distributionType" value="DEFAULT_WRAPPED" />
10 <option name="externalProjectPath" value="$PROJECT_DIR$" /> 7 <option name="externalProjectPath" value="$PROJECT_DIR$" />
  8 + <option name="modules">
  9 + <set>
  10 + <option value="$PROJECT_DIR$" />
  11 + <option value="$PROJECT_DIR$/app" />
  12 + <option value="$PROJECT_DIR$/app/strike" />
  13 + <option value="$PROJECT_DIR$/cloud" />
  14 + <option value="$PROJECT_DIR$/cloud/app_pay" />
  15 + <option value="$PROJECT_DIR$/cloud/pay" />
  16 + <option value="$PROJECT_DIR$/cloud/third_tool" />
  17 + <option value="$PROJECT_DIR$/cloud/user" />
  18 + <option value="$PROJECT_DIR$/cloud/video" />
  19 + <option value="$PROJECT_DIR$/core" />
  20 + <option value="$PROJECT_DIR$/core/app_qr" />
  21 + <option value="$PROJECT_DIR$/core/base" />
  22 + <option value="$PROJECT_DIR$/core/database" />
  23 + <option value="$PROJECT_DIR$/core/imageload" />
  24 + <option value="$PROJECT_DIR$/core/network" />
  25 + <option value="$PROJECT_DIR$/library_baidumap" />
  26 + <option value="$PROJECT_DIR$/module" />
  27 + <option value="$PROJECT_DIR$/module/pedometer" />
  28 + <option value="$PROJECT_DIR$/module/shanghaishop" />
  29 + <option value="$PROJECT_DIR$/module/shopcity" />
  30 + <option value="$PROJECT_DIR$/module/xiaojiasoundbox" />
  31 + </set>
  32 + </option>
11 <option name="resolveModulePerSourceSet" value="false" /> 33 <option name="resolveModulePerSourceSet" value="false" />
12 <option name="testRunner" value="PLATFORM" /> 34 <option name="testRunner" value="PLATFORM" />
13 </GradleProjectSettings> 35 </GradleProjectSettings>
app/strike/build.gradle
@@ -182,7 +182,7 @@ dependencies { @@ -182,7 +182,7 @@ dependencies {
182 implementation project(path: ':module:shopcity') 182 implementation project(path: ':module:shopcity')
183 // implementation project(path: ':module:shanghaishop') 183 // implementation project(path: ':module:shanghaishop')
184 implementation project(path: ':library_baidumap') 184 implementation project(path: ':library_baidumap')
185 - implementation 'com.jakewharton.rxbinding3:rxbinding:3.1.0' 185 +// implementation 'com.jakewharton.rxbinding3:rxbinding:3.1.0'
186 // implementation project(path: ':core:util') 186 // implementation project(path: ':core:util')
187 // implementation project(path: ':core:encipher') 187 // implementation project(path: ':core:encipher')
188 // implementation project(path: ':cloud:user') 188 // implementation project(path: ':cloud:user')
app/strike/src/main/java/com/cnlive/strike/DemoApplication.java
@@ -23,7 +23,6 @@ import com.baidu.mapapi.SDKInitializer; @@ -23,7 +23,6 @@ import com.baidu.mapapi.SDKInitializer;
23 import com.cnlive.cloud.user.auth.UserService; 23 import com.cnlive.cloud.user.auth.UserService;
24 import com.cnlive.core.libs.base.application.AppConfig; 24 import com.cnlive.core.libs.base.application.AppConfig;
25 import com.cnlive.core.libs.base.application.BaseApplication; 25 import com.cnlive.core.libs.base.application.BaseApplication;
26 -import com.cnlive.strike.demo.exoplayer.demo.DownloadTracker;  
27 import com.google.android.exoplayer2.BuildConfig; 26 import com.google.android.exoplayer2.BuildConfig;
28 import com.google.android.exoplayer2.DefaultRenderersFactory; 27 import com.google.android.exoplayer2.DefaultRenderersFactory;
29 import com.google.android.exoplayer2.RenderersFactory; 28 import com.google.android.exoplayer2.RenderersFactory;
@@ -72,7 +71,6 @@ public class DemoApplication extends BaseApplication { @@ -72,7 +71,6 @@ public class DemoApplication extends BaseApplication {
72 private File downloadDirectory; 71 private File downloadDirectory;
73 private Cache downloadCache; 72 private Cache downloadCache;
74 private DownloadManager downloadManager; 73 private DownloadManager downloadManager;
75 - private DownloadTracker downloadTracker;  
76 74
77 @Override 75 @Override
78 public void onCreate() { 76 public void onCreate() {
@@ -153,15 +151,7 @@ public class DemoApplication extends BaseApplication { @@ -153,15 +151,7 @@ public class DemoApplication extends BaseApplication {
153 .setExtensionRendererMode(extensionRendererMode); 151 .setExtensionRendererMode(extensionRendererMode);
154 } 152 }
155 153
156 - public DownloadManager getDownloadManager() {  
157 - initDownloadManager();  
158 - return downloadManager;  
159 - }  
160 154
161 - public DownloadTracker getDownloadTracker() {  
162 - initDownloadManager();  
163 - return downloadTracker;  
164 - }  
165 155
166 protected synchronized Cache getDownloadCache() { 156 protected synchronized Cache getDownloadCache() {
167 if (downloadCache == null) { 157 if (downloadCache == null) {
@@ -172,23 +162,6 @@ public class DemoApplication extends BaseApplication { @@ -172,23 +162,6 @@ public class DemoApplication extends BaseApplication {
172 return downloadCache; 162 return downloadCache;
173 } 163 }
174 164
175 - private synchronized void initDownloadManager() {  
176 - if (downloadManager == null) {  
177 - DefaultDownloadIndex downloadIndex = new DefaultDownloadIndex(getDatabaseProvider());  
178 - upgradeActionFile(  
179 - DOWNLOAD_ACTION_FILE, downloadIndex, /* addNewDownloadsAsCompleted= */ false);  
180 - upgradeActionFile(  
181 - DOWNLOAD_TRACKER_ACTION_FILE, downloadIndex, /* addNewDownloadsAsCompleted= */ true);  
182 - DownloaderConstructorHelper downloaderConstructorHelper =  
183 - new DownloaderConstructorHelper(getDownloadCache(), buildHttpDataSourceFactory());  
184 - downloadManager =  
185 - new DownloadManager(  
186 - this, downloadIndex, new DefaultDownloaderFactory(downloaderConstructorHelper));  
187 - downloadTracker =  
188 - new DownloadTracker(/* context= */ this, buildDataSourceFactory(), downloadManager);  
189 - }  
190 - }  
191 -  
192 private void upgradeActionFile( 165 private void upgradeActionFile(
193 String fileName, DefaultDownloadIndex downloadIndex, boolean addNewDownloadsAsCompleted) { 166 String fileName, DefaultDownloadIndex downloadIndex, boolean addNewDownloadsAsCompleted) {
194 try { 167 try {
app/strike/src/main/java/com/cnlive/strike/demo/activity/DemoMvpActivity.java
@@ -39,7 +39,6 @@ import com.cnlive.moudle.pedometer.commonInfo.CommonInfo; @@ -39,7 +39,6 @@ import com.cnlive.moudle.pedometer.commonInfo.CommonInfo;
39 import com.cnlive.moudle.pedometer.ui.activity.RunLineActivity; 39 import com.cnlive.moudle.pedometer.ui.activity.RunLineActivity;
40 import com.cnlive.strike.demo.activity.presenter.DemoActivityPresenter; 40 import com.cnlive.strike.demo.activity.presenter.DemoActivityPresenter;
41 import com.cnlive.strike.demo.activity.view.DemoActivityView; 41 import com.cnlive.strike.demo.activity.view.DemoActivityView;
42 -import com.cnlive.strike.demo.exoplayer.demo.SampleChooserActivity;  
43 import com.cnlive.strike.network.api.ApiService; 42 import com.cnlive.strike.network.api.ApiService;
44 import com.cnlive.strike.network.api.ApiTimeService; 43 import com.cnlive.strike.network.api.ApiTimeService;
45 import com.cnlive.strike.network.api.TimeServiceBean; 44 import com.cnlive.strike.network.api.TimeServiceBean;
@@ -434,8 +433,6 @@ public class DemoMvpActivity extends BaseActivity&lt;DemoActivityView, DemoActivity @@ -434,8 +433,6 @@ public class DemoMvpActivity extends BaseActivity&lt;DemoActivityView, DemoActivity
434 binding.btnExoHome.setOnClickListener(new View.OnClickListener() { 433 binding.btnExoHome.setOnClickListener(new View.OnClickListener() {
435 @Override 434 @Override
436 public void onClick(View v) { 435 public void onClick(View v) {
437 - Intent intent=new Intent(me, SampleChooserActivity.class);  
438 - startActivity(intent);  
439 } 436 }
440 }); 437 });
441 //获取uid 438 //获取uid
app/strike/src/main/java/com/cnlive/strike/demo/activity/ExoPlayerActivity.java
@@ -18,7 +18,9 @@ import com.google.android.exoplayer2.upstream.DefaultHttpDataSourceFactory; @@ -18,7 +18,9 @@ import com.google.android.exoplayer2.upstream.DefaultHttpDataSourceFactory;
18 import com.google.android.exoplayer2.util.Util; 18 import com.google.android.exoplayer2.util.Util;
19 import com.google.android.exoplayer2.video.VideoListener; 19 import com.google.android.exoplayer2.video.VideoListener;
20 import com.libs.video.video.exoplayer.component.DefaultErrorView; 20 import com.libs.video.video.exoplayer.component.DefaultErrorView;
  21 +import com.libs.video.video.exoplayer.component.DefaultYoukuPrepareView;
21 import com.libs.video.video.exoplayer.play.CNVideoView; 22 import com.libs.video.video.exoplayer.play.CNVideoView;
  23 +import com.libs.video.video.test.CNLiveVideoView;
22 import com.libs.video.video.test.VideoPlayer; 24 import com.libs.video.video.test.VideoPlayer;
23 import com.libs.video.video.exoplayer.component.DefaultAdControlView; 25 import com.libs.video.video.exoplayer.component.DefaultAdControlView;
24 import com.libs.video.video.exoplayer.controller.StandardVideoController; 26 import com.libs.video.video.exoplayer.controller.StandardVideoController;
@@ -93,11 +95,13 @@ public class ExoPlayerActivity extends BaseActivity implements VideoListener, Pl @@ -93,11 +95,13 @@ public class ExoPlayerActivity extends BaseActivity implements VideoListener, Pl
93 } 95 }
94 }); 96 });
95 DefaultErrorView errorView=new DefaultErrorView(this); 97 DefaultErrorView errorView=new DefaultErrorView(this);
96 - mController.addControlComponent(adControlView, errorView); 98 + mController.addControlComponent(new DefaultYoukuPrepareView(me),errorView);
97 //直播 99 //直播
98 binding.playerView.setUrl("http://ffyl.vods2.cnlive.com/223/vod/2018/1120/223_88c98ab1395f4762b703fbdd9d59d2e5/ff80808166c2a45201672f14a9933131_800.m3u8"); 100 binding.playerView.setUrl("http://ffyl.vods2.cnlive.com/223/vod/2018/1120/223_88c98ab1395f4762b703fbdd9d59d2e5/ff80808166c2a45201672f14a9933131_800.m3u8");
99 binding.playerView.setVideoController(mController); 101 binding.playerView.setVideoController(mController);
  102 + binding.playerView.setScreenScaleType(CNVideoView.SCREEN_SCALE_16_9);
100 binding.playerView.start(); 103 binding.playerView.start();
  104 +
101 //监听播放结束 105 //监听播放结束
102 // binding.playerView.addOnStateChangeListener(new CNVideoView.SimpleOnStateChangeListener() { 106 // binding.playerView.addOnStateChangeListener(new CNVideoView.SimpleOnStateChangeListener() {
103 // @Override 107 // @Override
app/strike/src/main/java/com/cnlive/strike/demo/exoplayer/demo/DemoDownloadService.java deleted 100644 → 0
1 -/*  
2 - * Copyright (C) 2017 The Android Open Source Project  
3 - *  
4 - * Licensed under the Apache License, Version 2.0 (the "License");  
5 - * you may not use this file except in compliance with the License.  
6 - * You may obtain a copy of the License at  
7 - *  
8 - * http://www.apache.org/licenses/LICENSE-2.0  
9 - *  
10 - * Unless required by applicable law or agreed to in writing, software  
11 - * distributed under the License is distributed on an "AS IS" BASIS,  
12 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  
13 - * See the License for the specific language governing permissions and  
14 - * limitations under the License.  
15 - */  
16 -package com.cnlive.strike.demo.exoplayer.demo;  
17 -  
18 -import android.app.Notification;  
19 -  
20 -import com.cnlive.cloud.R;  
21 -import com.cnlive.strike.DemoApplication;  
22 -import com.google.android.exoplayer2.offline.Download;  
23 -import com.google.android.exoplayer2.offline.DownloadManager;  
24 -import com.google.android.exoplayer2.offline.DownloadService;  
25 -import com.google.android.exoplayer2.scheduler.PlatformScheduler;  
26 -import com.google.android.exoplayer2.ui.DownloadNotificationHelper;  
27 -import com.google.android.exoplayer2.util.NotificationUtil;  
28 -import com.google.android.exoplayer2.util.Util;  
29 -import java.util.List;  
30 -  
31 -/** A service for downloading media. */  
32 -public class DemoDownloadService extends DownloadService {  
33 -  
34 - private static final String CHANNEL_ID = "download_channel";  
35 - private static final int JOB_ID = 1;  
36 - private static final int FOREGROUND_NOTIFICATION_ID = 1;  
37 -  
38 - private static int nextNotificationId = FOREGROUND_NOTIFICATION_ID + 1;  
39 -  
40 - private DownloadNotificationHelper notificationHelper;  
41 -  
42 - public DemoDownloadService() {  
43 - super(  
44 - FOREGROUND_NOTIFICATION_ID,  
45 - DEFAULT_FOREGROUND_NOTIFICATION_UPDATE_INTERVAL,  
46 - CHANNEL_ID,  
47 - R.string.exo_download_notification_channel_name,  
48 - /* channelDescriptionResourceId= */ 0);  
49 - nextNotificationId = FOREGROUND_NOTIFICATION_ID + 1;  
50 - }  
51 -  
52 - @Override  
53 - public void onCreate() {  
54 - super.onCreate();  
55 - notificationHelper = new DownloadNotificationHelper(this, CHANNEL_ID);  
56 - }  
57 -  
58 - @Override  
59 - protected DownloadManager getDownloadManager() {  
60 - return ((DemoApplication) getApplication()).getDownloadManager();  
61 - }  
62 -  
63 - @Override  
64 - protected PlatformScheduler getScheduler() {  
65 - return Util.SDK_INT >= 21 ? new PlatformScheduler(this, JOB_ID) : null;  
66 - }  
67 -  
68 - @Override  
69 - protected Notification getForegroundNotification(List<Download> downloads) {  
70 - return notificationHelper.buildProgressNotification(  
71 - R.drawable.ic_download, /* contentIntent= */ null, /* message= */ null, downloads);  
72 - }  
73 -  
74 - @Override  
75 - protected void onDownloadChanged(Download download) {  
76 - Notification notification;  
77 - if (download.state == Download.STATE_COMPLETED) {  
78 - notification =  
79 - notificationHelper.buildDownloadCompletedNotification(  
80 - R.drawable.ic_download_done,  
81 - /* contentIntent= */ null,  
82 - Util.fromUtf8Bytes(download.request.data));  
83 - } else if (download.state == Download.STATE_FAILED) {  
84 - notification =  
85 - notificationHelper.buildDownloadFailedNotification(  
86 - R.drawable.ic_download_done,  
87 - /* contentIntent= */ null,  
88 - Util.fromUtf8Bytes(download.request.data));  
89 - } else {  
90 - return;  
91 - }  
92 - NotificationUtil.setNotification(this, nextNotificationId++, notification);  
93 - }  
94 -}  
app/strike/src/main/java/com/cnlive/strike/demo/exoplayer/demo/DownloadTracker.java deleted 100644 → 0
1 -/*  
2 - * Copyright (C) 2017 The Android Open Source Project  
3 - *  
4 - * Licensed under the Apache License, Version 2.0 (the "License");  
5 - * you may not use this file except in compliance with the License.  
6 - * You may obtain a copy of the License at  
7 - *  
8 - * http://www.apache.org/licenses/LICENSE-2.0  
9 - *  
10 - * Unless required by applicable law or agreed to in writing, software  
11 - * distributed under the License is distributed on an "AS IS" BASIS,  
12 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  
13 - * See the License for the specific language governing permissions and  
14 - * limitations under the License.  
15 - */  
16 -package com.cnlive.strike.demo.exoplayer.demo;  
17 -  
18 -import android.content.Context;  
19 -import android.content.DialogInterface;  
20 -import android.net.Uri;  
21 -import android.widget.Toast;  
22 -import androidx.annotation.Nullable;  
23 -import androidx.fragment.app.FragmentManager;  
24 -  
25 -import com.cnlive.cloud.R;  
26 -import com.google.android.exoplayer2.C;  
27 -import com.google.android.exoplayer2.RenderersFactory;  
28 -import com.google.android.exoplayer2.offline.Download;  
29 -import com.google.android.exoplayer2.offline.DownloadCursor;  
30 -import com.google.android.exoplayer2.offline.DownloadHelper;  
31 -import com.google.android.exoplayer2.offline.DownloadIndex;  
32 -import com.google.android.exoplayer2.offline.DownloadManager;  
33 -import com.google.android.exoplayer2.offline.DownloadRequest;  
34 -import com.google.android.exoplayer2.offline.DownloadService;  
35 -import com.google.android.exoplayer2.trackselection.DefaultTrackSelector;  
36 -import com.google.android.exoplayer2.trackselection.MappingTrackSelector.MappedTrackInfo;  
37 -import com.google.android.exoplayer2.upstream.DataSource;  
38 -import com.google.android.exoplayer2.util.Log;  
39 -import com.google.android.exoplayer2.util.Util;  
40 -import java.io.IOException;  
41 -import java.util.HashMap;  
42 -import java.util.concurrent.CopyOnWriteArraySet;  
43 -  
44 -/** Tracks media that has been downloaded. */  
45 -public class DownloadTracker {  
46 -  
47 - /** Listens for changes in the tracked downloads. */  
48 - public interface Listener {  
49 -  
50 - /** Called when the tracked downloads changed. */  
51 - void onDownloadsChanged();  
52 - }  
53 -  
54 - private static final String TAG = "DownloadTracker";  
55 -  
56 - private final Context context;  
57 - private final DataSource.Factory dataSourceFactory;  
58 - private final CopyOnWriteArraySet<Listener> listeners;  
59 - private final HashMap<Uri, Download> downloads;  
60 - private final DownloadIndex downloadIndex;  
61 - private final DefaultTrackSelector.Parameters trackSelectorParameters;  
62 -  
63 - @Nullable private StartDownloadDialogHelper startDownloadDialogHelper;  
64 -  
65 - public DownloadTracker(  
66 - Context context, DataSource.Factory dataSourceFactory, DownloadManager downloadManager) {  
67 - this.context = context.getApplicationContext();  
68 - this.dataSourceFactory = dataSourceFactory;  
69 - listeners = new CopyOnWriteArraySet<>();  
70 - downloads = new HashMap<>();  
71 - downloadIndex = downloadManager.getDownloadIndex();  
72 - trackSelectorParameters = DownloadHelper.getDefaultTrackSelectorParameters(context);  
73 - downloadManager.addListener(new DownloadManagerListener());  
74 - loadDownloads();  
75 - }  
76 -  
77 - public void addListener(Listener listener) {  
78 - listeners.add(listener);  
79 - }  
80 -  
81 - public void removeListener(Listener listener) {  
82 - listeners.remove(listener);  
83 - }  
84 -  
85 - public boolean isDownloaded(Uri uri) {  
86 - Download download = downloads.get(uri);  
87 - return download != null && download.state != Download.STATE_FAILED;  
88 - }  
89 -  
90 - public DownloadRequest getDownloadRequest(Uri uri) {  
91 - Download download = downloads.get(uri);  
92 - return download != null && download.state != Download.STATE_FAILED ? download.request : null;  
93 - }  
94 -  
95 - public void toggleDownload(  
96 - FragmentManager fragmentManager,  
97 - String name,  
98 - Uri uri,  
99 - String extension,  
100 - RenderersFactory renderersFactory) {  
101 - Download download = downloads.get(uri);  
102 - if (download != null) {  
103 - DownloadService.sendRemoveDownload(  
104 - context, DemoDownloadService.class, download.request.id, /* foreground= */ false);  
105 - } else {  
106 - if (startDownloadDialogHelper != null) {  
107 - startDownloadDialogHelper.release();  
108 - }  
109 - startDownloadDialogHelper =  
110 - new StartDownloadDialogHelper(  
111 - fragmentManager, getDownloadHelper(uri, extension, renderersFactory), name);  
112 - }  
113 - }  
114 -  
115 - private void loadDownloads() {  
116 - try (DownloadCursor loadedDownloads = downloadIndex.getDownloads()) {  
117 - while (loadedDownloads.moveToNext()) {  
118 - Download download = loadedDownloads.getDownload();  
119 - downloads.put(download.request.uri, download);  
120 - }  
121 - } catch (IOException e) {  
122 - Log.w(TAG, "Failed to query downloads", e);  
123 - }  
124 - }  
125 -  
126 - private DownloadHelper getDownloadHelper(  
127 - Uri uri, String extension, RenderersFactory renderersFactory) {  
128 - int type = Util.inferContentType(uri, extension);  
129 - switch (type) {  
130 - case C.TYPE_DASH:  
131 - return DownloadHelper.forDash(context, uri, dataSourceFactory, renderersFactory);  
132 - case C.TYPE_SS:  
133 - return DownloadHelper.forSmoothStreaming(context, uri, dataSourceFactory, renderersFactory);  
134 - case C.TYPE_HLS:  
135 - return DownloadHelper.forHls(context, uri, dataSourceFactory, renderersFactory);  
136 - case C.TYPE_OTHER:  
137 - return DownloadHelper.forProgressive(context, uri);  
138 - default:  
139 - throw new IllegalStateException("Unsupported type: " + type);  
140 - }  
141 - }  
142 -  
143 - private class DownloadManagerListener implements DownloadManager.Listener {  
144 -  
145 - @Override  
146 - public void onDownloadChanged(DownloadManager downloadManager, Download download) {  
147 - downloads.put(download.request.uri, download);  
148 - for (Listener listener : listeners) {  
149 - listener.onDownloadsChanged();  
150 - }  
151 - }  
152 -  
153 - @Override  
154 - public void onDownloadRemoved(DownloadManager downloadManager, Download download) {  
155 - downloads.remove(download.request.uri);  
156 - for (Listener listener : listeners) {  
157 - listener.onDownloadsChanged();  
158 - }  
159 - }  
160 - }  
161 -  
162 - private final class StartDownloadDialogHelper  
163 - implements DownloadHelper.Callback,  
164 - DialogInterface.OnClickListener,  
165 - DialogInterface.OnDismissListener {  
166 -  
167 - private final FragmentManager fragmentManager;  
168 - private final DownloadHelper downloadHelper;  
169 - private final String name;  
170 -  
171 - private TrackSelectionDialog trackSelectionDialog;  
172 - private MappedTrackInfo mappedTrackInfo;  
173 -  
174 - public StartDownloadDialogHelper(  
175 - FragmentManager fragmentManager, DownloadHelper downloadHelper, String name) {  
176 - this.fragmentManager = fragmentManager;  
177 - this.downloadHelper = downloadHelper;  
178 - this.name = name;  
179 - downloadHelper.prepare(this);  
180 - }  
181 -  
182 - public void release() {  
183 - downloadHelper.release();  
184 - if (trackSelectionDialog != null) {  
185 - trackSelectionDialog.dismiss();  
186 - }  
187 - }  
188 -  
189 - // DownloadHelper.Callback implementation.  
190 -  
191 - @Override  
192 - public void onPrepared(DownloadHelper helper) {  
193 - if (helper.getPeriodCount() == 0) {  
194 - Log.d(TAG, "No periods found. Downloading entire stream.");  
195 - startDownload();  
196 - downloadHelper.release();  
197 - return;  
198 - }  
199 - mappedTrackInfo = downloadHelper.getMappedTrackInfo(/* periodIndex= */ 0);  
200 - if (!TrackSelectionDialog.willHaveContent(mappedTrackInfo)) {  
201 - Log.d(TAG, "No dialog content. Downloading entire stream.");  
202 - startDownload();  
203 - downloadHelper.release();  
204 - return;  
205 - }  
206 - trackSelectionDialog =  
207 - TrackSelectionDialog.createForMappedTrackInfoAndParameters(  
208 - /* titleId= */ R.string.exo_download_description,  
209 - mappedTrackInfo,  
210 - trackSelectorParameters,  
211 - /* allowAdaptiveSelections =*/ false,  
212 - /* allowMultipleOverrides= */ true,  
213 - /* onClickListener= */ this,  
214 - /* onDismissListener= */ this);  
215 - trackSelectionDialog.show(fragmentManager, /* tag= */ null);  
216 - }  
217 -  
218 - @Override  
219 - public void onPrepareError(DownloadHelper helper, IOException e) {  
220 - Toast.makeText(context, R.string.download_start_error, Toast.LENGTH_LONG).show();  
221 - Log.e(  
222 - TAG,  
223 - e instanceof DownloadHelper.LiveContentUnsupportedException  
224 - ? "Downloading live content unsupported"  
225 - : "Failed to start download",  
226 - e);  
227 - }  
228 -  
229 - // DialogInterface.OnClickListener implementation.  
230 -  
231 - @Override  
232 - public void onClick(DialogInterface dialog, int which) {  
233 - for (int periodIndex = 0; periodIndex < downloadHelper.getPeriodCount(); periodIndex++) {  
234 - downloadHelper.clearTrackSelections(periodIndex);  
235 - for (int i = 0; i < mappedTrackInfo.getRendererCount(); i++) {  
236 - if (!trackSelectionDialog.getIsDisabled(/* rendererIndex= */ i)) {  
237 - downloadHelper.addTrackSelectionForSingleRenderer(  
238 - periodIndex,  
239 - /* rendererIndex= */ i,  
240 - trackSelectorParameters,  
241 - trackSelectionDialog.getOverrides(/* rendererIndex= */ i));  
242 - }  
243 - }  
244 - }  
245 - DownloadRequest downloadRequest = buildDownloadRequest();  
246 - if (downloadRequest.streamKeys.isEmpty()) {  
247 - // All tracks were deselected in the dialog. Don't start the download.  
248 - return;  
249 - }  
250 - startDownload(downloadRequest);  
251 - }  
252 -  
253 - // DialogInterface.OnDismissListener implementation.  
254 -  
255 - @Override  
256 - public void onDismiss(DialogInterface dialogInterface) {  
257 - trackSelectionDialog = null;  
258 - downloadHelper.release();  
259 - }  
260 -  
261 - // Internal methods.  
262 -  
263 - private void startDownload() {  
264 - startDownload(buildDownloadRequest());  
265 - }  
266 -  
267 - private void startDownload(DownloadRequest downloadRequest) {  
268 - DownloadService.sendAddDownload(  
269 - context, DemoDownloadService.class, downloadRequest, /* foreground= */ false);  
270 - }  
271 -  
272 - private DownloadRequest buildDownloadRequest() {  
273 - return downloadHelper.getDownloadRequest(Util.getUtf8Bytes(name));  
274 - }  
275 - }  
276 -}  
app/strike/src/main/java/com/cnlive/strike/demo/exoplayer/demo/PlayerActivity.java deleted 100644 → 0
1 -/*  
2 - * Copyright (C) 2016 The Android Open Source Project  
3 - *  
4 - * Licensed under the Apache License, Version 2.0 (the "License");  
5 - * you may not use this file except in compliance with the License.  
6 - * You may obtain a copy of the License at  
7 - *  
8 - * http://www.apache.org/licenses/LICENSE-2.0  
9 - *  
10 - * Unless required by applicable law or agreed to in writing, software  
11 - * distributed under the License is distributed on an "AS IS" BASIS,  
12 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  
13 - * See the License for the specific language governing permissions and  
14 - * limitations under the License.  
15 - */  
16 -package com.cnlive.strike.demo.exoplayer.demo;  
17 -  
18 -import android.content.Intent;  
19 -import android.content.pm.PackageManager;  
20 -import android.media.MediaDrm;  
21 -import android.net.Uri;  
22 -import android.os.Bundle;  
23 -import android.util.Pair;  
24 -import android.view.KeyEvent;  
25 -import android.view.View;  
26 -import android.view.View.OnClickListener;  
27 -import android.widget.Button;  
28 -import android.widget.LinearLayout;  
29 -import android.widget.TextView;  
30 -import android.widget.Toast;  
31 -import androidx.annotation.NonNull;  
32 -import androidx.annotation.Nullable;  
33 -import androidx.appcompat.app.AppCompatActivity;  
34 -  
35 -import com.cnlive.cloud.R;  
36 -import com.cnlive.strike.DemoApplication;  
37 -import com.google.android.exoplayer2.C;  
38 -import com.google.android.exoplayer2.C.ContentType;  
39 -import com.google.android.exoplayer2.ExoPlaybackException;  
40 -import com.google.android.exoplayer2.Format;  
41 -import com.google.android.exoplayer2.PlaybackPreparer;  
42 -import com.google.android.exoplayer2.Player;  
43 -import com.google.android.exoplayer2.RenderersFactory;  
44 -import com.google.android.exoplayer2.SimpleExoPlayer;  
45 -import com.google.android.exoplayer2.drm.DefaultDrmSessionManager;  
46 -import com.google.android.exoplayer2.drm.DrmSessionManager;  
47 -import com.google.android.exoplayer2.drm.ExoMediaCrypto;  
48 -import com.google.android.exoplayer2.drm.FrameworkMediaDrm;  
49 -import com.google.android.exoplayer2.drm.HttpMediaDrmCallback;  
50 -import com.google.android.exoplayer2.drm.MediaDrmCallback;  
51 -import com.google.android.exoplayer2.mediacodec.MediaCodecRenderer.DecoderInitializationException;  
52 -import com.google.android.exoplayer2.mediacodec.MediaCodecUtil.DecoderQueryException;  
53 -import com.google.android.exoplayer2.offline.DownloadHelper;  
54 -import com.google.android.exoplayer2.offline.DownloadRequest;  
55 -import com.google.android.exoplayer2.source.BehindLiveWindowException;  
56 -import com.google.android.exoplayer2.source.ConcatenatingMediaSource;  
57 -import com.google.android.exoplayer2.source.MediaSource;  
58 -import com.google.android.exoplayer2.source.MediaSourceFactory;  
59 -import com.google.android.exoplayer2.source.MergingMediaSource;  
60 -import com.google.android.exoplayer2.source.ProgressiveMediaSource;  
61 -import com.google.android.exoplayer2.source.SingleSampleMediaSource;  
62 -import com.google.android.exoplayer2.source.TrackGroupArray;  
63 -import com.google.android.exoplayer2.source.ads.AdsLoader;  
64 -import com.google.android.exoplayer2.source.ads.AdsMediaSource;  
65 -import com.google.android.exoplayer2.source.dash.DashMediaSource;  
66 -import com.google.android.exoplayer2.source.hls.HlsMediaSource;  
67 -import com.google.android.exoplayer2.source.smoothstreaming.SsMediaSource;  
68 -import com.google.android.exoplayer2.trackselection.AdaptiveTrackSelection;  
69 -import com.google.android.exoplayer2.trackselection.DefaultTrackSelector;  
70 -import com.google.android.exoplayer2.trackselection.MappingTrackSelector.MappedTrackInfo;  
71 -import com.google.android.exoplayer2.trackselection.RandomTrackSelection;  
72 -import com.google.android.exoplayer2.trackselection.TrackSelection;  
73 -import com.google.android.exoplayer2.trackselection.TrackSelectionArray;  
74 -import com.google.android.exoplayer2.ui.DebugTextViewHelper;  
75 -import com.google.android.exoplayer2.ui.PlayerControlView;  
76 -import com.google.android.exoplayer2.ui.PlayerView;  
77 -import com.google.android.exoplayer2.ui.spherical.SphericalGLSurfaceView;  
78 -import com.google.android.exoplayer2.upstream.DataSource;  
79 -import com.google.android.exoplayer2.upstream.HttpDataSource;  
80 -import com.google.android.exoplayer2.util.ErrorMessageProvider;  
81 -import com.google.android.exoplayer2.util.EventLogger;  
82 -import com.google.android.exoplayer2.util.Util;  
83 -import java.lang.reflect.Constructor;  
84 -import java.net.CookieHandler;  
85 -import java.net.CookieManager;  
86 -import java.net.CookiePolicy;  
87 -  
88 -/** An activity that plays media using {@link SimpleExoPlayer}. */  
89 -public class PlayerActivity extends AppCompatActivity  
90 - implements OnClickListener, PlaybackPreparer, PlayerControlView.VisibilityListener {  
91 -  
92 - // Activity extras.  
93 -  
94 - public static final String SPHERICAL_STEREO_MODE_EXTRA = "spherical_stereo_mode";  
95 - public static final String SPHERICAL_STEREO_MODE_MONO = "mono";  
96 - public static final String SPHERICAL_STEREO_MODE_TOP_BOTTOM = "top_bottom";  
97 - public static final String SPHERICAL_STEREO_MODE_LEFT_RIGHT = "left_right";  
98 -  
99 - // Actions.  
100 -  
101 - public static final String ACTION_VIEW = "com.google.android.exoplayer.demo.action.VIEW";  
102 - public static final String ACTION_VIEW_LIST =  
103 - "com.google.android.exoplayer.demo.action.VIEW_LIST";  
104 -  
105 - // Player configuration extras.  
106 -  
107 - public static final String ABR_ALGORITHM_EXTRA = "abr_algorithm";  
108 - public static final String ABR_ALGORITHM_DEFAULT = "default";  
109 - public static final String ABR_ALGORITHM_RANDOM = "random";  
110 -  
111 - // Media item configuration extras.  
112 -  
113 - public static final String URI_EXTRA = "uri";  
114 - public static final String EXTENSION_EXTRA = "extension";  
115 - public static final String IS_LIVE_EXTRA = "is_live";  
116 -  
117 - public static final String DRM_SCHEME_EXTRA = "drm_scheme";  
118 - public static final String DRM_LICENSE_URL_EXTRA = "drm_license_url";  
119 - public static final String DRM_KEY_REQUEST_PROPERTIES_EXTRA = "drm_key_request_properties";  
120 - public static final String DRM_MULTI_SESSION_EXTRA = "drm_multi_session";  
121 - public static final String PREFER_EXTENSION_DECODERS_EXTRA = "prefer_extension_decoders";  
122 - public static final String TUNNELING_EXTRA = "tunneling";  
123 - public static final String AD_TAG_URI_EXTRA = "ad_tag_uri";  
124 - public static final String SUBTITLE_URI_EXTRA = "subtitle_uri";  
125 - public static final String SUBTITLE_MIME_TYPE_EXTRA = "subtitle_mime_type";  
126 - public static final String SUBTITLE_LANGUAGE_EXTRA = "subtitle_language";  
127 - // For backwards compatibility only.  
128 - public static final String DRM_SCHEME_UUID_EXTRA = "drm_scheme_uuid";  
129 -  
130 - // Saved instance state keys.  
131 -  
132 - private static final String KEY_TRACK_SELECTOR_PARAMETERS = "track_selector_parameters";  
133 - private static final String KEY_WINDOW = "window";  
134 - private static final String KEY_POSITION = "position";  
135 - private static final String KEY_AUTO_PLAY = "auto_play";  
136 -  
137 - private static final CookieManager DEFAULT_COOKIE_MANAGER;  
138 - static {  
139 - DEFAULT_COOKIE_MANAGER = new CookieManager();  
140 - DEFAULT_COOKIE_MANAGER.setCookiePolicy(CookiePolicy.ACCEPT_ORIGINAL_SERVER);  
141 - }  
142 -  
143 - private PlayerView playerView;  
144 - private LinearLayout debugRootView;  
145 - private Button selectTracksButton;  
146 - private TextView debugTextView;  
147 - private boolean isShowingTrackSelectionDialog;  
148 -  
149 - private DataSource.Factory dataSourceFactory;  
150 - private SimpleExoPlayer player;  
151 - private MediaSource mediaSource;  
152 - private DefaultTrackSelector trackSelector;  
153 - private DefaultTrackSelector.Parameters trackSelectorParameters;  
154 - private DebugTextViewHelper debugViewHelper;  
155 - private TrackGroupArray lastSeenTrackGroupArray;  
156 -  
157 - private boolean startAutoPlay;  
158 - private int startWindow;  
159 - private long startPosition;  
160 -  
161 - // Fields used only for ad playback. The ads loader is loaded via reflection.  
162 -  
163 - private AdsLoader adsLoader;  
164 - private Uri loadedAdTagUri;  
165 -  
166 - // Activity lifecycle  
167 -  
168 - @Override  
169 - public void onCreate(Bundle savedInstanceState) {  
170 - Intent intent = getIntent();  
171 - String sphericalStereoMode = intent.getStringExtra(SPHERICAL_STEREO_MODE_EXTRA);  
172 - if (sphericalStereoMode != null) {  
173 - setTheme(R.style.PlayerTheme_Spherical);  
174 - }  
175 - super.onCreate(savedInstanceState);  
176 - dataSourceFactory = buildDataSourceFactory();  
177 - if (CookieHandler.getDefault() != DEFAULT_COOKIE_MANAGER) {  
178 - CookieHandler.setDefault(DEFAULT_COOKIE_MANAGER);  
179 - }  
180 -  
181 - setContentView(R.layout.player_activity);  
182 - debugRootView = findViewById(R.id.controls_root);  
183 - debugTextView = findViewById(R.id.debug_text_view);  
184 - selectTracksButton = findViewById(R.id.select_tracks_button);  
185 - selectTracksButton.setOnClickListener(this);  
186 -  
187 - playerView = findViewById(R.id.player_view);  
188 - playerView.setControllerVisibilityListener(this);  
189 - playerView.setErrorMessageProvider(new PlayerErrorMessageProvider());  
190 - playerView.requestFocus();  
191 - if (sphericalStereoMode != null) {  
192 - int stereoMode;  
193 - if (SPHERICAL_STEREO_MODE_MONO.equals(sphericalStereoMode)) {  
194 - stereoMode = C.STEREO_MODE_MONO;  
195 - } else if (SPHERICAL_STEREO_MODE_TOP_BOTTOM.equals(sphericalStereoMode)) {  
196 - stereoMode = C.STEREO_MODE_TOP_BOTTOM;  
197 - } else if (SPHERICAL_STEREO_MODE_LEFT_RIGHT.equals(sphericalStereoMode)) {  
198 - stereoMode = C.STEREO_MODE_LEFT_RIGHT;  
199 - } else {  
200 - showToast(R.string.error_unrecognized_stereo_mode);  
201 - finish();  
202 - return;  
203 - }  
204 - ((SphericalGLSurfaceView) playerView.getVideoSurfaceView()).setDefaultStereoMode(stereoMode);  
205 - }  
206 -  
207 - if (savedInstanceState != null) {  
208 - trackSelectorParameters = savedInstanceState.getParcelable(KEY_TRACK_SELECTOR_PARAMETERS);  
209 - startAutoPlay = savedInstanceState.getBoolean(KEY_AUTO_PLAY);  
210 - startWindow = savedInstanceState.getInt(KEY_WINDOW);  
211 - startPosition = savedInstanceState.getLong(KEY_POSITION);  
212 - } else {  
213 - DefaultTrackSelector.ParametersBuilder builder =  
214 - new DefaultTrackSelector.ParametersBuilder(/* context= */ this);  
215 - boolean tunneling = intent.getBooleanExtra(TUNNELING_EXTRA, false);  
216 - if (Util.SDK_INT >= 21 && tunneling) {  
217 - builder.setTunnelingAudioSessionId(C.generateAudioSessionIdV21(/* context= */ this));  
218 - }  
219 - trackSelectorParameters = builder.build();  
220 - clearStartPosition();  
221 - }  
222 - }  
223 -  
224 - @Override  
225 - public void onNewIntent(Intent intent) {  
226 - super.onNewIntent(intent);  
227 - releasePlayer();  
228 - releaseAdsLoader();  
229 - clearStartPosition();  
230 - setIntent(intent);  
231 - }  
232 -  
233 - @Override  
234 - public void onStart() {  
235 - super.onStart();  
236 - if (Util.SDK_INT > 23) {  
237 - initializePlayer();  
238 - if (playerView != null) {  
239 - playerView.onResume();  
240 - }  
241 - }  
242 - }  
243 -  
244 - @Override  
245 - public void onResume() {  
246 - super.onResume();  
247 - if (Util.SDK_INT <= 23 || player == null) {  
248 - initializePlayer();  
249 - if (playerView != null) {  
250 - playerView.onResume();  
251 - }  
252 - }  
253 - }  
254 -  
255 - @Override  
256 - public void onPause() {  
257 - super.onPause();  
258 - if (Util.SDK_INT <= 23) {  
259 - if (playerView != null) {  
260 - playerView.onPause();  
261 - }  
262 - releasePlayer();  
263 - }  
264 - }  
265 -  
266 - @Override  
267 - public void onStop() {  
268 - super.onStop();  
269 - if (Util.SDK_INT > 23) {  
270 - if (playerView != null) {  
271 - playerView.onPause();  
272 - }  
273 - releasePlayer();  
274 - }  
275 - }  
276 -  
277 - @Override  
278 - public void onDestroy() {  
279 - super.onDestroy();  
280 - releaseAdsLoader();  
281 - }  
282 -  
283 - @Override  
284 - public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,  
285 - @NonNull int[] grantResults) {  
286 - if (grantResults.length == 0) {  
287 - // Empty results are triggered if a permission is requested while another request was already  
288 - // pending and can be safely ignored in this case.  
289 - return;  
290 - }  
291 - if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {  
292 - initializePlayer();  
293 - } else {  
294 - showToast(R.string.storage_permission_denied);  
295 - finish();  
296 - }  
297 - }  
298 -  
299 - @Override  
300 - public void onSaveInstanceState(Bundle outState) {  
301 - super.onSaveInstanceState(outState);  
302 - updateTrackSelectorParameters();  
303 - updateStartPosition();  
304 - outState.putParcelable(KEY_TRACK_SELECTOR_PARAMETERS, trackSelectorParameters);  
305 - outState.putBoolean(KEY_AUTO_PLAY, startAutoPlay);  
306 - outState.putInt(KEY_WINDOW, startWindow);  
307 - outState.putLong(KEY_POSITION, startPosition);  
308 - }  
309 -  
310 - // Activity input  
311 -  
312 - @Override  
313 - public boolean dispatchKeyEvent(KeyEvent event) {  
314 - // See whether the player view wants to handle media or DPAD keys events.  
315 - return playerView.dispatchKeyEvent(event) || super.dispatchKeyEvent(event);  
316 - }  
317 -  
318 - // OnClickListener methods  
319 -  
320 - @Override  
321 - public void onClick(View view) {  
322 - if (view == selectTracksButton  
323 - && !isShowingTrackSelectionDialog  
324 - && TrackSelectionDialog.willHaveContent(trackSelector)) {  
325 - isShowingTrackSelectionDialog = true;  
326 - TrackSelectionDialog trackSelectionDialog =  
327 - TrackSelectionDialog.createForTrackSelector(  
328 - trackSelector,  
329 - /* onDismissListener= */ dismissedDialog -> isShowingTrackSelectionDialog = false);  
330 - trackSelectionDialog.show(getSupportFragmentManager(), /* tag= */ null);  
331 - }  
332 - }  
333 -  
334 - // PlaybackControlView.PlaybackPreparer implementation  
335 -  
336 - @Override  
337 - public void preparePlayback() {  
338 - player.retry();  
339 - }  
340 -  
341 - // PlaybackControlView.VisibilityListener implementation  
342 -  
343 - @Override  
344 - public void onVisibilityChange(int visibility) {  
345 - debugRootView.setVisibility(visibility);  
346 - }  
347 -  
348 - // Internal methods  
349 -  
350 - private void initializePlayer() {  
351 - if (player == null) {  
352 - Intent intent = getIntent();  
353 -  
354 - mediaSource = createTopLevelMediaSource(intent);  
355 - if (mediaSource == null) {  
356 - return;  
357 - }  
358 -  
359 - TrackSelection.Factory trackSelectionFactory;  
360 - String abrAlgorithm = intent.getStringExtra(ABR_ALGORITHM_EXTRA);  
361 - if (abrAlgorithm == null || ABR_ALGORITHM_DEFAULT.equals(abrAlgorithm)) {  
362 - trackSelectionFactory = new AdaptiveTrackSelection.Factory();  
363 - } else if (ABR_ALGORITHM_RANDOM.equals(abrAlgorithm)) {  
364 - trackSelectionFactory = new RandomTrackSelection.Factory();  
365 - } else {  
366 - showToast(R.string.error_unrecognized_abr_algorithm);  
367 - finish();  
368 - return;  
369 - }  
370 -  
371 - boolean preferExtensionDecoders =  
372 - intent.getBooleanExtra(PREFER_EXTENSION_DECODERS_EXTRA, false);  
373 - RenderersFactory renderersFactory =  
374 - ((DemoApplication) getApplication()).buildRenderersFactory(preferExtensionDecoders);  
375 -  
376 - trackSelector = new DefaultTrackSelector(/* context= */ this, trackSelectionFactory);  
377 - trackSelector.setParameters(trackSelectorParameters);  
378 - lastSeenTrackGroupArray = null;  
379 -  
380 - player =  
381 - new SimpleExoPlayer.Builder(/* context= */ this, renderersFactory)  
382 - .setTrackSelector(trackSelector)  
383 - .build();  
384 - player.addListener(new PlayerEventListener());  
385 - player.setPlayWhenReady(startAutoPlay);  
386 - player.addAnalyticsListener(new EventLogger(trackSelector));  
387 - playerView.setPlayer(player);  
388 - playerView.setPlaybackPreparer(this);  
389 - debugViewHelper = new DebugTextViewHelper(player, debugTextView);  
390 - debugViewHelper.start();  
391 - if (adsLoader != null) {  
392 - adsLoader.setPlayer(player);  
393 - }  
394 - }  
395 - boolean haveStartPosition = startWindow != C.INDEX_UNSET;  
396 - if (haveStartPosition) {  
397 - player.seekTo(startWindow, startPosition);  
398 - }  
399 - player.prepare(mediaSource, !haveStartPosition, false);  
400 - updateButtonVisibility();  
401 - }  
402 -  
403 - @Nullable  
404 - private MediaSource createTopLevelMediaSource(Intent intent) {  
405 - String action = intent.getAction();  
406 - boolean actionIsListView = ACTION_VIEW_LIST.equals(action);  
407 - if (!actionIsListView && !ACTION_VIEW.equals(action)) {  
408 - showToast(getString(R.string.unexpected_intent_action, action));  
409 - finish();  
410 - return null;  
411 - }  
412 -  
413 - Sample intentAsSample = Sample.createFromIntent(intent);  
414 - Sample.UriSample[] samples =  
415 - intentAsSample instanceof Sample.PlaylistSample  
416 - ? ((Sample.PlaylistSample) intentAsSample).children  
417 - : new Sample.UriSample[] {(Sample.UriSample) intentAsSample};  
418 -  
419 - boolean seenAdsTagUri = false;  
420 - for (Sample.UriSample sample : samples) {  
421 - seenAdsTagUri |= sample.adTagUri != null;  
422 - if (!Util.checkCleartextTrafficPermitted(sample.uri)) {  
423 - showToast(R.string.error_cleartext_not_permitted);  
424 - return null;  
425 - }  
426 - if (Util.maybeRequestReadExternalStoragePermission(/* activity= */ this, sample.uri)) {  
427 - // The player will be reinitialized if the permission is granted.  
428 - return null;  
429 - }  
430 - }  
431 -  
432 - MediaSource[] mediaSources = new MediaSource[samples.length];  
433 - for (int i = 0; i < samples.length; i++) {  
434 - mediaSources[i] = createLeafMediaSource(samples[i]);  
435 - Sample.SubtitleInfo subtitleInfo = samples[i].subtitleInfo;  
436 - if (subtitleInfo != null) {  
437 - Format subtitleFormat =  
438 - Format.createTextSampleFormat(  
439 - /* id= */ null,  
440 - subtitleInfo.mimeType,  
441 - C.SELECTION_FLAG_DEFAULT,  
442 - subtitleInfo.language);  
443 - MediaSource subtitleMediaSource =  
444 - new SingleSampleMediaSource.Factory(dataSourceFactory)  
445 - .createMediaSource(subtitleInfo.uri, subtitleFormat, C.TIME_UNSET);  
446 - mediaSources[i] = new MergingMediaSource(mediaSources[i], subtitleMediaSource);  
447 - }  
448 - }  
449 - MediaSource mediaSource =  
450 - mediaSources.length == 1 ? mediaSources[0] : new ConcatenatingMediaSource(mediaSources);  
451 -  
452 - if (seenAdsTagUri) {  
453 - Uri adTagUri = samples[0].adTagUri;  
454 - if (actionIsListView) {  
455 - showToast(R.string.unsupported_ads_in_concatenation);  
456 - } else {  
457 - if (!adTagUri.equals(loadedAdTagUri)) {  
458 - releaseAdsLoader();  
459 - loadedAdTagUri = adTagUri;  
460 - }  
461 - MediaSource adsMediaSource = createAdsMediaSource(mediaSource, adTagUri);  
462 - if (adsMediaSource != null) {  
463 - mediaSource = adsMediaSource;  
464 - } else {  
465 - showToast(R.string.ima_not_loaded);  
466 - }  
467 - }  
468 - } else {  
469 - releaseAdsLoader();  
470 - }  
471 -  
472 - return mediaSource;  
473 - }  
474 -  
475 - private MediaSource createLeafMediaSource(Sample.UriSample parameters) {  
476 - Sample.DrmInfo drmInfo = parameters.drmInfo;  
477 - int errorStringId = R.string.error_drm_unknown;  
478 - DrmSessionManager<ExoMediaCrypto> drmSessionManager = null;  
479 - if (drmInfo == null) {  
480 - drmSessionManager = DrmSessionManager.getDummyDrmSessionManager();  
481 - } else if (Util.SDK_INT < 18) {  
482 - errorStringId = R.string.error_drm_unsupported_before_api_18;  
483 - } else if (!MediaDrm.isCryptoSchemeSupported(drmInfo.drmScheme)) {  
484 - errorStringId = R.string.error_drm_unsupported_scheme;  
485 - } else {  
486 - MediaDrmCallback mediaDrmCallback =  
487 - createMediaDrmCallback(drmInfo.drmLicenseUrl, drmInfo.drmKeyRequestProperties);  
488 - drmSessionManager =  
489 - new DefaultDrmSessionManager.Builder()  
490 - .setUuidAndExoMediaDrmProvider(drmInfo.drmScheme, FrameworkMediaDrm.DEFAULT_PROVIDER)  
491 - .setMultiSession(drmInfo.drmMultiSession)  
492 - .build(mediaDrmCallback);  
493 - }  
494 -  
495 - if (drmSessionManager == null) {  
496 - showToast(errorStringId);  
497 - finish();  
498 - return null;  
499 - }  
500 -  
501 - DownloadRequest downloadRequest =  
502 - ((DemoApplication) getApplication())  
503 - .getDownloadTracker()  
504 - .getDownloadRequest(parameters.uri);  
505 - if (downloadRequest != null) {  
506 - return DownloadHelper.createMediaSource(downloadRequest, dataSourceFactory);  
507 - }  
508 - return createLeafMediaSource(parameters.uri, parameters.extension, drmSessionManager);  
509 - }  
510 -  
511 - private MediaSource createLeafMediaSource(  
512 - Uri uri, String extension, DrmSessionManager<ExoMediaCrypto> drmSessionManager) {  
513 - @ContentType int type = Util.inferContentType(uri, extension);  
514 - switch (type) {  
515 - case C.TYPE_DASH:  
516 - return new DashMediaSource.Factory(dataSourceFactory)  
517 - .setDrmSessionManager(drmSessionManager)  
518 - .createMediaSource(uri);  
519 - case C.TYPE_SS:  
520 - return new SsMediaSource.Factory(dataSourceFactory)  
521 - .setDrmSessionManager(drmSessionManager)  
522 - .createMediaSource(uri);  
523 - case C.TYPE_HLS:  
524 - return new HlsMediaSource.Factory(dataSourceFactory)  
525 - .setDrmSessionManager(drmSessionManager)  
526 - .createMediaSource(uri);  
527 - case C.TYPE_OTHER:  
528 - return new ProgressiveMediaSource.Factory(dataSourceFactory)  
529 - .setDrmSessionManager(drmSessionManager)  
530 - .createMediaSource(uri);  
531 - default:  
532 - throw new IllegalStateException("Unsupported type: " + type);  
533 - }  
534 - }  
535 -  
536 - private HttpMediaDrmCallback createMediaDrmCallback(  
537 - String licenseUrl, String[] keyRequestPropertiesArray) {  
538 - HttpDataSource.Factory licenseDataSourceFactory =  
539 - ((DemoApplication) getApplication()).buildHttpDataSourceFactory();  
540 - HttpMediaDrmCallback drmCallback =  
541 - new HttpMediaDrmCallback(licenseUrl, licenseDataSourceFactory);  
542 - if (keyRequestPropertiesArray != null) {  
543 - for (int i = 0; i < keyRequestPropertiesArray.length - 1; i += 2) {  
544 - drmCallback.setKeyRequestProperty(keyRequestPropertiesArray[i],  
545 - keyRequestPropertiesArray[i + 1]);  
546 - }  
547 - }  
548 - return drmCallback;  
549 - }  
550 -  
551 - private void releasePlayer() {  
552 - if (player != null) {  
553 - updateTrackSelectorParameters();  
554 - updateStartPosition();  
555 - debugViewHelper.stop();  
556 - debugViewHelper = null;  
557 - player.release();  
558 - player = null;  
559 - mediaSource = null;  
560 - trackSelector = null;  
561 - }  
562 - if (adsLoader != null) {  
563 - adsLoader.setPlayer(null);  
564 - }  
565 - }  
566 -  
567 - private void releaseAdsLoader() {  
568 - if (adsLoader != null) {  
569 - adsLoader.release();  
570 - adsLoader = null;  
571 - loadedAdTagUri = null;  
572 - playerView.getOverlayFrameLayout().removeAllViews();  
573 - }  
574 - }  
575 -  
576 - private void updateTrackSelectorParameters() {  
577 - if (trackSelector != null) {  
578 - trackSelectorParameters = trackSelector.getParameters();  
579 - }  
580 - }  
581 -  
582 - private void updateStartPosition() {  
583 - if (player != null) {  
584 - startAutoPlay = player.getPlayWhenReady();  
585 - startWindow = player.getCurrentWindowIndex();  
586 - startPosition = Math.max(0, player.getContentPosition());  
587 - }  
588 - }  
589 -  
590 - private void clearStartPosition() {  
591 - startAutoPlay = true;  
592 - startWindow = C.INDEX_UNSET;  
593 - startPosition = C.TIME_UNSET;  
594 - }  
595 -  
596 - /** Returns a new DataSource factory. */  
597 - private DataSource.Factory buildDataSourceFactory() {  
598 - return ((DemoApplication) getApplication()).buildDataSourceFactory();  
599 - }  
600 -  
601 - /** Returns an ads media source, reusing the ads loader if one exists. */  
602 - @Nullable  
603 - private MediaSource createAdsMediaSource(MediaSource mediaSource, Uri adTagUri) {  
604 - // Load the extension source using reflection so the demo app doesn't have to depend on it.  
605 - // The ads loader is reused for multiple playbacks, so that ad playback can resume.  
606 - try {  
607 - Class<?> loaderClass = Class.forName("com.google.android.exoplayer2.ext.ima.ImaAdsLoader");  
608 - if (adsLoader == null) {  
609 - // Full class names used so the LINT.IfChange rule triggers should any of the classes move.  
610 - // LINT.IfChange  
611 - Constructor<? extends AdsLoader> loaderConstructor =  
612 - loaderClass  
613 - .asSubclass(AdsLoader.class)  
614 - .getConstructor(android.content.Context.class, Uri.class);  
615 - // LINT.ThenChange(../../../../../../../../proguard-rules.txt)  
616 - adsLoader = loaderConstructor.newInstance(this, adTagUri);  
617 - }  
618 - MediaSourceFactory adMediaSourceFactory =  
619 - new MediaSourceFactory() {  
620 - @Override  
621 - public MediaSource createMediaSource(Uri uri) {  
622 - return PlayerActivity.this.createLeafMediaSource(  
623 - uri, /* extension=*/ null, DrmSessionManager.getDummyDrmSessionManager());  
624 - }  
625 -  
626 - @Override  
627 - public int[] getSupportedTypes() {  
628 - return new int[] {C.TYPE_DASH, C.TYPE_SS, C.TYPE_HLS, C.TYPE_OTHER};  
629 - }  
630 - };  
631 - return new AdsMediaSource(mediaSource, adMediaSourceFactory, adsLoader, playerView);  
632 - } catch (ClassNotFoundException e) {  
633 - // IMA extension not loaded.  
634 - return null;  
635 - } catch (Exception e) {  
636 - throw new RuntimeException(e);  
637 - }  
638 - }  
639 -  
640 - // User controls  
641 -  
642 - private void updateButtonVisibility() {  
643 - selectTracksButton.setEnabled(  
644 - player != null && TrackSelectionDialog.willHaveContent(trackSelector));  
645 - }  
646 -  
647 - private void showControls() {  
648 - debugRootView.setVisibility(View.VISIBLE);  
649 - }  
650 -  
651 - private void showToast(int messageId) {  
652 - showToast(getString(messageId));  
653 - }  
654 -  
655 - private void showToast(String message) {  
656 - Toast.makeText(getApplicationContext(), message, Toast.LENGTH_LONG).show();  
657 - }  
658 -  
659 - private static boolean isBehindLiveWindow(ExoPlaybackException e) {  
660 - if (e.type != ExoPlaybackException.TYPE_SOURCE) {  
661 - return false;  
662 - }  
663 - Throwable cause = e.getSourceException();  
664 - while (cause != null) {  
665 - if (cause instanceof BehindLiveWindowException) {  
666 - return true;  
667 - }  
668 - cause = cause.getCause();  
669 - }  
670 - return false;  
671 - }  
672 -  
673 - private class PlayerEventListener implements Player.EventListener {  
674 -  
675 - @Override  
676 - public void onPlayerStateChanged(boolean playWhenReady, @Player.State int playbackState) {  
677 - if (playbackState == Player.STATE_ENDED) {  
678 - showControls();  
679 - }  
680 - updateButtonVisibility();  
681 - }  
682 -  
683 - @Override  
684 - public void onPlayerError(ExoPlaybackException e) {  
685 - if (isBehindLiveWindow(e)) {  
686 - clearStartPosition();  
687 - initializePlayer();  
688 - } else {  
689 - updateButtonVisibility();  
690 - showControls();  
691 - }  
692 - }  
693 -  
694 - @Override  
695 - @SuppressWarnings("ReferenceEquality")  
696 - public void onTracksChanged(TrackGroupArray trackGroups, TrackSelectionArray trackSelections) {  
697 - updateButtonVisibility();  
698 - if (trackGroups != lastSeenTrackGroupArray) {  
699 - MappedTrackInfo mappedTrackInfo = trackSelector.getCurrentMappedTrackInfo();  
700 - if (mappedTrackInfo != null) {  
701 - if (mappedTrackInfo.getTypeSupport(C.TRACK_TYPE_VIDEO)  
702 - == MappedTrackInfo.RENDERER_SUPPORT_UNSUPPORTED_TRACKS) {  
703 - showToast(R.string.error_unsupported_video);  
704 - }  
705 - if (mappedTrackInfo.getTypeSupport(C.TRACK_TYPE_AUDIO)  
706 - == MappedTrackInfo.RENDERER_SUPPORT_UNSUPPORTED_TRACKS) {  
707 - showToast(R.string.error_unsupported_audio);  
708 - }  
709 - }  
710 - lastSeenTrackGroupArray = trackGroups;  
711 - }  
712 - }  
713 - }  
714 -  
715 - private class PlayerErrorMessageProvider implements ErrorMessageProvider<ExoPlaybackException> {  
716 -  
717 - @Override  
718 - public Pair<Integer, String> getErrorMessage(ExoPlaybackException e) {  
719 - String errorString = getString(R.string.error_generic);  
720 - if (e.type == ExoPlaybackException.TYPE_RENDERER) {  
721 - Exception cause = e.getRendererException();  
722 - if (cause instanceof DecoderInitializationException) {  
723 - // Special case for decoder initialization failures.  
724 - DecoderInitializationException decoderInitializationException =  
725 - (DecoderInitializationException) cause;  
726 - if (decoderInitializationException.codecInfo == null) {  
727 - if (decoderInitializationException.getCause() instanceof DecoderQueryException) {  
728 - errorString = getString(R.string.error_querying_decoders);  
729 - } else if (decoderInitializationException.secureDecoderRequired) {  
730 - errorString =  
731 - getString(  
732 - R.string.error_no_secure_decoder, decoderInitializationException.mimeType);  
733 - } else {  
734 - errorString =  
735 - getString(R.string.error_no_decoder, decoderInitializationException.mimeType);  
736 - }  
737 - } else {  
738 - errorString =  
739 - getString(  
740 - R.string.error_instantiating_decoder,  
741 - decoderInitializationException.codecInfo.name);  
742 - }  
743 - }  
744 - }  
745 - return Pair.create(0, errorString);  
746 - }  
747 - }  
748 -}  
app/strike/src/main/java/com/cnlive/strike/demo/exoplayer/demo/Sample.java deleted 100644 → 0
1 -/*  
2 - * Copyright (C) 2019 The Android Open Source Project  
3 - *  
4 - * Licensed under the Apache License, Version 2.0 (the "License");  
5 - * you may not use this file except in compliance with the License.  
6 - * You may obtain a copy of the License at  
7 - *  
8 - * http://www.apache.org/licenses/LICENSE-2.0  
9 - *  
10 - * Unless required by applicable law or agreed to in writing, software  
11 - * distributed under the License is distributed on an "AS IS" BASIS,  
12 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  
13 - * See the License for the specific language governing permissions and  
14 - * limitations under the License.  
15 - */  
16 -package com.cnlive.strike.demo.exoplayer.demo;  
17 -  
18 -import static com.cnlive.strike.demo.exoplayer.demo.PlayerActivity.ACTION_VIEW_LIST;  
19 -import static com.cnlive.strike.demo.exoplayer.demo.PlayerActivity.AD_TAG_URI_EXTRA;  
20 -import static com.cnlive.strike.demo.exoplayer.demo.PlayerActivity.DRM_KEY_REQUEST_PROPERTIES_EXTRA;  
21 -import static com.cnlive.strike.demo.exoplayer.demo.PlayerActivity.DRM_LICENSE_URL_EXTRA;  
22 -import static com.cnlive.strike.demo.exoplayer.demo.PlayerActivity.DRM_MULTI_SESSION_EXTRA;  
23 -import static com.cnlive.strike.demo.exoplayer.demo.PlayerActivity.DRM_SCHEME_EXTRA;  
24 -import static com.cnlive.strike.demo.exoplayer.demo.PlayerActivity.DRM_SCHEME_UUID_EXTRA;  
25 -import static com.cnlive.strike.demo.exoplayer.demo.PlayerActivity.EXTENSION_EXTRA;  
26 -import static com.cnlive.strike.demo.exoplayer.demo.PlayerActivity.IS_LIVE_EXTRA;  
27 -import static com.cnlive.strike.demo.exoplayer.demo.PlayerActivity.SUBTITLE_LANGUAGE_EXTRA;  
28 -import static com.cnlive.strike.demo.exoplayer.demo.PlayerActivity.SUBTITLE_MIME_TYPE_EXTRA;  
29 -import static com.cnlive.strike.demo.exoplayer.demo.PlayerActivity.SUBTITLE_URI_EXTRA;  
30 -import static com.cnlive.strike.demo.exoplayer.demo.PlayerActivity.URI_EXTRA;  
31 -  
32 -import android.content.Intent;  
33 -import android.net.Uri;  
34 -import androidx.annotation.Nullable;  
35 -import com.google.android.exoplayer2.util.Assertions;  
36 -import com.google.android.exoplayer2.util.Util;  
37 -import java.util.ArrayList;  
38 -import java.util.UUID;  
39 -  
40 -/* package */public abstract class Sample {  
41 -  
42 - public static final class UriSample extends Sample {  
43 -  
44 - public static UriSample createFromIntent(Uri uri, Intent intent, String extrasKeySuffix) {  
45 - String extension = intent.getStringExtra(EXTENSION_EXTRA + extrasKeySuffix);  
46 - String adsTagUriString = intent.getStringExtra(AD_TAG_URI_EXTRA + extrasKeySuffix);  
47 - boolean isLive =  
48 - intent.getBooleanExtra(IS_LIVE_EXTRA + extrasKeySuffix, /* defaultValue= */ false);  
49 - Uri adTagUri = adsTagUriString != null ? Uri.parse(adsTagUriString) : null;  
50 - return new UriSample(  
51 - /* name= */ null,  
52 - uri,  
53 - extension,  
54 - isLive,  
55 - DrmInfo.createFromIntent(intent, extrasKeySuffix),  
56 - adTagUri,  
57 - /* sphericalStereoMode= */ null,  
58 - SubtitleInfo.createFromIntent(intent, extrasKeySuffix));  
59 - }  
60 -  
61 - public final Uri uri;  
62 - public final String extension;  
63 - public final boolean isLive;  
64 - public final DrmInfo drmInfo;  
65 - public final Uri adTagUri;  
66 - @Nullable public final String sphericalStereoMode;  
67 - @Nullable SubtitleInfo subtitleInfo;  
68 -  
69 - public UriSample(  
70 - String name,  
71 - Uri uri,  
72 - String extension,  
73 - boolean isLive,  
74 - DrmInfo drmInfo,  
75 - Uri adTagUri,  
76 - @Nullable String sphericalStereoMode,  
77 - @Nullable SubtitleInfo subtitleInfo) {  
78 - super(name);  
79 - this.uri = uri;  
80 - this.extension = extension;  
81 - this.isLive = isLive;  
82 - this.drmInfo = drmInfo;  
83 - this.adTagUri = adTagUri;  
84 - this.sphericalStereoMode = sphericalStereoMode;  
85 - this.subtitleInfo = subtitleInfo;  
86 - }  
87 -  
88 - @Override  
89 - public void addToIntent(Intent intent) {  
90 - intent.setAction(PlayerActivity.ACTION_VIEW).setData(uri);  
91 - intent.putExtra(IS_LIVE_EXTRA, isLive);  
92 - intent.putExtra(PlayerActivity.SPHERICAL_STEREO_MODE_EXTRA, sphericalStereoMode);  
93 - addPlayerConfigToIntent(intent, /* extrasKeySuffix= */ "");  
94 - }  
95 -  
96 - public void addToPlaylistIntent(Intent intent, String extrasKeySuffix) {  
97 - intent.putExtra(URI_EXTRA + extrasKeySuffix, uri.toString());  
98 - intent.putExtra(IS_LIVE_EXTRA + extrasKeySuffix, isLive);  
99 - addPlayerConfigToIntent(intent, extrasKeySuffix);  
100 - }  
101 -  
102 - private void addPlayerConfigToIntent(Intent intent, String extrasKeySuffix) {  
103 - intent  
104 - .putExtra(EXTENSION_EXTRA + extrasKeySuffix, extension)  
105 - .putExtra(  
106 - AD_TAG_URI_EXTRA + extrasKeySuffix, adTagUri != null ? adTagUri.toString() : null);  
107 - if (drmInfo != null) {  
108 - drmInfo.addToIntent(intent, extrasKeySuffix);  
109 - }  
110 - if (subtitleInfo != null) {  
111 - subtitleInfo.addToIntent(intent, extrasKeySuffix);  
112 - }  
113 - }  
114 - }  
115 -  
116 - public static final class PlaylistSample extends Sample {  
117 -  
118 - public final UriSample[] children;  
119 -  
120 - public PlaylistSample(String name, UriSample... children) {  
121 - super(name);  
122 - this.children = children;  
123 - }  
124 -  
125 - @Override  
126 - public void addToIntent(Intent intent) {  
127 - intent.setAction(ACTION_VIEW_LIST);  
128 - for (int i = 0; i < children.length; i++) {  
129 - children[i].addToPlaylistIntent(intent, /* extrasKeySuffix= */ "_" + i);  
130 - }  
131 - }  
132 - }  
133 -  
134 - public static final class DrmInfo {  
135 -  
136 - public static DrmInfo createFromIntent(Intent intent, String extrasKeySuffix) {  
137 - String schemeKey = DRM_SCHEME_EXTRA + extrasKeySuffix;  
138 - String schemeUuidKey = DRM_SCHEME_UUID_EXTRA + extrasKeySuffix;  
139 - if (!intent.hasExtra(schemeKey) && !intent.hasExtra(schemeUuidKey)) {  
140 - return null;  
141 - }  
142 - String drmSchemeExtra =  
143 - intent.hasExtra(schemeKey)  
144 - ? intent.getStringExtra(schemeKey)  
145 - : intent.getStringExtra(schemeUuidKey);  
146 - UUID drmScheme = Util.getDrmUuid(drmSchemeExtra);  
147 - String drmLicenseUrl = intent.getStringExtra(DRM_LICENSE_URL_EXTRA + extrasKeySuffix);  
148 - String[] keyRequestPropertiesArray =  
149 - intent.getStringArrayExtra(DRM_KEY_REQUEST_PROPERTIES_EXTRA + extrasKeySuffix);  
150 - boolean drmMultiSession =  
151 - intent.getBooleanExtra(DRM_MULTI_SESSION_EXTRA + extrasKeySuffix, false);  
152 - return new DrmInfo(drmScheme, drmLicenseUrl, keyRequestPropertiesArray, drmMultiSession);  
153 - }  
154 -  
155 - public final UUID drmScheme;  
156 - public final String drmLicenseUrl;  
157 - public final String[] drmKeyRequestProperties;  
158 - public final boolean drmMultiSession;  
159 -  
160 - public DrmInfo(  
161 - UUID drmScheme,  
162 - String drmLicenseUrl,  
163 - String[] drmKeyRequestProperties,  
164 - boolean drmMultiSession) {  
165 - this.drmScheme = drmScheme;  
166 - this.drmLicenseUrl = drmLicenseUrl;  
167 - this.drmKeyRequestProperties = drmKeyRequestProperties;  
168 - this.drmMultiSession = drmMultiSession;  
169 - }  
170 -  
171 - public void addToIntent(Intent intent, String extrasKeySuffix) {  
172 - Assertions.checkNotNull(intent);  
173 - intent.putExtra(DRM_SCHEME_EXTRA + extrasKeySuffix, drmScheme.toString());  
174 - intent.putExtra(DRM_LICENSE_URL_EXTRA + extrasKeySuffix, drmLicenseUrl);  
175 - intent.putExtra(DRM_KEY_REQUEST_PROPERTIES_EXTRA + extrasKeySuffix, drmKeyRequestProperties);  
176 - intent.putExtra(DRM_MULTI_SESSION_EXTRA + extrasKeySuffix, drmMultiSession);  
177 - }  
178 - }  
179 -  
180 - public static final class SubtitleInfo {  
181 -  
182 - @Nullable  
183 - public static SubtitleInfo createFromIntent(Intent intent, String extrasKeySuffix) {  
184 - if (!intent.hasExtra(SUBTITLE_URI_EXTRA + extrasKeySuffix)) {  
185 - return null;  
186 - }  
187 - return new SubtitleInfo(  
188 - Uri.parse(intent.getStringExtra(SUBTITLE_URI_EXTRA + extrasKeySuffix)),  
189 - intent.getStringExtra(SUBTITLE_MIME_TYPE_EXTRA + extrasKeySuffix),  
190 - intent.getStringExtra(SUBTITLE_LANGUAGE_EXTRA + extrasKeySuffix));  
191 - }  
192 -  
193 - public final Uri uri;  
194 - public final String mimeType;  
195 - @Nullable public final String language;  
196 -  
197 - public SubtitleInfo(Uri uri, String mimeType, @Nullable String language) {  
198 - this.uri = Assertions.checkNotNull(uri);  
199 - this.mimeType = Assertions.checkNotNull(mimeType);  
200 - this.language = language;  
201 - }  
202 -  
203 - public void addToIntent(Intent intent, String extrasKeySuffix) {  
204 - intent.putExtra(SUBTITLE_URI_EXTRA + extrasKeySuffix, uri.toString());  
205 - intent.putExtra(SUBTITLE_MIME_TYPE_EXTRA + extrasKeySuffix, mimeType);  
206 - intent.putExtra(SUBTITLE_LANGUAGE_EXTRA + extrasKeySuffix, language);  
207 - }  
208 - }  
209 -  
210 - public static Sample createFromIntent(Intent intent) {  
211 - if (ACTION_VIEW_LIST.equals(intent.getAction())) {  
212 - ArrayList<String> intentUris = new ArrayList<>();  
213 - int index = 0;  
214 - while (intent.hasExtra(URI_EXTRA + "_" + index)) {  
215 - intentUris.add(intent.getStringExtra(URI_EXTRA + "_" + index));  
216 - index++;  
217 - }  
218 - UriSample[] children = new UriSample[intentUris.size()];  
219 - for (int i = 0; i < children.length; i++) {  
220 - Uri uri = Uri.parse(intentUris.get(i));  
221 - children[i] = UriSample.createFromIntent(uri, intent, /* extrasKeySuffix= */ "_" + i);  
222 - }  
223 - return new PlaylistSample(/* name= */ null, children);  
224 - } else {  
225 - return UriSample.createFromIntent(intent.getData(), intent, /* extrasKeySuffix= */ "");  
226 - }  
227 - }  
228 -  
229 - @Nullable public final String name;  
230 -  
231 - public Sample(String name) {  
232 - this.name = name;  
233 - }  
234 -  
235 - public abstract void addToIntent(Intent intent);  
236 -}  
app/strike/src/main/java/com/cnlive/strike/demo/exoplayer/demo/SampleChooserActivity.java deleted 100644 → 0
1 -/*  
2 - * Copyright (C) 2016 The Android Open Source Project  
3 - *  
4 - * Licensed under the Apache License, Version 2.0 (the "License");  
5 - * you may not use this file except in compliance with the License.  
6 - * You may obtain a copy of the License at  
7 - *  
8 - * http://www.apache.org/licenses/LICENSE-2.0  
9 - *  
10 - * Unless required by applicable law or agreed to in writing, software  
11 - * distributed under the License is distributed on an "AS IS" BASIS,  
12 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  
13 - * See the License for the specific language governing permissions and  
14 - * limitations under the License.  
15 - */  
16 -package com.cnlive.strike.demo.exoplayer.demo;  
17 -  
18 -import android.content.Context;  
19 -import android.content.Intent;  
20 -import android.content.res.AssetManager;  
21 -import android.net.Uri;  
22 -import android.os.AsyncTask;  
23 -import android.os.Bundle;  
24 -import android.util.JsonReader;  
25 -import android.view.Menu;  
26 -import android.view.MenuInflater;  
27 -import android.view.MenuItem;  
28 -import android.view.View;  
29 -import android.view.View.OnClickListener;  
30 -import android.view.ViewGroup;  
31 -import android.widget.BaseExpandableListAdapter;  
32 -import android.widget.ExpandableListView;  
33 -import android.widget.ExpandableListView.OnChildClickListener;  
34 -import android.widget.ImageButton;  
35 -import android.widget.TextView;  
36 -import android.widget.Toast;  
37 -import androidx.annotation.Nullable;  
38 -import androidx.appcompat.app.AppCompatActivity;  
39 -  
40 -import com.cnlive.cloud.R;  
41 -import com.cnlive.strike.DemoApplication;  
42 -import com.google.android.exoplayer2.ParserException;  
43 -import com.google.android.exoplayer2.RenderersFactory;  
44 -import com.google.android.exoplayer2.offline.DownloadService;  
45 -import com.google.android.exoplayer2.upstream.DataSource;  
46 -import com.google.android.exoplayer2.upstream.DataSourceInputStream;  
47 -import com.google.android.exoplayer2.upstream.DataSpec;  
48 -import com.google.android.exoplayer2.upstream.DefaultDataSource;  
49 -import com.google.android.exoplayer2.util.Assertions;  
50 -import com.google.android.exoplayer2.util.Log;  
51 -import com.google.android.exoplayer2.util.Util;  
52 -import java.io.IOException;  
53 -import java.io.InputStream;  
54 -import java.io.InputStreamReader;  
55 -import java.util.ArrayList;  
56 -import java.util.Arrays;  
57 -import java.util.Collections;  
58 -import java.util.List;  
59 -  
60 -/** An activity for selecting from a list of media samples. */  
61 -public class SampleChooserActivity extends AppCompatActivity  
62 - implements DownloadTracker.Listener, OnChildClickListener {  
63 -  
64 - private static final String TAG = "SampleChooserActivity";  
65 -  
66 - private boolean useExtensionRenderers;  
67 - private DownloadTracker downloadTracker;  
68 - private SampleAdapter sampleAdapter;  
69 - private MenuItem preferExtensionDecodersMenuItem;  
70 - private MenuItem randomAbrMenuItem;  
71 - private MenuItem tunnelingMenuItem;  
72 -  
73 - @Override  
74 - public void onCreate(Bundle savedInstanceState) {  
75 - super.onCreate(savedInstanceState);  
76 - setContentView(R.layout.sample_chooser_activity);  
77 - sampleAdapter = new SampleAdapter();  
78 - ExpandableListView sampleListView = findViewById(R.id.sample_list);  
79 - sampleListView.setAdapter(sampleAdapter);  
80 - sampleListView.setOnChildClickListener(this);  
81 -  
82 - Intent intent = getIntent();  
83 - String dataUri = intent.getDataString();  
84 - String[] uris;  
85 - if (dataUri != null) {  
86 - uris = new String[] {dataUri};  
87 - } else {  
88 - ArrayList<String> uriList = new ArrayList<>();  
89 - AssetManager assetManager = getAssets();  
90 - try {  
91 - for (String asset : assetManager.list("")) {  
92 - if (asset.endsWith(".exolist.json")) {  
93 - uriList.add("asset:///" + asset);  
94 - }  
95 - }  
96 - } catch (IOException e) {  
97 - Toast.makeText(getApplicationContext(), R.string.sample_list_load_error, Toast.LENGTH_LONG)  
98 - .show();  
99 - }  
100 - uris = new String[uriList.size()];  
101 - uriList.toArray(uris);  
102 - Arrays.sort(uris);  
103 - }  
104 -  
105 - DemoApplication application = (DemoApplication) getApplication();  
106 - useExtensionRenderers = application.useExtensionRenderers();  
107 - downloadTracker = application.getDownloadTracker();  
108 - SampleListLoader loaderTask = new SampleListLoader();  
109 - loaderTask.execute(uris);  
110 -  
111 - // Start the download service if it should be running but it's not currently.  
112 - // Starting the service in the foreground causes notification flicker if there is no scheduled  
113 - // action. Starting it in the background throws an exception if the app is in the background too  
114 - // (e.g. if device screen is locked).  
115 - try {  
116 - DownloadService.start(this, DemoDownloadService.class);  
117 - } catch (IllegalStateException e) {  
118 - DownloadService.startForeground(this, DemoDownloadService.class);  
119 - }  
120 - }  
121 -  
122 - @Override  
123 - public boolean onCreateOptionsMenu(Menu menu) {  
124 - MenuInflater inflater = getMenuInflater();  
125 - inflater.inflate(R.menu.sample_chooser_menu, menu);  
126 - preferExtensionDecodersMenuItem = menu.findItem(R.id.prefer_extension_decoders);  
127 - preferExtensionDecodersMenuItem.setVisible(useExtensionRenderers);  
128 - randomAbrMenuItem = menu.findItem(R.id.random_abr);  
129 - tunnelingMenuItem = menu.findItem(R.id.tunneling);  
130 - if (Util.SDK_INT < 21) {  
131 - tunnelingMenuItem.setEnabled(false);  
132 - }  
133 - return true;  
134 - }  
135 -  
136 - @Override  
137 - public boolean onOptionsItemSelected(MenuItem item) {  
138 - item.setChecked(!item.isChecked());  
139 - return true;  
140 - }  
141 -  
142 - @Override  
143 - public void onStart() {  
144 - super.onStart();  
145 - downloadTracker.addListener(this);  
146 - sampleAdapter.notifyDataSetChanged();  
147 - }  
148 -  
149 - @Override  
150 - public void onStop() {  
151 - downloadTracker.removeListener(this);  
152 - super.onStop();  
153 - }  
154 -  
155 - @Override  
156 - public void onDownloadsChanged() {  
157 - sampleAdapter.notifyDataSetChanged();  
158 - }  
159 -  
160 - private void onSampleGroups(final List<SampleGroup> groups, boolean sawError) {  
161 - if (sawError) {  
162 - Toast.makeText(getApplicationContext(), R.string.sample_list_load_error, Toast.LENGTH_LONG)  
163 - .show();  
164 - }  
165 - sampleAdapter.setSampleGroups(groups);  
166 - }  
167 -  
168 - @Override  
169 - public boolean onChildClick(  
170 - ExpandableListView parent, View view, int groupPosition, int childPosition, long id) {  
171 - Sample sample = (Sample) view.getTag();  
172 - Intent intent = new Intent(this, PlayerActivity.class);  
173 - intent.putExtra(  
174 - PlayerActivity.PREFER_EXTENSION_DECODERS_EXTRA,  
175 - isNonNullAndChecked(preferExtensionDecodersMenuItem));  
176 - String abrAlgorithm =  
177 - isNonNullAndChecked(randomAbrMenuItem)  
178 - ? PlayerActivity.ABR_ALGORITHM_RANDOM  
179 - : PlayerActivity.ABR_ALGORITHM_DEFAULT;  
180 - intent.putExtra(PlayerActivity.ABR_ALGORITHM_EXTRA, abrAlgorithm);  
181 - intent.putExtra(PlayerActivity.TUNNELING_EXTRA, isNonNullAndChecked(tunnelingMenuItem));  
182 - sample.addToIntent(intent);  
183 - startActivity(intent);  
184 - return true;  
185 - }  
186 -  
187 - private void onSampleDownloadButtonClicked(Sample sample) {  
188 - int downloadUnsupportedStringId = getDownloadUnsupportedStringId(sample);  
189 - if (downloadUnsupportedStringId != 0) {  
190 - Toast.makeText(getApplicationContext(), downloadUnsupportedStringId, Toast.LENGTH_LONG)  
191 - .show();  
192 - } else {  
193 - Sample.UriSample UriSample = (Sample.UriSample) sample;  
194 - RenderersFactory renderersFactory =  
195 - ((DemoApplication) getApplication())  
196 - .buildRenderersFactory(isNonNullAndChecked(preferExtensionDecodersMenuItem));  
197 - downloadTracker.toggleDownload(  
198 - getSupportFragmentManager(),  
199 - sample.name,  
200 - UriSample.uri,  
201 - UriSample.extension,  
202 - renderersFactory);  
203 - }  
204 - }  
205 -  
206 - private int getDownloadUnsupportedStringId(Sample sample) {  
207 - if (sample instanceof Sample.PlaylistSample) {  
208 - return R.string.download_playlist_unsupported;  
209 - }  
210 - Sample.UriSample UriSample = (Sample.UriSample) sample;  
211 - if (UriSample.drmInfo != null) {  
212 - return R.string.download_drm_unsupported;  
213 - }  
214 - if (UriSample.isLive) {  
215 - return R.string.download_live_unsupported;  
216 - }  
217 - if (UriSample.adTagUri != null) {  
218 - return R.string.download_ads_unsupported;  
219 - }  
220 - String scheme = UriSample.uri.getScheme();  
221 - if (!("http".equals(scheme) || "https".equals(scheme))) {  
222 - return R.string.download_scheme_unsupported;  
223 - }  
224 - return 0;  
225 - }  
226 -  
227 - private static boolean isNonNullAndChecked(@Nullable MenuItem menuItem) {  
228 - // Temporary workaround for layouts that do not inflate the options menu.  
229 - return menuItem != null && menuItem.isChecked();  
230 - }  
231 -  
232 - private final class SampleListLoader extends AsyncTask<String, Void, List<SampleGroup>> {  
233 -  
234 - private boolean sawError;  
235 -  
236 - @Override  
237 - protected List<SampleGroup> doInBackground(String... uris) {  
238 - List<SampleGroup> result = new ArrayList<>();  
239 - Context context = getApplicationContext();  
240 - String userAgent = Util.getUserAgent(context, "ExoPlayerDemo");  
241 - DataSource dataSource =  
242 - new DefaultDataSource(context, userAgent, /* allowCrossProtocolRedirects= */ false);  
243 - for (String uri : uris) {  
244 - DataSpec dataSpec = new DataSpec(Uri.parse(uri));  
245 - InputStream inputStream = new DataSourceInputStream(dataSource, dataSpec);  
246 - try {  
247 - readSampleGroups(new JsonReader(new InputStreamReader(inputStream, "UTF-8")), result);  
248 - } catch (Exception e) {  
249 - Log.e(TAG, "Error loading sample list: " + uri, e);  
250 - sawError = true;  
251 - } finally {  
252 - Util.closeQuietly(dataSource);  
253 - }  
254 - }  
255 - return result;  
256 - }  
257 -  
258 - @Override  
259 - protected void onPostExecute(List<SampleGroup> result) {  
260 - onSampleGroups(result, sawError);  
261 - }  
262 -  
263 - private void readSampleGroups(JsonReader reader, List<SampleGroup> groups) throws IOException {  
264 - reader.beginArray();  
265 - while (reader.hasNext()) {  
266 - readSampleGroup(reader, groups);  
267 - }  
268 - reader.endArray();  
269 - }  
270 -  
271 - private void readSampleGroup(JsonReader reader, List<SampleGroup> groups) throws IOException {  
272 - String groupName = "";  
273 - ArrayList<Sample> samples = new ArrayList<>();  
274 -  
275 - reader.beginObject();  
276 - while (reader.hasNext()) {  
277 - String name = reader.nextName();  
278 - switch (name) {  
279 - case "name":  
280 - groupName = reader.nextString();  
281 - break;  
282 - case "samples":  
283 - reader.beginArray();  
284 - while (reader.hasNext()) {  
285 - samples.add(readEntry(reader, false));  
286 - }  
287 - reader.endArray();  
288 - break;  
289 - case "_comment":  
290 - reader.nextString(); // Ignore.  
291 - break;  
292 - default:  
293 - throw new ParserException("Unsupported name: " + name);  
294 - }  
295 - }  
296 - reader.endObject();  
297 -  
298 - SampleGroup group = getGroup(groupName, groups);  
299 - group.samples.addAll(samples);  
300 - }  
301 -  
302 - private Sample readEntry(JsonReader reader, boolean insidePlaylist) throws IOException {  
303 - String sampleName = null;  
304 - Uri uri = null;  
305 - String extension = null;  
306 - boolean isLive = false;  
307 - String drmScheme = null;  
308 - String drmLicenseUrl = null;  
309 - String[] drmKeyRequestProperties = null;  
310 - boolean drmMultiSession = false;  
311 - ArrayList<Sample.UriSample> playlistSamples = null;  
312 - String adTagUri = null;  
313 - String sphericalStereoMode = null;  
314 - List<Sample.SubtitleInfo> subtitleInfos = new ArrayList<>();  
315 - Uri subtitleUri = null;  
316 - String subtitleMimeType = null;  
317 - String subtitleLanguage = null;  
318 -  
319 - reader.beginObject();  
320 - while (reader.hasNext()) {  
321 - String name = reader.nextName();  
322 - switch (name) {  
323 - case "name":  
324 - sampleName = reader.nextString();  
325 - break;  
326 - case "uri":  
327 - uri = Uri.parse(reader.nextString());  
328 - break;  
329 - case "extension":  
330 - extension = reader.nextString();  
331 - break;  
332 - case "drm_scheme":  
333 - drmScheme = reader.nextString();  
334 - break;  
335 - case "is_live":  
336 - isLive = reader.nextBoolean();  
337 - break;  
338 - case "drm_license_url":  
339 - drmLicenseUrl = reader.nextString();  
340 - break;  
341 - case "drm_key_request_properties":  
342 - ArrayList<String> drmKeyRequestPropertiesList = new ArrayList<>();  
343 - reader.beginObject();  
344 - while (reader.hasNext()) {  
345 - drmKeyRequestPropertiesList.add(reader.nextName());  
346 - drmKeyRequestPropertiesList.add(reader.nextString());  
347 - }  
348 - reader.endObject();  
349 - drmKeyRequestProperties = drmKeyRequestPropertiesList.toArray(new String[0]);  
350 - break;  
351 - case "drm_multi_session":  
352 - drmMultiSession = reader.nextBoolean();  
353 - break;  
354 - case "playlist":  
355 - Assertions.checkState(!insidePlaylist, "Invalid nesting of playlists");  
356 - playlistSamples = new ArrayList<Sample.UriSample>();  
357 - reader.beginArray();  
358 - while (reader.hasNext()) {  
359 - playlistSamples.add((Sample.UriSample) readEntry(reader, /* insidePlaylist= */ true));  
360 - }  
361 - reader.endArray();  
362 - break;  
363 - case "ad_tag_uri":  
364 - adTagUri = reader.nextString();  
365 - break;  
366 - case "spherical_stereo_mode":  
367 - Assertions.checkState(  
368 - !insidePlaylist, "Invalid attribute on nested item: spherical_stereo_mode");  
369 - sphericalStereoMode = reader.nextString();  
370 - break;  
371 - case "subtitle_uri":  
372 - subtitleUri = Uri.parse(reader.nextString());  
373 - break;  
374 - case "subtitle_mime_type":  
375 - subtitleMimeType = reader.nextString();  
376 - break;  
377 - case "subtitle_language":  
378 - subtitleLanguage = reader.nextString();  
379 - break;  
380 - default:  
381 - throw new ParserException("Unsupported attribute name: " + name);  
382 - }  
383 - }  
384 - reader.endObject();  
385 - Sample.DrmInfo drmInfo =  
386 - drmScheme == null  
387 - ? null  
388 - : new Sample.DrmInfo(  
389 - Util.getDrmUuid(drmScheme),  
390 - drmLicenseUrl,  
391 - drmKeyRequestProperties,  
392 - drmMultiSession);  
393 - Sample.SubtitleInfo subtitleInfo =  
394 - subtitleUri == null  
395 - ? null  
396 - : new Sample.SubtitleInfo(  
397 - subtitleUri,  
398 - Assertions.checkNotNull(  
399 - subtitleMimeType, "subtitle_mime_type is required if subtitle_uri is set."),  
400 - subtitleLanguage);  
401 - if (playlistSamples != null) {  
402 - Sample.UriSample[] playlistSamplesArray = playlistSamples.toArray(new Sample.UriSample[0]);  
403 - return new Sample.PlaylistSample(sampleName, playlistSamplesArray);  
404 - } else {  
405 - return new Sample.UriSample(  
406 - sampleName,  
407 - uri,  
408 - extension,  
409 - isLive,  
410 - drmInfo,  
411 - adTagUri != null ? Uri.parse(adTagUri) : null,  
412 - sphericalStereoMode,  
413 - subtitleInfo);  
414 - }  
415 - }  
416 -  
417 - private SampleGroup getGroup(String groupName, List<SampleGroup> groups) {  
418 - for (int i = 0; i < groups.size(); i++) {  
419 - if (Util.areEqual(groupName, groups.get(i).title)) {  
420 - return groups.get(i);  
421 - }  
422 - }  
423 - SampleGroup group = new SampleGroup(groupName);  
424 - groups.add(group);  
425 - return group;  
426 - }  
427 -  
428 - }  
429 -  
430 - private final class SampleAdapter extends BaseExpandableListAdapter implements OnClickListener {  
431 -  
432 - private List<SampleGroup> sampleGroups;  
433 -  
434 - public SampleAdapter() {  
435 - sampleGroups = Collections.emptyList();  
436 - }  
437 -  
438 - public void setSampleGroups(List<SampleGroup> sampleGroups) {  
439 - this.sampleGroups = sampleGroups;  
440 - notifyDataSetChanged();  
441 - }  
442 -  
443 - @Override  
444 - public Sample getChild(int groupPosition, int childPosition) {  
445 - return getGroup(groupPosition).samples.get(childPosition);  
446 - }  
447 -  
448 - @Override  
449 - public long getChildId(int groupPosition, int childPosition) {  
450 - return childPosition;  
451 - }  
452 -  
453 - @Override  
454 - public View getChildView(int groupPosition, int childPosition, boolean isLastChild,  
455 - View convertView, ViewGroup parent) {  
456 - View view = convertView;  
457 - if (view == null) {  
458 - view = getLayoutInflater().inflate(R.layout.sample_list_item, parent, false);  
459 - View downloadButton = view.findViewById(R.id.download_button);  
460 - downloadButton.setOnClickListener(this);  
461 - downloadButton.setFocusable(false);  
462 - }  
463 - initializeChildView(view, getChild(groupPosition, childPosition));  
464 - return view;  
465 - }  
466 -  
467 - @Override  
468 - public int getChildrenCount(int groupPosition) {  
469 - return getGroup(groupPosition).samples.size();  
470 - }  
471 -  
472 - @Override  
473 - public SampleGroup getGroup(int groupPosition) {  
474 - return sampleGroups.get(groupPosition);  
475 - }  
476 -  
477 - @Override  
478 - public long getGroupId(int groupPosition) {  
479 - return groupPosition;  
480 - }  
481 -  
482 - @Override  
483 - public View getGroupView(int groupPosition, boolean isExpanded, View convertView,  
484 - ViewGroup parent) {  
485 - View view = convertView;  
486 - if (view == null) {  
487 - view =  
488 - getLayoutInflater()  
489 - .inflate(android.R.layout.simple_expandable_list_item_1, parent, false);  
490 - }  
491 - ((TextView) view).setText(getGroup(groupPosition).title);  
492 - return view;  
493 - }  
494 -  
495 - @Override  
496 - public int getGroupCount() {  
497 - return sampleGroups.size();  
498 - }  
499 -  
500 - @Override  
501 - public boolean hasStableIds() {  
502 - return false;  
503 - }  
504 -  
505 - @Override  
506 - public boolean isChildSelectable(int groupPosition, int childPosition) {  
507 - return true;  
508 - }  
509 -  
510 - @Override  
511 - public void onClick(View view) {  
512 - onSampleDownloadButtonClicked((Sample) view.getTag());  
513 - }  
514 -  
515 - private void initializeChildView(View view, Sample sample) {  
516 - view.setTag(sample);  
517 - TextView sampleTitle = view.findViewById(R.id.sample_title);  
518 - sampleTitle.setText(sample.name);  
519 -  
520 - boolean canDownload = getDownloadUnsupportedStringId(sample) == 0;  
521 - boolean isDownloaded = canDownload && downloadTracker.isDownloaded(((Sample.UriSample) sample).uri);  
522 - ImageButton downloadButton = view.findViewById(R.id.download_button);  
523 - downloadButton.setTag(sample);  
524 - downloadButton.setColorFilter(  
525 - canDownload ? (isDownloaded ? 0xFF42A5F5 : 0xFFBDBDBD) : 0xFF666666);  
526 - downloadButton.setImageResource(  
527 - isDownloaded ? R.drawable.ic_download_done : R.drawable.ic_download);  
528 - }  
529 - }  
530 -  
531 - private static final class SampleGroup {  
532 -  
533 - public final String title;  
534 - public final List<Sample> samples;  
535 -  
536 - public SampleGroup(String title) {  
537 - this.title = title;  
538 - this.samples = new ArrayList<>();  
539 - }  
540 -  
541 - }  
542 -}  
app/strike/src/main/java/com/cnlive/strike/demo/exoplayer/demo/TrackSelectionDialog.java deleted 100644 → 0
1 -/*  
2 - * Copyright (C) 2019 The Android Open Source Project  
3 - *  
4 - * Licensed under the Apache License, Version 2.0 (the "License");  
5 - * you may not use this file except in compliance with the License.  
6 - * You may obtain a copy of the License at  
7 - *  
8 - * http://www.apache.org/licenses/LICENSE-2.0  
9 - *  
10 - * Unless required by applicable law or agreed to in writing, software  
11 - * distributed under the License is distributed on an "AS IS" BASIS,  
12 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  
13 - * See the License for the specific language governing permissions and  
14 - * limitations under the License.  
15 - */  
16 -package com.cnlive.strike.demo.exoplayer.demo;  
17 -  
18 -import android.app.Dialog;  
19 -import android.content.DialogInterface;  
20 -import android.content.res.Resources;  
21 -import android.os.Bundle;  
22 -import android.util.SparseArray;  
23 -import android.view.LayoutInflater;  
24 -import android.view.View;  
25 -import android.view.ViewGroup;  
26 -import android.widget.Button;  
27 -import androidx.annotation.Nullable;  
28 -import androidx.appcompat.app.AppCompatDialog;  
29 -import androidx.fragment.app.DialogFragment;  
30 -import androidx.fragment.app.Fragment;  
31 -import androidx.fragment.app.FragmentManager;  
32 -import androidx.fragment.app.FragmentPagerAdapter;  
33 -import androidx.viewpager.widget.ViewPager;  
34 -  
35 -import com.cnlive.cloud.R;  
36 -import com.google.android.exoplayer2.C;  
37 -import com.google.android.exoplayer2.source.TrackGroupArray;  
38 -import com.google.android.exoplayer2.trackselection.DefaultTrackSelector;  
39 -import com.google.android.exoplayer2.trackselection.DefaultTrackSelector.SelectionOverride;  
40 -import com.google.android.exoplayer2.trackselection.MappingTrackSelector.MappedTrackInfo;  
41 -import com.google.android.exoplayer2.ui.TrackSelectionView;  
42 -import com.google.android.exoplayer2.util.Assertions;  
43 -import com.google.android.material.tabs.TabLayout;  
44 -import java.util.ArrayList;  
45 -import java.util.Collections;  
46 -import java.util.List;  
47 -  
48 -/** Dialog to select tracks. */  
49 -public final class TrackSelectionDialog extends DialogFragment {  
50 -  
51 - private final SparseArray<TrackSelectionViewFragment> tabFragments;  
52 - private final ArrayList<Integer> tabTrackTypes;  
53 -  
54 - private int titleId;  
55 - private DialogInterface.OnClickListener onClickListener;  
56 - private DialogInterface.OnDismissListener onDismissListener;  
57 -  
58 - /**  
59 - * Returns whether a track selection dialog will have content to display if initialized with the  
60 - * specified {@link DefaultTrackSelector} in its current state.  
61 - */  
62 - public static boolean willHaveContent(DefaultTrackSelector trackSelector) {  
63 - MappedTrackInfo mappedTrackInfo = trackSelector.getCurrentMappedTrackInfo();  
64 - return mappedTrackInfo != null && willHaveContent(mappedTrackInfo);  
65 - }  
66 -  
67 - /**  
68 - * Returns whether a track selection dialog will have content to display if initialized with the  
69 - * specified {@link MappedTrackInfo}.  
70 - */  
71 - public static boolean willHaveContent(MappedTrackInfo mappedTrackInfo) {  
72 - for (int i = 0; i < mappedTrackInfo.getRendererCount(); i++) {  
73 - if (showTabForRenderer(mappedTrackInfo, i)) {  
74 - return true;  
75 - }  
76 - }  
77 - return false;  
78 - }  
79 -  
80 - /**  
81 - * Creates a dialog for a given {@link DefaultTrackSelector}, whose parameters will be  
82 - * automatically updated when tracks are selected.  
83 - *  
84 - * @param trackSelector The {@link DefaultTrackSelector}.  
85 - * @param onDismissListener A {@link DialogInterface.OnDismissListener} to call when the dialog is  
86 - * dismissed.  
87 - */  
88 - public static TrackSelectionDialog createForTrackSelector(  
89 - DefaultTrackSelector trackSelector, DialogInterface.OnDismissListener onDismissListener) {  
90 - MappedTrackInfo mappedTrackInfo =  
91 - Assertions.checkNotNull(trackSelector.getCurrentMappedTrackInfo());  
92 - TrackSelectionDialog trackSelectionDialog = new TrackSelectionDialog();  
93 - DefaultTrackSelector.Parameters parameters = trackSelector.getParameters();  
94 - trackSelectionDialog.init(  
95 - /* titleId= */ R.string.track_selection_title,  
96 - mappedTrackInfo,  
97 - /* initialParameters = */ parameters,  
98 - /* allowAdaptiveSelections =*/ true,  
99 - /* allowMultipleOverrides= */ false,  
100 - /* onClickListener= */ (dialog, which) -> {  
101 - DefaultTrackSelector.ParametersBuilder builder = parameters.buildUpon();  
102 - for (int i = 0; i < mappedTrackInfo.getRendererCount(); i++) {  
103 - builder  
104 - .clearSelectionOverrides(/* rendererIndex= */ i)  
105 - .setRendererDisabled(  
106 - /* rendererIndex= */ i,  
107 - trackSelectionDialog.getIsDisabled(/* rendererIndex= */ i));  
108 - List<SelectionOverride> overrides =  
109 - trackSelectionDialog.getOverrides(/* rendererIndex= */ i);  
110 - if (!overrides.isEmpty()) {  
111 - builder.setSelectionOverride(  
112 - /* rendererIndex= */ i,  
113 - mappedTrackInfo.getTrackGroups(/* rendererIndex= */ i),  
114 - overrides.get(0));  
115 - }  
116 - }  
117 - trackSelector.setParameters(builder);  
118 - },  
119 - onDismissListener);  
120 - return trackSelectionDialog;  
121 - }  
122 -  
123 - /**  
124 - * Creates a dialog for given {@link MappedTrackInfo} and {@link DefaultTrackSelector.Parameters}.  
125 - *  
126 - * @param titleId The resource id of the dialog title.  
127 - * @param mappedTrackInfo The {@link MappedTrackInfo} to display.  
128 - * @param initialParameters The {@link DefaultTrackSelector.Parameters} describing the initial  
129 - * track selection.  
130 - * @param allowAdaptiveSelections Whether adaptive selections (consisting of more than one track)  
131 - * can be made.  
132 - * @param allowMultipleOverrides Whether tracks from multiple track groups can be selected.  
133 - * @param onClickListener {@link DialogInterface.OnClickListener} called when tracks are selected.  
134 - * @param onDismissListener {@link DialogInterface.OnDismissListener} called when the dialog is  
135 - * dismissed.  
136 - */  
137 - public static TrackSelectionDialog createForMappedTrackInfoAndParameters(  
138 - int titleId,  
139 - MappedTrackInfo mappedTrackInfo,  
140 - DefaultTrackSelector.Parameters initialParameters,  
141 - boolean allowAdaptiveSelections,  
142 - boolean allowMultipleOverrides,  
143 - DialogInterface.OnClickListener onClickListener,  
144 - DialogInterface.OnDismissListener onDismissListener) {  
145 - TrackSelectionDialog trackSelectionDialog = new TrackSelectionDialog();  
146 - trackSelectionDialog.init(  
147 - titleId,  
148 - mappedTrackInfo,  
149 - initialParameters,  
150 - allowAdaptiveSelections,  
151 - allowMultipleOverrides,  
152 - onClickListener,  
153 - onDismissListener);  
154 - return trackSelectionDialog;  
155 - }  
156 -  
157 - public TrackSelectionDialog() {  
158 - tabFragments = new SparseArray<>();  
159 - tabTrackTypes = new ArrayList<>();  
160 - // Retain instance across activity re-creation to prevent losing access to init data.  
161 - setRetainInstance(true);  
162 - }  
163 -  
164 - private void init(  
165 - int titleId,  
166 - MappedTrackInfo mappedTrackInfo,  
167 - DefaultTrackSelector.Parameters initialParameters,  
168 - boolean allowAdaptiveSelections,  
169 - boolean allowMultipleOverrides,  
170 - DialogInterface.OnClickListener onClickListener,  
171 - DialogInterface.OnDismissListener onDismissListener) {  
172 - this.titleId = titleId;  
173 - this.onClickListener = onClickListener;  
174 - this.onDismissListener = onDismissListener;  
175 - for (int i = 0; i < mappedTrackInfo.getRendererCount(); i++) {  
176 - if (showTabForRenderer(mappedTrackInfo, i)) {  
177 - int trackType = mappedTrackInfo.getRendererType(/* rendererIndex= */ i);  
178 - TrackGroupArray trackGroupArray = mappedTrackInfo.getTrackGroups(i);  
179 - TrackSelectionViewFragment tabFragment = new TrackSelectionViewFragment();  
180 - tabFragment.init(  
181 - mappedTrackInfo,  
182 - /* rendererIndex= */ i,  
183 - initialParameters.getRendererDisabled(/* rendererIndex= */ i),  
184 - initialParameters.getSelectionOverride(/* rendererIndex= */ i, trackGroupArray),  
185 - allowAdaptiveSelections,  
186 - allowMultipleOverrides);  
187 - tabFragments.put(i, tabFragment);  
188 - tabTrackTypes.add(trackType);  
189 - }  
190 - }  
191 - }  
192 -  
193 - /**  
194 - * Returns whether a renderer is disabled.  
195 - *  
196 - * @param rendererIndex Renderer index.  
197 - * @return Whether the renderer is disabled.  
198 - */  
199 - public boolean getIsDisabled(int rendererIndex) {  
200 - TrackSelectionViewFragment rendererView = tabFragments.get(rendererIndex);  
201 - return rendererView != null && rendererView.isDisabled;  
202 - }  
203 -  
204 - /**  
205 - * Returns the list of selected track selection overrides for the specified renderer. There will  
206 - * be at most one override for each track group.  
207 - *  
208 - * @param rendererIndex Renderer index.  
209 - * @return The list of track selection overrides for this renderer.  
210 - */  
211 - public List<SelectionOverride> getOverrides(int rendererIndex) {  
212 - TrackSelectionViewFragment rendererView = tabFragments.get(rendererIndex);  
213 - return rendererView == null ? Collections.emptyList() : rendererView.overrides;  
214 - }  
215 -  
216 - @Override  
217 - public Dialog onCreateDialog(Bundle savedInstanceState) {  
218 - // We need to own the view to let tab layout work correctly on all API levels. We can't use  
219 - // AlertDialog because it owns the view itself, so we use AppCompatDialog instead, themed using  
220 - // the AlertDialog theme overlay with force-enabled title.  
221 - AppCompatDialog dialog =  
222 - new AppCompatDialog(getActivity(), R.style.TrackSelectionDialogThemeOverlay);  
223 - dialog.setTitle(titleId);  
224 - return dialog;  
225 - }  
226 -  
227 - @Override  
228 - public void onDismiss(DialogInterface dialog) {  
229 - super.onDismiss(dialog);  
230 - onDismissListener.onDismiss(dialog);  
231 - }  
232 -  
233 - @Nullable  
234 - @Override  
235 - public View onCreateView(  
236 - LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {  
237 -  
238 - View dialogView = inflater.inflate(R.layout.track_selection_dialog, container, false);  
239 - TabLayout tabLayout = dialogView.findViewById(R.id.track_selection_dialog_tab_layout);  
240 - ViewPager viewPager = dialogView.findViewById(R.id.track_selection_dialog_view_pager);  
241 - Button cancelButton = dialogView.findViewById(R.id.track_selection_dialog_cancel_button);  
242 - Button okButton = dialogView.findViewById(R.id.track_selection_dialog_ok_button);  
243 - viewPager.setAdapter(new FragmentAdapter(getChildFragmentManager()));  
244 - tabLayout.setupWithViewPager(viewPager);  
245 - tabLayout.setVisibility(tabFragments.size() > 1 ? View.VISIBLE : View.GONE);  
246 - cancelButton.setOnClickListener(view -> dismiss());  
247 - okButton.setOnClickListener(  
248 - view -> {  
249 - onClickListener.onClick(getDialog(), DialogInterface.BUTTON_POSITIVE);  
250 - dismiss();  
251 - });  
252 - return dialogView;  
253 - }  
254 -  
255 - private static boolean showTabForRenderer(MappedTrackInfo mappedTrackInfo, int rendererIndex) {  
256 - TrackGroupArray trackGroupArray = mappedTrackInfo.getTrackGroups(rendererIndex);  
257 - if (trackGroupArray.length == 0) {  
258 - return false;  
259 - }  
260 - int trackType = mappedTrackInfo.getRendererType(rendererIndex);  
261 - return isSupportedTrackType(trackType);  
262 - }  
263 -  
264 - private static boolean isSupportedTrackType(int trackType) {  
265 - switch (trackType) {  
266 - case C.TRACK_TYPE_VIDEO:  
267 - case C.TRACK_TYPE_AUDIO:  
268 - case C.TRACK_TYPE_TEXT:  
269 - return true;  
270 - default:  
271 - return false;  
272 - }  
273 - }  
274 -  
275 - private static String getTrackTypeString(Resources resources, int trackType) {  
276 - switch (trackType) {  
277 - case C.TRACK_TYPE_VIDEO:  
278 - return resources.getString(R.string.exo_track_selection_title_video);  
279 - case C.TRACK_TYPE_AUDIO:  
280 - return resources.getString(R.string.exo_track_selection_title_audio);  
281 - case C.TRACK_TYPE_TEXT:  
282 - return resources.getString(R.string.exo_track_selection_title_text);  
283 - default:  
284 - throw new IllegalArgumentException();  
285 - }  
286 - }  
287 -  
288 - private final class FragmentAdapter extends FragmentPagerAdapter {  
289 -  
290 - public FragmentAdapter(FragmentManager fragmentManager) {  
291 - super(fragmentManager);  
292 - }  
293 -  
294 - @Override  
295 - public Fragment getItem(int position) {  
296 - return tabFragments.valueAt(position);  
297 - }  
298 -  
299 - @Override  
300 - public int getCount() {  
301 - return tabFragments.size();  
302 - }  
303 -  
304 - @Nullable  
305 - @Override  
306 - public CharSequence getPageTitle(int position) {  
307 - return getTrackTypeString(getResources(), tabTrackTypes.get(position));  
308 - }  
309 - }  
310 -  
311 - /** Fragment to show a track selection in tab of the track selection dialog. */  
312 - public static final class TrackSelectionViewFragment extends Fragment  
313 - implements TrackSelectionView.TrackSelectionListener {  
314 -  
315 - private MappedTrackInfo mappedTrackInfo;  
316 - private int rendererIndex;  
317 - private boolean allowAdaptiveSelections;  
318 - private boolean allowMultipleOverrides;  
319 -  
320 - /* package */ boolean isDisabled;  
321 - /* package */ List<SelectionOverride> overrides;  
322 -  
323 - public TrackSelectionViewFragment() {  
324 - // Retain instance across activity re-creation to prevent losing access to init data.  
325 - setRetainInstance(true);  
326 - }  
327 -  
328 - public void init(  
329 - MappedTrackInfo mappedTrackInfo,  
330 - int rendererIndex,  
331 - boolean initialIsDisabled,  
332 - @Nullable SelectionOverride initialOverride,  
333 - boolean allowAdaptiveSelections,  
334 - boolean allowMultipleOverrides) {  
335 - this.mappedTrackInfo = mappedTrackInfo;  
336 - this.rendererIndex = rendererIndex;  
337 - this.isDisabled = initialIsDisabled;  
338 - this.overrides =  
339 - initialOverride == null  
340 - ? Collections.emptyList()  
341 - : Collections.singletonList(initialOverride);  
342 - this.allowAdaptiveSelections = allowAdaptiveSelections;  
343 - this.allowMultipleOverrides = allowMultipleOverrides;  
344 - }  
345 -  
346 - @Nullable  
347 - @Override  
348 - public View onCreateView(  
349 - LayoutInflater inflater,  
350 - @Nullable ViewGroup container,  
351 - @Nullable Bundle savedInstanceState) {  
352 - View rootView =  
353 - inflater.inflate(  
354 - R.layout.exo_track_selection_dialog, container, /* attachToRoot= */ false);  
355 - TrackSelectionView trackSelectionView = rootView.findViewById(R.id.exo_track_selection_view);  
356 - trackSelectionView.setShowDisableOption(true);  
357 - trackSelectionView.setAllowMultipleOverrides(allowMultipleOverrides);  
358 - trackSelectionView.setAllowAdaptiveSelections(allowAdaptiveSelections);  
359 - trackSelectionView.init(  
360 - mappedTrackInfo, rendererIndex, isDisabled, overrides, /* listener= */ this);  
361 - return rootView;  
362 - }  
363 -  
364 - @Override  
365 - public void onTrackSelectionChanged(boolean isDisabled, List<SelectionOverride> overrides) {  
366 - this.isDisabled = isDisabled;  
367 - this.overrides = overrides;  
368 - }  
369 - }  
370 -}  
cloud/video/src/main/java/com/libs/video/video/exoplayer/component/DefaultErrorView.java
1 package com.libs.video.video.exoplayer.component; 1 package com.libs.video.video.exoplayer.component;
2 2
3 import android.content.Context; 3 import android.content.Context;
  4 +import android.content.res.Configuration;
4 import android.util.AttributeSet; 5 import android.util.AttributeSet;
5 import android.util.Log; 6 import android.util.Log;
6 import android.view.LayoutInflater; 7 import android.view.LayoutInflater;
@@ -17,6 +18,7 @@ import com.cnlive.core.libs.base.util.NetworkUtil; @@ -17,6 +18,7 @@ import com.cnlive.core.libs.base.util.NetworkUtil;
17 import com.libs.video.video.exoplayer.PlayErrorException; 18 import com.libs.video.video.exoplayer.PlayErrorException;
18 import com.libs.video.video.exoplayer.controller.ControlWrapper; 19 import com.libs.video.video.exoplayer.controller.ControlWrapper;
19 import com.libs.video.video.exoplayer.controller.IControlComponent; 20 import com.libs.video.video.exoplayer.controller.IControlComponent;
  21 +import com.libs.video.video.exoplayer.controller.OrientationHelper;
20 import com.libs.video.video.exoplayer.play.AbstractPlayer; 22 import com.libs.video.video.exoplayer.play.AbstractPlayer;
21 import com.libs.video.video.exoplayer.play.CNVideoView; 23 import com.libs.video.video.exoplayer.play.CNVideoView;
22 24
@@ -140,5 +142,17 @@ public class DefaultErrorView extends LinearLayout implements IControlComponent @@ -140,5 +142,17 @@ public class DefaultErrorView extends LinearLayout implements IControlComponent
140 } 142 }
141 } 143 }
142 144
143 - 145 + /**
  146 + * @param newConfig
  147 + */
  148 + @Override
  149 + protected void onConfigurationChanged(Configuration newConfig) {
  150 + super.onConfigurationChanged(newConfig);
  151 + //新状态为横屏
  152 + if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
  153 + Log.e(TAG, "onConfigurationChanged: 横屏" );
  154 + }else {
  155 + Log.e(TAG, "onConfigurationChanged: 竖屏" );
  156 + }
  157 + }
144 } 158 }
cloud/video/src/main/java/com/libs/video/video/exoplayer/component/DefaultYoukuErrorView.java 0 → 100644
  1 +package com.libs.video.video.exoplayer.component;
  2 +
  3 +import android.content.Context;
  4 +import android.content.res.Configuration;
  5 +import android.util.AttributeSet;
  6 +import android.util.Log;
  7 +import android.view.LayoutInflater;
  8 +import android.view.MotionEvent;
  9 +import android.view.View;
  10 +import android.view.ViewConfiguration;
  11 +import android.view.animation.Animation;
  12 +import android.widget.Button;
  13 +import android.widget.LinearLayout;
  14 +import android.widget.TextView;
  15 +
  16 +import com.cnlive.cloud.video.R;
  17 +import com.libs.video.video.exoplayer.PlayErrorException;
  18 +import com.libs.video.video.exoplayer.controller.ControlWrapper;
  19 +import com.libs.video.video.exoplayer.controller.IControlComponent;
  20 +import com.libs.video.video.exoplayer.play.CNVideoView;
  21 +
  22 +import androidx.annotation.NonNull;
  23 +import androidx.annotation.Nullable;
  24 +
  25 +/**
  26 + * 播放出错提示界面
  27 + */
  28 +public class DefaultYoukuErrorView extends LinearLayout implements IControlComponent {
  29 +
  30 + private float mDownX;
  31 + private float mDownY;
  32 + private Button btnRetry;
  33 + private TextView tvMessage;
  34 + private ControlWrapper mControlWrapper;//公共控制接口
  35 + private String TAG = this.getClass().getName();
  36 +
  37 + public DefaultYoukuErrorView(Context context) {
  38 + this(context, null);
  39 + }
  40 +
  41 + public DefaultYoukuErrorView(Context context, @Nullable AttributeSet attrs) {
  42 + super(context, attrs);
  43 + }
  44 +
  45 + public DefaultYoukuErrorView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
  46 + super(context, attrs, defStyleAttr);
  47 + }
  48 +
  49 + {
  50 + setVisibility(GONE);
  51 + LayoutInflater.from(getContext()).inflate(R.layout.cnvideo_layout_error_view, this, true);
  52 + btnRetry = findViewById(R.id.btn_retry);
  53 + tvMessage=findViewById(R.id.tv_message);
  54 + btnRetry.setOnClickListener(new OnClickListener() {
  55 + @Override
  56 + public void onClick(View v) {
  57 + setVisibility(GONE);
  58 + mControlWrapper.replay(false);
  59 + }
  60 + });
  61 + setClickable(true);
  62 + }
  63 +
  64 + @Override
  65 + public void attach(@NonNull ControlWrapper controlWrapper) {
  66 + mControlWrapper = controlWrapper;
  67 + }
  68 +
  69 + @Override
  70 + public View getView() {
  71 + return this;
  72 + }
  73 +
  74 +
  75 + @Override
  76 + public void onPlayStateChanged(int playState) {
  77 + if (playState == CNVideoView.STATE_ERROR) {
  78 + //将view的z轴改变,置于父view的最上方。这个方法会将view从父view中移除,再添加到父view中。
  79 + bringToFront();
  80 + setVisibility(VISIBLE);
  81 + } else if (playState == CNVideoView.STATE_IDLE) {
  82 + setVisibility(GONE);
  83 + }
  84 + }
  85 +
  86 +
  87 + @Override
  88 + public boolean dispatchTouchEvent(MotionEvent ev) {
  89 + switch (ev.getAction()) {
  90 + case MotionEvent.ACTION_DOWN:
  91 + mDownX = ev.getX();
  92 + mDownY = ev.getY();
  93 + // True if the child does not want the parent to intercept touch events.
  94 + getParent().requestDisallowInterceptTouchEvent(true);
  95 + break;
  96 + case MotionEvent.ACTION_MOVE:
  97 + float absDeltaX = Math.abs(ev.getX() - mDownX);
  98 + float absDeltaY = Math.abs(ev.getY() - mDownY);
  99 + if (absDeltaX > ViewConfiguration.get(getContext()).getScaledTouchSlop() ||
  100 + absDeltaY > ViewConfiguration.get(getContext()).getScaledTouchSlop()) {
  101 + getParent().requestDisallowInterceptTouchEvent(false);
  102 + }
  103 + case MotionEvent.ACTION_UP:
  104 + break;
  105 + }
  106 + return super.dispatchTouchEvent(ev);
  107 + }
  108 +
  109 + @Override
  110 + public void onVisibilityChanged(boolean isVisible, Animation anim) {
  111 +
  112 + }
  113 +
  114 + @Override
  115 + public void onPlayerStateChanged(int playerState) {
  116 +
  117 + }
  118 +
  119 + @Override
  120 + public void setProgress(int duration, int position) {
  121 +
  122 + }
  123 +
  124 + @Override
  125 + public void onLockStateChanged(boolean isLock) {
  126 +
  127 + }
  128 +
  129 + @Override
  130 + public void onPlayError(PlayErrorException exception) {
  131 + //获取当前类型
  132 + if (null == tvMessage) {
  133 + return;
  134 + }
  135 + switch (exception.getErrorType()) {
  136 + case PlayErrorException.TYPE_NETWORK_ERROR:
  137 + tvMessage.setText(exception.getErrorMsg());
  138 + break;
  139 + }
  140 + }
  141 +
  142 + /**
  143 + * @param newConfig
  144 + */
  145 + @Override
  146 + protected void onConfigurationChanged(Configuration newConfig) {
  147 + super.onConfigurationChanged(newConfig);
  148 + //新状态为横屏
  149 + if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
  150 + Log.e(TAG, "onConfigurationChanged: 横屏" );
  151 + }else {
  152 + Log.e(TAG, "onConfigurationChanged: 竖屏" );
  153 + }
  154 + }
  155 +}
cloud/video/src/main/java/com/libs/video/video/exoplayer/component/DefaultYoukuPrepareView.java 0 → 100644
  1 +package com.libs.video.video.exoplayer.component;
  2 +
  3 +import android.content.Context;
  4 +import android.graphics.drawable.AnimationDrawable;
  5 +import android.util.AttributeSet;
  6 +import android.view.LayoutInflater;
  7 +import android.view.View;
  8 +import android.view.animation.Animation;
  9 +import android.widget.FrameLayout;
  10 +import android.widget.ImageView;
  11 +import android.widget.ProgressBar;
  12 +
  13 +import com.cnlive.cloud.video.R;
  14 +import com.libs.video.video.exoplayer.PlayErrorException;
  15 +import com.libs.video.video.exoplayer.controller.ControlWrapper;
  16 +import com.libs.video.video.exoplayer.controller.IControlComponent;
  17 +import com.libs.video.video.exoplayer.play.CNVideoView;
  18 +import com.libs.video.video.exoplayer.play.VideoViewManager;
  19 +
  20 +import androidx.annotation.NonNull;
  21 +import androidx.annotation.Nullable;
  22 +
  23 +/**
  24 + * 准备播放界面
  25 + */
  26 +public class DefaultYoukuPrepareView extends FrameLayout implements IControlComponent {
  27 +
  28 + private ControlWrapper mControlWrapper;
  29 +
  30 + // private ImageView mStartPlay;
  31 + private FrameLayout mNetWarning;
  32 + private View youkuLoading;
  33 +
  34 + public DefaultYoukuPrepareView(@NonNull Context context) {
  35 + super(context);
  36 + }
  37 +
  38 + public DefaultYoukuPrepareView(@NonNull Context context, @Nullable AttributeSet attrs) {
  39 + super(context, attrs);
  40 + }
  41 +
  42 + public DefaultYoukuPrepareView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
  43 + super(context, attrs, defStyleAttr);
  44 + }
  45 +
  46 + {
  47 + LayoutInflater.from(getContext()).inflate(R.layout.cnvideo_layout_youku_prepare_view, this, true);
  48 +// mStartPlay = findViewById(R.id.start_play);
  49 + youkuLoading= findViewById(R.id.view_youku_loading);
  50 + mNetWarning = findViewById(R.id.net_warning_layout);
  51 + AnimationDrawable animationDrawable = (AnimationDrawable) youkuLoading.getBackground();
  52 + animationDrawable.start();
  53 + findViewById(R.id.status_btn).setOnClickListener(new OnClickListener() {
  54 + @Override
  55 + public void onClick(View v) {
  56 + mNetWarning.setVisibility(GONE);
  57 + VideoViewManager.instance().setPlayOnMobileNetwork(true);
  58 + mControlWrapper.start();
  59 + }
  60 + });
  61 + }
  62 +
  63 + /**
  64 + * 设置点击此界面开始播放
  65 + */
  66 + public void setClickStart() {
  67 + setOnClickListener(new OnClickListener() {
  68 + @Override
  69 + public void onClick(View v) {
  70 + mControlWrapper.start();
  71 + }
  72 + });
  73 + }
  74 +
  75 + @Override
  76 + public void attach(@NonNull ControlWrapper controlWrapper) {
  77 + mControlWrapper = controlWrapper;
  78 + }
  79 +
  80 + @Override
  81 + public View getView() {
  82 + return this;
  83 + }
  84 +
  85 + @Override
  86 + public void onVisibilityChanged(boolean isVisible, Animation anim) {
  87 +
  88 + }
  89 +
  90 + @Override
  91 + public void onPlayStateChanged(int playState) {
  92 + switch (playState) {
  93 + case CNVideoView.STATE_PREPARING:
  94 + bringToFront();
  95 + setVisibility(VISIBLE);
  96 +// mStartPlay.setVisibility(View.GONE);
  97 + mNetWarning.setVisibility(GONE);
  98 + break;
  99 + case CNVideoView.STATE_PLAYING:
  100 + case CNVideoView.STATE_PAUSED:
  101 + case CNVideoView.STATE_ERROR:
  102 + case CNVideoView.STATE_BUFFERING:
  103 + case CNVideoView.STATE_BUFFERED:
  104 + case CNVideoView.STATE_PLAYBACK_COMPLETED:
  105 + setVisibility(GONE);
  106 + break;
  107 + case CNVideoView.STATE_IDLE:
  108 + setVisibility(VISIBLE);
  109 + bringToFront();
  110 + mNetWarning.setVisibility(GONE);
  111 +// mStartPlay.setVisibility(View.VISIBLE);
  112 + break;
  113 + case CNVideoView.STATE_START_ABORT:
  114 + setVisibility(VISIBLE);
  115 + mNetWarning.setVisibility(VISIBLE);
  116 + mNetWarning.bringToFront();
  117 + break;
  118 + }
  119 + }
  120 +
  121 + @Override
  122 + public void onPlayerStateChanged(int playerState) {
  123 +
  124 + }
  125 +
  126 + @Override
  127 + public void setProgress(int duration, int position) {
  128 +
  129 + }
  130 +
  131 + @Override
  132 + public void onLockStateChanged(boolean isLocked) {
  133 +
  134 + }
  135 +
  136 + @Override
  137 + public void onPlayError(PlayErrorException exception) {
  138 +
  139 + }
  140 +}
cloud/video/src/main/java/com/libs/video/video/exoplayer/controller/ControlWrapper.java
@@ -31,10 +31,10 @@ public class ControlWrapper implements MediaPlayerControl, IVideoController { @@ -31,10 +31,10 @@ public class ControlWrapper implements MediaPlayerControl, IVideoController {
31 return abstractPlayer; 31 return abstractPlayer;
32 } 32 }
33 33
34 - @Override  
35 - public int getMediaCount() {  
36 - return mPlayerControl.getMediaCount();  
37 - } 34 +// @Override
  35 +// public int getMediaCount() {
  36 +// return mPlayerControl.getMediaCount();
  37 +// }
38 38
39 @Override 39 @Override
40 public void start() { 40 public void start() {
cloud/video/src/main/java/com/libs/video/video/exoplayer/controller/IControlComponent.java
@@ -65,4 +65,9 @@ public interface IControlComponent { @@ -65,4 +65,9 @@ public interface IControlComponent {
65 * @param exception 65 * @param exception
66 */ 66 */
67 void onPlayError(PlayErrorException exception); 67 void onPlayError(PlayErrorException exception);
  68 +
  69 + /**屏幕方向改变
  70 + * @param orientation
  71 + */
  72 +// void onScreenOrientationChanged(int orientation);
68 } 73 }
cloud/video/src/main/java/com/libs/video/video/exoplayer/controller/MediaPlayerControl.java
@@ -9,7 +9,7 @@ import com.libs.video.video.exoplayer.play.AbstractPlayer; @@ -9,7 +9,7 @@ import com.libs.video.video.exoplayer.play.AbstractPlayer;
9 */ 9 */
10 public interface MediaPlayerControl { 10 public interface MediaPlayerControl {
11 11
12 - int getMediaCount(); 12 +// int getMediaCount();
13 13
14 void start(); 14 void start();
15 15
cloud/video/src/main/java/com/libs/video/video/exoplayer/controller/StandardVideoController.java
@@ -16,6 +16,7 @@ import com.cnlive.cloud.video.R; @@ -16,6 +16,7 @@ import com.cnlive.cloud.video.R;
16 import com.libs.video.video.exoplayer.PlayErrorException; 16 import com.libs.video.video.exoplayer.PlayErrorException;
17 import com.libs.video.video.exoplayer.component.DefaultCompleteView; 17 import com.libs.video.video.exoplayer.component.DefaultCompleteView;
18 import com.libs.video.video.exoplayer.component.DefaultErrorView; 18 import com.libs.video.video.exoplayer.component.DefaultErrorView;
  19 +import com.libs.video.video.exoplayer.component.DefaultYoukuPrepareView;
19 import com.libs.video.video.exoplayer.component.GestureView; 20 import com.libs.video.video.exoplayer.component.GestureView;
20 import com.libs.video.video.exoplayer.component.LiveControlView; 21 import com.libs.video.video.exoplayer.component.LiveControlView;
21 import com.libs.video.video.exoplayer.component.DefaultPrepareView; 22 import com.libs.video.video.exoplayer.component.DefaultPrepareView;
@@ -37,7 +38,7 @@ public class StandardVideoController extends GestureVideoController implements V @@ -37,7 +38,7 @@ public class StandardVideoController extends GestureVideoController implements V
37 38
38 protected ImageView mLockButton;//锁屏按钮 39 protected ImageView mLockButton;//锁屏按钮
39 40
40 - protected ProgressBar mLoadingProgress; 41 +// protected ProgressBar mLoadingProgress;
41 42
42 public StandardVideoController(@NonNull Context context) { 43 public StandardVideoController(@NonNull Context context) {
43 this(context, null); 44 this(context, null);
@@ -61,7 +62,7 @@ public class StandardVideoController extends GestureVideoController implements V @@ -61,7 +62,7 @@ public class StandardVideoController extends GestureVideoController implements V
61 super.initView(); 62 super.initView();
62 mLockButton = findViewById(R.id.lock); 63 mLockButton = findViewById(R.id.lock);
63 mLockButton.setOnClickListener(this); 64 mLockButton.setOnClickListener(this);
64 - mLoadingProgress = findViewById(R.id.loading); 65 +// mLoadingProgress = findViewById(R.id.loading);
65 } 66 }
66 67
67 68
@@ -170,21 +171,21 @@ public class StandardVideoController extends GestureVideoController implements V @@ -170,21 +171,21 @@ public class StandardVideoController extends GestureVideoController implements V
170 //调用release方法会回到此状态 171 //调用release方法会回到此状态
171 case CNVideoView.STATE_IDLE: 172 case CNVideoView.STATE_IDLE:
172 mLockButton.setSelected(false); 173 mLockButton.setSelected(false);
173 - mLoadingProgress.setVisibility(GONE); 174 +// mLoadingProgress.setVisibility(GONE);
174 break; 175 break;
175 case CNVideoView.STATE_PLAYING: 176 case CNVideoView.STATE_PLAYING:
176 case CNVideoView.STATE_PAUSED: 177 case CNVideoView.STATE_PAUSED:
177 case CNVideoView.STATE_PREPARED: 178 case CNVideoView.STATE_PREPARED:
178 case CNVideoView.STATE_ERROR: 179 case CNVideoView.STATE_ERROR:
179 case CNVideoView.STATE_BUFFERED: 180 case CNVideoView.STATE_BUFFERED:
180 - mLoadingProgress.setVisibility(GONE); 181 +// mLoadingProgress.setVisibility(GONE);
181 break; 182 break;
182 case CNVideoView.STATE_PREPARING: 183 case CNVideoView.STATE_PREPARING:
183 case CNVideoView.STATE_BUFFERING: 184 case CNVideoView.STATE_BUFFERING:
184 - mLoadingProgress.setVisibility(VISIBLE); 185 +// mLoadingProgress.setVisibility(VISIBLE);
185 break; 186 break;
186 case CNVideoView.STATE_PLAYBACK_COMPLETED: 187 case CNVideoView.STATE_PLAYBACK_COMPLETED:
187 - mLoadingProgress.setVisibility(GONE); 188 +// mLoadingProgress.setVisibility(GONE);
188 mLockButton.setVisibility(GONE); 189 mLockButton.setVisibility(GONE);
189 mLockButton.setSelected(false); 190 mLockButton.setSelected(false);
190 break; 191 break;
cloud/video/src/main/java/com/libs/video/video/exoplayer/play/CNVideoView.java
@@ -28,10 +28,13 @@ import com.libs.video.video.exoplayer.render.IRenderView; @@ -28,10 +28,13 @@ import com.libs.video.video.exoplayer.render.IRenderView;
28 import com.libs.video.video.exoplayer.render.RenderViewFactory; 28 import com.libs.video.video.exoplayer.render.RenderViewFactory;
29 29
30 import java.io.IOException; 30 import java.io.IOException;
  31 +import java.lang.annotation.Retention;
  32 +import java.lang.annotation.RetentionPolicy;
31 import java.util.ArrayList; 33 import java.util.ArrayList;
32 import java.util.List; 34 import java.util.List;
33 import java.util.Map; 35 import java.util.Map;
34 36
  37 +import androidx.annotation.IntDef;
35 import androidx.annotation.NonNull; 38 import androidx.annotation.NonNull;
36 import androidx.annotation.Nullable; 39 import androidx.annotation.Nullable;
37 40
@@ -125,8 +128,8 @@ public class CNVideoView&lt;P extends AbstractPlayer&gt; extends FrameLayout @@ -125,8 +128,8 @@ public class CNVideoView&lt;P extends AbstractPlayer&gt; extends FrameLayout
125 */ 128 */
126 private int mPlayerBackgroundColor; 129 private int mPlayerBackgroundColor;
127 130
128 - private List<String> dataSource;  
129 - private int curentPlayIndex; 131 +// private List<String> dataSource;
  132 +// private int curentPlayIndex;
130 133
131 public CNVideoView(@NonNull Context context) { 134 public CNVideoView(@NonNull Context context) {
132 this(context, null); 135 this(context, null);
@@ -138,7 +141,7 @@ public class CNVideoView&lt;P extends AbstractPlayer&gt; extends FrameLayout @@ -138,7 +141,7 @@ public class CNVideoView&lt;P extends AbstractPlayer&gt; extends FrameLayout
138 141
139 public CNVideoView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) { 142 public CNVideoView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
140 super(context, attrs, defStyleAttr); 143 super(context, attrs, defStyleAttr);
141 - dataSource = new ArrayList<>(); 144 +// dataSource = new ArrayList<>();
142 //读取全局配置 145 //读取全局配置
143 VideoViewConfig config = VideoViewManager.getConfig(); 146 VideoViewConfig config = VideoViewManager.getConfig();
144 mEnableAudioFocus = config.mEnableAudioFocus; 147 mEnableAudioFocus = config.mEnableAudioFocus;
@@ -184,16 +187,16 @@ public class CNVideoView&lt;P extends AbstractPlayer&gt; extends FrameLayout @@ -184,16 +187,16 @@ public class CNVideoView&lt;P extends AbstractPlayer&gt; extends FrameLayout
184 } 187 }
185 188
186 189
187 -  
188 - /**  
189 - * 当前媒体数量  
190 - *  
191 - * @return  
192 - */  
193 - @Override  
194 - public int getMediaCount() {  
195 - return dataSource.size();  
196 - } 190 +//
  191 +// /**
  192 +// * 当前媒体数量
  193 +// *
  194 +// * @return
  195 +// */
  196 +// @Override
  197 +// public int getMediaCount() {
  198 +// return dataSource.size();
  199 +// }
197 200
198 /** 201 /**
199 * 开始播放,注意:调用此方法后必须调用{@link #release()}释放播放器,否则会导致内存泄漏 202 * 开始播放,注意:调用此方法后必须调用{@link #release()}释放播放器,否则会导致内存泄漏
@@ -579,11 +582,11 @@ public class CNVideoView&lt;P extends AbstractPlayer&gt; extends FrameLayout @@ -579,11 +582,11 @@ public class CNVideoView&lt;P extends AbstractPlayer&gt; extends FrameLayout
579 } 582 }
580 setPlayState(STATE_PLAYBACK_COMPLETED); 583 setPlayState(STATE_PLAYBACK_COMPLETED);
581 584
582 - if (curentPlayIndex + 1 <= dataSource.size() - 1) {  
583 - curentPlayIndex += 1;  
584 - mUrl = dataSource.get(curentPlayIndex);  
585 - replay(true);  
586 - } 585 +// if (curentPlayIndex + 1 <= dataSource.size() - 1) {
  586 +// curentPlayIndex += 1;
  587 +// mUrl = dataSource.get(curentPlayIndex);
  588 +// replay(true);
  589 +// }
587 } 590 }
588 591
589 @Override 592 @Override
@@ -655,19 +658,19 @@ public class CNVideoView&lt;P extends AbstractPlayer&gt; extends FrameLayout @@ -655,19 +658,19 @@ public class CNVideoView&lt;P extends AbstractPlayer&gt; extends FrameLayout
655 * 设置视频地址 658 * 设置视频地址
656 */ 659 */
657 public void setUrl(String url) { 660 public void setUrl(String url) {
658 - dataSource.clear();  
659 - dataSource.add(url);  
660 - curentPlayIndex = 0;  
661 - setUrl(dataSource.get(0), null); 661 +// dataSource.clear();
  662 +// dataSource.add(url);
  663 +// curentPlayIndex = 0;
  664 + setUrl(url, null);
662 } 665 }
663 666
664 - public void setDataSource(List<String> url) {  
665 - dataSource.clear();  
666 - dataSource.addAll(url);  
667 - curentPlayIndex = 0;  
668 - setUrl(dataSource.get(0), null);  
669 -  
670 - } 667 +// public void setDataSource(List<String> url) {
  668 +// dataSource.clear();
  669 +// dataSource.addAll(url);
  670 +// curentPlayIndex = 0;
  671 +// setUrl(dataSource.get(0), null);
  672 +//
  673 +// }
671 674
672 /** 675 /**
673 * 设置包含请求头信息的视频地址 676 * 设置包含请求头信息的视频地址
@@ -960,7 +963,7 @@ public class CNVideoView&lt;P extends AbstractPlayer&gt; extends FrameLayout @@ -960,7 +963,7 @@ public class CNVideoView&lt;P extends AbstractPlayer&gt; extends FrameLayout
960 * 设置视频比例 963 * 设置视频比例
961 */ 964 */
962 @Override 965 @Override
963 - public void setScreenScaleType(int screenScaleType) { 966 + public void setScreenScaleType(@CNVideoView.screenScalType int screenScaleType) {
964 mCurrentScreenScaleType = screenScaleType; 967 mCurrentScreenScaleType = screenScaleType;
965 if (mRenderView != null) { 968 if (mRenderView != null) {
966 mRenderView.setScaleType(screenScaleType); 969 mRenderView.setScaleType(screenScaleType);
@@ -1144,4 +1147,11 @@ public class CNVideoView&lt;P extends AbstractPlayer&gt; extends FrameLayout @@ -1144,4 +1147,11 @@ public class CNVideoView&lt;P extends AbstractPlayer&gt; extends FrameLayout
1144 } 1147 }
1145 1148
1146 1149
  1150 + /**
  1151 + * 视频缩放类型
  1152 + */
  1153 + @IntDef({SCREEN_SCALE_DEFAULT,SCREEN_SCALE_16_9,SCREEN_SCALE_4_3,SCREEN_SCALE_MATCH_PARENT,SCREEN_SCALE_ORIGINAL,SCREEN_SCALE_CENTER_CROP})
  1154 + @Retention(RetentionPolicy.SOURCE)
  1155 + public @interface screenScalType {
  1156 + }
1147 } 1157 }
cloud/video/src/main/res/drawable-hdpi/loading_00.png 0 → 100644

390 Bytes

cloud/video/src/main/res/drawable-hdpi/loading_01.png 0 → 100644

363 Bytes

cloud/video/src/main/res/drawable-hdpi/loading_02.png 0 → 100644

378 Bytes

cloud/video/src/main/res/drawable-hdpi/loading_03.png 0 → 100644

379 Bytes

cloud/video/src/main/res/drawable-hdpi/loading_04.png 0 → 100644

384 Bytes

cloud/video/src/main/res/drawable-hdpi/loading_05.png 0 → 100644

419 Bytes

cloud/video/src/main/res/drawable-hdpi/loading_06.png 0 → 100644

404 Bytes

cloud/video/src/main/res/drawable-hdpi/loading_07.png 0 → 100644

372 Bytes

cloud/video/src/main/res/drawable-hdpi/loading_08.png 0 → 100644

369 Bytes

cloud/video/src/main/res/drawable-hdpi/loading_09.png 0 → 100644

408 Bytes

cloud/video/src/main/res/drawable-hdpi/loading_10.png 0 → 100644

419 Bytes

cloud/video/src/main/res/drawable-hdpi/loading_11.png 0 → 100644

388 Bytes

cloud/video/src/main/res/drawable-hdpi/loading_12.png 0 → 100644

382 Bytes

cloud/video/src/main/res/drawable-hdpi/loading_13.png 0 → 100644

386 Bytes

cloud/video/src/main/res/drawable-hdpi/loading_14.png 0 → 100644

363 Bytes

cloud/video/src/main/res/drawable-hdpi/loading_15.png 0 → 100644

385 Bytes

cloud/video/src/main/res/drawable-hdpi/loading_16.png 0 → 100644

375 Bytes

cloud/video/src/main/res/drawable-hdpi/loading_17.png 0 → 100644

383 Bytes

cloud/video/src/main/res/drawable-hdpi/loading_18.png 0 → 100644

387 Bytes

cloud/video/src/main/res/drawable-hdpi/loading_19.png 0 → 100644

389 Bytes

cloud/video/src/main/res/drawable-hdpi/loading_20.png 0 → 100644

429 Bytes

cloud/video/src/main/res/drawable-hdpi/loading_21.png 0 → 100644

411 Bytes

cloud/video/src/main/res/drawable-hdpi/loading_22.png 0 → 100644

369 Bytes

cloud/video/src/main/res/drawable-hdpi/loading_23.png 0 → 100644

375 Bytes

cloud/video/src/main/res/drawable-hdpi/loading_24.png 0 → 100644

403 Bytes

cloud/video/src/main/res/drawable-hdpi/loading_25.png 0 → 100644

425 Bytes

cloud/video/src/main/res/drawable-hdpi/loading_26.png 0 → 100644

390 Bytes

cloud/video/src/main/res/drawable-hdpi/loading_27.png 0 → 100644

382 Bytes

cloud/video/src/main/res/drawable-hdpi/loading_28.png 0 → 100644

374 Bytes

cloud/video/src/main/res/drawable-hdpi/loading_29.png 0 → 100644

367 Bytes

cloud/video/src/main/res/drawable-hdpi/player_small_loading_view_bg.png 0 → 100644

11.7 KB

cloud/video/src/main/res/drawable-hdpi/xadsdk_youku_logo.png 0 → 100644

3.05 KB

cloud/video/src/main/res/drawable/anim_youku_prepare.xml 0 → 100644
  1 +<?xml version="1.0" encoding="utf-8"?>
  2 +<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
  3 + android:oneshot="false">
  4 + <item
  5 + android:drawable="@drawable/loading_00"
  6 + android:duration="100" />
  7 + <item
  8 + android:drawable="@drawable/loading_01"
  9 + android:duration="100" />
  10 + <item
  11 + android:drawable="@drawable/loading_02"
  12 + android:duration="100" />
  13 + <item
  14 + android:drawable="@drawable/loading_03"
  15 + android:duration="100" />
  16 + <item
  17 + android:drawable="@drawable/loading_04"
  18 + android:duration="100" />
  19 + <item
  20 + android:drawable="@drawable/loading_05"
  21 + android:duration="100" />
  22 + <item
  23 + android:drawable="@drawable/loading_06"
  24 + android:duration="100" />
  25 + <item
  26 + android:drawable="@drawable/loading_07"
  27 + android:duration="100" />
  28 + <item
  29 + android:drawable="@drawable/loading_08"
  30 + android:duration="100" />
  31 + <item
  32 + android:drawable="@drawable/loading_09"
  33 + android:duration="100" />
  34 + <item
  35 + android:drawable="@drawable/loading_10"
  36 + android:duration="100" />
  37 + <item
  38 + android:drawable="@drawable/loading_11"
  39 + android:duration="100" />
  40 + <item
  41 + android:drawable="@drawable/loading_12"
  42 + android:duration="100" />
  43 + <item
  44 + android:drawable="@drawable/loading_13"
  45 + android:duration="100" />
  46 + <item
  47 + android:drawable="@drawable/loading_14"
  48 + android:duration="100" />
  49 + <item
  50 + android:drawable="@drawable/loading_15"
  51 + android:duration="100" />
  52 + <item
  53 + android:drawable="@drawable/loading_16"
  54 + android:duration="100" />
  55 + <item
  56 + android:drawable="@drawable/loading_17"
  57 + android:duration="100" />
  58 + <item
  59 + android:drawable="@drawable/loading_18"
  60 + android:duration="100" />
  61 + <item
  62 + android:drawable="@drawable/loading_19"
  63 + android:duration="100" />
  64 + <item
  65 + android:drawable="@drawable/loading_20"
  66 + android:duration="100" />
  67 + <item
  68 + android:drawable="@drawable/loading_21"
  69 + android:duration="100" />
  70 + <item
  71 + android:drawable="@drawable/loading_22"
  72 + android:duration="100" />
  73 + <item
  74 + android:drawable="@drawable/loading_23"
  75 + android:duration="100" />
  76 + <item
  77 + android:drawable="@drawable/loading_24"
  78 + android:duration="100" />
  79 + <item
  80 + android:drawable="@drawable/loading_25"
  81 + android:duration="100" />
  82 + <item
  83 + android:drawable="@drawable/loading_26"
  84 + android:duration="100" />
  85 + <item
  86 + android:drawable="@drawable/loading_27"
  87 + android:duration="100" />
  88 + <item
  89 + android:drawable="@drawable/loading_28"
  90 + android:duration="100" />
  91 + <item
  92 + android:drawable="@drawable/loading_29"
  93 + android:duration="100" />
  94 +</animation-list>
0 \ No newline at end of file 95 \ No newline at end of file
cloud/video/src/main/res/layout/cnvideo_layout_youku_prepare_view.xml 0 → 100644
  1 +<?xml version="1.0" encoding="utf-8"?>
  2 +<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3 + xmlns:tools="http://schemas.android.com/tools"
  4 + android:layout_width="match_parent"
  5 + android:layout_height="match_parent"
  6 + android:background="@drawable/player_small_loading_view_bg">
  7 +
  8 +
  9 + <LinearLayout
  10 + android:layout_width="match_parent"
  11 + android:layout_height="match_parent"
  12 + android:gravity="center"
  13 + android:orientation="vertical">
  14 +
  15 + <ImageView
  16 + android:layout_width="120dp"
  17 + android:layout_height="50dp"
  18 + android:background="@drawable/xadsdk_youku_logo" />
  19 +
  20 + <TextView
  21 + android:layout_width="wrap_content"
  22 + android:layout_height="wrap_content"
  23 + android:text="加载中"
  24 + android:textColor="@color/my_dialog_line"
  25 + android:textSize="15sp" />
  26 +
  27 + <View
  28 + android:id="@+id/view_youku_loading"
  29 + android:layout_width="30dp"
  30 + android:layout_height="30dp"
  31 + android:background="@drawable/anim_youku_prepare" />
  32 + </LinearLayout>
  33 +
  34 + <FrameLayout
  35 + android:id="@+id/net_warning_layout"
  36 + android:layout_width="match_parent"
  37 + android:layout_height="match_parent"
  38 + android:background="@android:color/black"
  39 + android:clickable="true"
  40 + android:focusable="true"
  41 + android:visibility="gone">
  42 +
  43 + <LinearLayout
  44 + android:layout_width="match_parent"
  45 + android:layout_height="match_parent"
  46 + android:gravity="center"
  47 + android:orientation="vertical">
  48 +
  49 + <TextView
  50 + android:id="@+id/message"
  51 + android:layout_width="wrap_content"
  52 + android:layout_height="wrap_content"
  53 + android:gravity="center"
  54 + android:text="@string/cnvideo_wifi_tip"
  55 + android:textColor="@android:color/white" />
  56 +
  57 + <TextView
  58 + android:id="@+id/status_btn"
  59 + android:layout_width="wrap_content"
  60 + android:layout_height="wrap_content"
  61 + android:layout_marginTop="16dp"
  62 + android:background="@drawable/cnvideo_shape_status_view_btn"
  63 + android:gravity="center"
  64 + android:paddingLeft="16dp"
  65 + android:paddingTop="4dp"
  66 + android:paddingRight="16dp"
  67 + android:paddingBottom="4dp"
  68 + android:text="@string/cnvideo_continue_play"
  69 + android:textColor="@android:color/white" />
  70 +
  71 + </LinearLayout>
  72 + </FrameLayout>
  73 +
  74 +</FrameLayout>
0 \ No newline at end of file 75 \ No newline at end of file
config.gradle
@@ -80,10 +80,10 @@ ext { @@ -80,10 +80,10 @@ ext {
80 // //权限 80 // //权限
81 easypermissions : 'pub.devrel:easypermissions:1.0.0', 81 easypermissions : 'pub.devrel:easypermissions:1.0.0',
82 //MVP 82 //MVP
83 - mvp : 'com.hannesdorfmann.mosby3:mvp:3.0.4',  
84 - mvp_viewstate : 'com.hannesdorfmann.mosby3:viewstate:3.0.4',  
85 - mvp_lce : 'com.hannesdorfmann.mosby3:mvp-lce:3.0.4',  
86 - mvp_nullobject_presenter: 'com.hannesdorfmann.mosby3:mvp-nullobject-presenter:3.0.4', 83 + mvp : 'com.hannesdorfmann.mosby3:mvp:3.1.1',
  84 + mvp_viewstate : 'com.hannesdorfmann.mosby3:viewstate:3.1.1',
  85 + mvp_lce : 'com.hannesdorfmann.mosby3:mvp-lce:3.1.1',
  86 + mvp_nullobject_presenter: 'com.hannesdorfmann.mosby3:mvp-nullobject-presenter:3.1.1',
87 //UI框架库 87 //UI框架库
88 qmui : 'com.qmuiteam:qmui:1.4.0', 88 qmui : 'com.qmuiteam:qmui:1.4.0',
89 qmui_arch : 'com.qmuiteam:arch:0.6.1', 89 qmui_arch : 'com.qmuiteam:arch:0.6.1',
@@ -136,10 +136,10 @@ ext { @@ -136,10 +136,10 @@ ext {
136 library.qmui, 136 library.qmui,
137 library.qmui_arch, 137 library.qmui_arch,
138 //mvp 138 //mvp
139 -// library.mvp,  
140 -// library.mvp_lce,  
141 -// library.mvp_nullobject_presenter,  
142 -// library.mvp_viewstate, 139 + library.mvp,
  140 + library.mvp_lce,
  141 + library.mvp_nullobject_presenter,
  142 + library.mvp_viewstate,
143 //图片加载Glide 143 //图片加载Glide
144 glide.api, 144 glide.api,
145 glide.transformations, 145 glide.transformations,
core/base/src/main/java/com/hannesdorfmann/mosby3/ActivityScopedCache.java deleted 100644 → 0
1 -/*  
2 - * Copyright 2017 Hannes Dorfmann.  
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 -  
18 -package com.hannesdorfmann.mosby3;  
19 -  
20 -import android.os.Build;  
21 -import android.util.ArrayMap;  
22 -  
23 -import androidx.annotation.NonNull;  
24 -import androidx.annotation.Nullable;  
25 -import androidx.annotation.RequiresApi;  
26 -  
27 -import com.hannesdorfmann.mosby3.mvp.MvpPresenter;  
28 -import com.hannesdorfmann.mosby3.mvp.MvpView;  
29 -import java.util.Map;  
30 -  
31 -/**  
32 - * This class basically represents a Map for View Id to the Presenter / ViewState.  
33 - * One instance of this class is also associated by {@link PresenterManager} to one Activity (kept  
34 - * across screen orientation changes)  
35 - *  
36 - * @author Hannes Dorfmann  
37 - * @since 3.0.0  
38 - */  
39 -@RequiresApi(api = Build.VERSION_CODES.KITKAT)  
40 -class ActivityScopedCache {  
41 -  
42 - private final Map<String, PresenterHolder> presenterMap = new ArrayMap<>();  
43 -  
44 - ActivityScopedCache() {  
45 - // package private  
46 - }  
47 -  
48 - public void clear() {  
49 - /*  
50 - // TODO: can this check if there are still Presenters in the internal cache that must be detached? Maybe post() / postDelayed() on the MainThreadLooper()  
51 - // it doesnt work out that well, because super.onDestroy() which then invokes PresenterManager.clear() might be called before the MviDelegates did their job to remove the Presenter from cache and detach the view permanently  
52 -  
53 - for (PresenterHolder holder : presenterMap.values()) {  
54 - // This should never be the case: If there were some presenters left in the internal cache,  
55 - // a delegate didn't work correctly as expected  
56 - if (holder.presenter != null) {  
57 - holder.presenter.detachView(false);  
58 - if (PresenterManager.DEBUG) {  
59 - Log.w(PresenterManager.DEBUG_TAG,  
60 - "Found a Presenter that is still alive. This should never happen. It seems that a MvpDelegate / MviDelegate didn't work correctly because this Delegate should have removed the presenter. The Presenter was "  
61 - + holder.presenter);  
62 - }  
63 - }  
64 - }  
65 - */  
66 - presenterMap.clear();  
67 - }  
68 -  
69 - /**  
70 - * Get the Presenter for a given {@link MvpView} if exists or <code>null</code>  
71 - *  
72 - * @param viewId The mosby internal view id  
73 - * @param <P> The type tof the {@link MvpPresenter}  
74 - * @return The Presenter for the given view id or <code>null</code>  
75 - */  
76 - @Nullable  
77 - public <P> P getPresenter(@NonNull String viewId) {  
78 - PresenterHolder holder = presenterMap.get(viewId);  
79 - return holder == null ? null : (P) holder.presenter;  
80 - }  
81 -  
82 - /**  
83 - * Get the ViewState for a given {@link MvpView} if exists or <code>null</code>  
84 - *  
85 - * @param viewId The mosby internal view id  
86 - * @param <VS> The type tof the {@link MvpPresenter}  
87 - * @return The ViewState for the given view id or <code>null</code>  
88 - */  
89 - @Nullable public <VS> VS getViewState(@NonNull String viewId) {  
90 - PresenterHolder holder = presenterMap.get(viewId);  
91 - return holder == null ? null : (VS) holder.viewState;  
92 - }  
93 -  
94 - /**  
95 - * Put the presenter in the internal cache  
96 - *  
97 - * @param viewId The mosby internal View id of the {@link MvpView} which the presenter is  
98 - * associated to.  
99 - * @param presenter The Presenter  
100 - */  
101 - public void putPresenter(@NonNull String viewId,  
102 - @NonNull MvpPresenter<? extends MvpView> presenter) {  
103 -  
104 - if (viewId == null) {  
105 - throw new NullPointerException("ViewId is null");  
106 - }  
107 -  
108 - if (presenter == null) {  
109 - throw new NullPointerException("Presenter is null");  
110 - }  
111 -  
112 - PresenterHolder presenterHolder = presenterMap.get(viewId);  
113 - if (presenterHolder == null) {  
114 - presenterHolder = new PresenterHolder();  
115 - presenterHolder.presenter = presenter;  
116 - presenterMap.put(viewId, presenterHolder);  
117 - } else {  
118 - presenterHolder.presenter = presenter;  
119 - }  
120 - }  
121 -  
122 -  
123 - /**  
124 - * Put the viewstate in the internal cache  
125 - *  
126 - * @param viewId The mosby internal View id of the {@link MvpView} which the presenter is  
127 - * associated to.  
128 - * @param viewState The Viewstate  
129 - */  
130 - public void putViewState(@NonNull String viewId,  
131 - @NonNull Object viewState) {  
132 -  
133 - if (viewId == null) {  
134 - throw new NullPointerException("ViewId is null");  
135 - }  
136 -  
137 - if (viewState == null) {  
138 - throw new NullPointerException("ViewState is null");  
139 - }  
140 -  
141 - PresenterHolder presenterHolder = presenterMap.get(viewId);  
142 - if (presenterHolder == null) {  
143 - presenterHolder = new PresenterHolder();  
144 - presenterHolder.viewState = viewState;  
145 - presenterMap.put(viewId, presenterHolder);  
146 - } else {  
147 - presenterHolder.viewState = viewState;  
148 - }  
149 - }  
150 -  
151 - /**  
152 - * Removes the Presenter (and ViewState) from the internal storage  
153 - *  
154 - * @param viewId The msoby internal view id  
155 - */  
156 - public void remove(@NonNull String viewId) {  
157 -  
158 - if (viewId == null) {  
159 - throw new NullPointerException("View Id is null");  
160 - }  
161 -  
162 - presenterMap.remove(viewId);  
163 - }  
164 -  
165 - /**  
166 - * Internal config change Cache entry  
167 - */  
168 - static final class PresenterHolder {  
169 - private MvpPresenter<?> presenter;  
170 - private Object viewState; // workaround: didn't want to introduce dependency to viewstate module  
171 - }  
172 -}  
core/base/src/main/java/com/hannesdorfmann/mosby3/MosbySavedState.java deleted 100644 → 0
1 -/*  
2 - * Copyright 2016 Hannes Dorfmann.  
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.hannesdorfmann.mosby3;  
18 -  
19 -import android.os.Build;  
20 -import android.os.Parcel;  
21 -import android.os.Parcelable;  
22 -import android.view.AbsSavedState;  
23 -  
24 -import androidx.annotation.RequiresApi;  
25 -import androidx.core.os.ParcelableCompat;  
26 -import androidx.core.os.ParcelableCompatCreatorCallbacks;  
27 -  
28 -/**  
29 - * The SavedState implementation to store the view's internal id to  
30 - *  
31 - * @author Hannes Dorfmann  
32 - * @since 3.0  
33 - */  
34 -public class MosbySavedState extends AbsSavedState {  
35 -  
36 - public static final Creator<MosbySavedState> CREATOR =  
37 - ParcelableCompat.newCreator(new ParcelableCompatCreatorCallbacks<MosbySavedState>() {  
38 - public MosbySavedState createFromParcel(Parcel in, ClassLoader loader) {  
39 - if (loader == null) {  
40 - loader = MosbySavedState.class.getClassLoader();  
41 - }  
42 - return new MosbySavedState(in, loader);  
43 - }  
44 -  
45 - public MosbySavedState[] newArray(int size) {  
46 - return new MosbySavedState[size];  
47 - }  
48 - });  
49 -  
50 - private String mosbyViewId;  
51 -  
52 - public MosbySavedState(Parcelable superState, String mosbyViewId) {  
53 - super(superState);  
54 - this.mosbyViewId = mosbyViewId;  
55 - }  
56 -  
57 - protected MosbySavedState(Parcel in, ClassLoader loader) {  
58 - super(in, loader);  
59 - this.mosbyViewId = in.readString();  
60 - }  
61 -  
62 - @Override public void writeToParcel(Parcel out, int flags) {  
63 - super.writeToParcel(out, flags);  
64 - out.writeString(mosbyViewId);  
65 - }  
66 -  
67 - public String getMosbyViewId() {  
68 - return mosbyViewId;  
69 - }  
70 -  
71 -}  
core/base/src/main/java/com/hannesdorfmann/mosby3/PresenterManager.java deleted 100644 → 0
1 -package com.hannesdorfmann.mosby3;  
2 -  
3 -import android.app.Activity;  
4 -import android.app.Application;  
5 -import android.content.Context;  
6 -import android.content.ContextWrapper;  
7 -import android.os.Build;  
8 -import android.os.Bundle;  
9 -import android.util.ArrayMap;  
10 -import android.util.Log;  
11 -import android.view.View;  
12 -  
13 -import androidx.annotation.MainThread;  
14 -import androidx.annotation.NonNull;  
15 -import androidx.annotation.Nullable;  
16 -import androidx.annotation.RequiresApi;  
17 -  
18 -import com.hannesdorfmann.mosby3.mvp.MvpPresenter;  
19 -import com.hannesdorfmann.mosby3.mvp.MvpView;  
20 -import java.util.Map;  
21 -import java.util.UUID;  
22 -  
23 -/**  
24 - * A internal class responsible to save internal presenter instances during screen orientation  
25 - * changes and reattach the presenter afterwards.  
26 - *  
27 - * <p>  
28 - * The idea is that each MVP View (like a Activity, Fragment, ViewGroup) will get a unique view id.  
29 - * This view id is  
30 - * used to store the presenter and viewstate in it. After screen orientation changes we can reuse  
31 - * the presenter and viewstate by querying for the given view id (must be saved in view's state  
32 - * somehow).  
33 - * </p>  
34 - *  
35 - * @author Hannes Dorfmann  
36 - * @since 3.0  
37 - */  
38 -@RequiresApi(api = Build.VERSION_CODES.KITKAT)  
39 -final public class PresenterManager {  
40 -  
41 - public static boolean DEBUG = false;  
42 - public static final String DEBUG_TAG = "PresenterManager";  
43 - final static String KEY_ACTIVITY_ID = "com.hannesdorfmann.mosby3.MosbyPresenterManagerActivityId";  
44 -  
45 - private final static Map<Activity, String> activityIdMap = new ArrayMap<>();  
46 - private final static Map<String, ActivityScopedCache> activityScopedCacheMap = new ArrayMap<>();  
47 -  
48 - static final Application.ActivityLifecycleCallbacks activityLifecycleCallbacks =  
49 - new Application.ActivityLifecycleCallbacks() {  
50 - @Override public void onActivityCreated(Activity activity, Bundle savedInstanceState) {  
51 - if (savedInstanceState != null) {  
52 - String activityId = savedInstanceState.getString(KEY_ACTIVITY_ID);  
53 - if (activityId != null) {  
54 - // After a screen orientation change we map the newly created Activity to the same  
55 - // Activity ID as the previous activity has had (before screen orientation change)  
56 - activityIdMap.put(activity, activityId);  
57 - }  
58 - }  
59 - }  
60 -  
61 - @Override public void onActivitySaveInstanceState(Activity activity, Bundle outState) {  
62 - // Save the activityId into bundle so that the other  
63 - String activityId = activityIdMap.get(activity);  
64 - if (activityId != null) {  
65 - outState.putString(KEY_ACTIVITY_ID, activityId);  
66 - }  
67 - }  
68 -  
69 - @Override public void onActivityStarted(Activity activity) {  
70 - }  
71 -  
72 - @Override public void onActivityResumed(Activity activity) {  
73 - }  
74 -  
75 - @Override public void onActivityPaused(Activity activity) {  
76 -  
77 - }  
78 -  
79 - @Override public void onActivityStopped(Activity activity) {  
80 - }  
81 -  
82 - @Override public void onActivityDestroyed(Activity activity) {  
83 - if (!activity.isChangingConfigurations()) {  
84 - // Activity will be destroyed permanently, so reset the cache  
85 - String activityId = activityIdMap.get(activity);  
86 - if (activityId != null) {  
87 - ActivityScopedCache scopedCache = activityScopedCacheMap.get(activityId);  
88 - if (scopedCache != null) {  
89 - scopedCache.clear();  
90 - activityScopedCacheMap.remove(activityId);  
91 - }  
92 -  
93 - // No Activity Scoped cache available, so unregister  
94 - if (activityScopedCacheMap.isEmpty()) {  
95 - // All Mosby related activities are destroyed, so we can remove the activity lifecylce listener  
96 - activity.getApplication()  
97 - .unregisterActivityLifecycleCallbacks(activityLifecycleCallbacks);  
98 - if (DEBUG) {  
99 - Log.d(DEBUG_TAG, "Unregistering ActivityLifecycleCallbacks");  
100 - }  
101 - }  
102 - }  
103 - }  
104 - activityIdMap.remove(activity);  
105 - }  
106 - };  
107 -  
108 - private PresenterManager() {  
109 - throw new RuntimeException("Not instantiatable!");  
110 - }  
111 -  
112 - /**  
113 - * Get an already existing {@link ActivityScopedCache} or creates a new one if not existing yet  
114 - *  
115 - * @param activity The Activitiy for which you want to get the activity scope for  
116 - * @return The {@link ActivityScopedCache} for the given Activity  
117 - */  
118 - @NonNull  
119 - @MainThread  
120 - static ActivityScopedCache getOrCreateActivityScopedCache(  
121 - @NonNull Activity activity) {  
122 - if (activity == null) {  
123 - throw new NullPointerException("Activity is null");  
124 - }  
125 -  
126 - String activityId = activityIdMap.get(activity);  
127 - if (activityId == null) {  
128 - // Activity not registered yet  
129 - activityId = UUID.randomUUID().toString();  
130 - activityIdMap.put(activity, activityId);  
131 -  
132 - if (activityIdMap.size() == 1) {  
133 - // Added the an Activity for the first time so register Activity LifecycleListener  
134 - activity.getApplication().registerActivityLifecycleCallbacks(activityLifecycleCallbacks);  
135 - if (DEBUG) {  
136 - Log.d(DEBUG_TAG, "Registering ActivityLifecycleCallbacks");  
137 - }  
138 - }  
139 - }  
140 -  
141 - ActivityScopedCache activityScopedCache = activityScopedCacheMap.get(activityId);  
142 - if (activityScopedCache == null) {  
143 - activityScopedCache = new ActivityScopedCache();  
144 - activityScopedCacheMap.put(activityId, activityScopedCache);  
145 - }  
146 -  
147 - return activityScopedCache;  
148 - }  
149 -  
150 - /**  
151 - * Get the {@link ActivityScopedCache} for the given Activity or <code>null</code> if no {@link  
152 - * ActivityScopedCache} exists for the given Activity  
153 - *  
154 - * @param activity The activity  
155 - * @return The {@link ActivityScopedCache} or null  
156 - * @see #getOrCreateActivityScopedCache(Activity)  
157 - */  
158 - @Nullable  
159 - @MainThread static ActivityScopedCache getActivityScope(@NonNull Activity activity) {  
160 - if (activity == null) {  
161 - throw new NullPointerException("Activity is null");  
162 - }  
163 - String activityId = activityIdMap.get(activity);  
164 - if (activityId == null) {  
165 - return null;  
166 - }  
167 -  
168 - return activityScopedCacheMap.get(activityId);  
169 - }  
170 -  
171 - /**  
172 - * Get the presenter for the View with the given (Mosby - internal) view Id or <code>null</code>  
173 - * if no presenter for the given view (via view id) exists.  
174 - *  
175 - * @param activity The Activity (used for scoping)  
176 - * @param viewId The mosby internal View Id (unique among all {@link MvpView}  
177 - * @param <P> The Presenter type  
178 - * @return The Presenter or <code>null</code>  
179 - */  
180 - @Nullable public static <P> P getPresenter(@NonNull Activity activity, @NonNull String viewId) {  
181 - if (activity == null) {  
182 - throw new NullPointerException("Activity is null");  
183 - }  
184 -  
185 - if (viewId == null) {  
186 - throw new NullPointerException("View id is null");  
187 - }  
188 -  
189 - ActivityScopedCache scopedCache = getActivityScope(activity);  
190 - return scopedCache == null ? null : (P) scopedCache.getPresenter(viewId);  
191 - }  
192 -  
193 - /**  
194 - * Get the ViewState (see mosby viestate modlue) for the View with the given (Mosby - internal)  
195 - * view Id or <code>null</code>  
196 - * if no viewstate for the given view exists.  
197 - *  
198 - * @param activity The Activity (used for scoping)  
199 - * @param viewId The mosby internal View Id (unique among all {@link MvpView}  
200 - * @param <VS> The type of the ViewState type  
201 - * @return The Presenter or <code>null</code>  
202 - */  
203 - @Nullable public static <VS> VS getViewState(@NonNull Activity activity, @NonNull String viewId) {  
204 - if (activity == null) {  
205 - throw new NullPointerException("Activity is null");  
206 - }  
207 -  
208 - if (viewId == null) {  
209 - throw new NullPointerException("View id is null");  
210 - }  
211 -  
212 - ActivityScopedCache scopedCache = getActivityScope(activity);  
213 - return scopedCache == null ? null : (VS) scopedCache.getViewState(viewId);  
214 - }  
215 -  
216 - /**  
217 - * Get the Activity of a context. This is typically used to determine the hosting activity of a  
218 - * {@link View}  
219 - *  
220 - * @param context The context  
221 - * @return The Activity or throws an Exception if Activity couldnt be determined  
222 - */  
223 - @NonNull public static Activity getActivity(@NonNull Context context) {  
224 - if (context == null) {  
225 - throw new NullPointerException("context == null");  
226 - }  
227 - if (context instanceof Activity) {  
228 - return (Activity) context;  
229 - }  
230 -  
231 - while (context instanceof ContextWrapper) {  
232 - if (context instanceof Activity) {  
233 - return (Activity) context;  
234 - }  
235 - context = ((ContextWrapper) context).getBaseContext();  
236 - }  
237 - throw new IllegalStateException("Could not find the surrounding Activity");  
238 - }  
239 -  
240 - /**  
241 - * Clears the internal (static) state. Used for testing.  
242 - */  
243 - static void reset() {  
244 - activityIdMap.clear();  
245 - for (ActivityScopedCache scopedCache : activityScopedCacheMap.values()) {  
246 - scopedCache.clear();  
247 - }  
248 -  
249 - activityScopedCacheMap.clear();  
250 - }  
251 -  
252 - /**  
253 - * Puts the presenter into the internal cache  
254 - *  
255 - * @param activity The parent activity  
256 - * @param viewId the view id (mosby internal)  
257 - * @param presenter the presenter  
258 - */  
259 - public static void putPresenter(@NonNull Activity activity, @NonNull String viewId,  
260 - @NonNull MvpPresenter<? extends MvpView> presenter) {  
261 - if (activity == null) {  
262 - throw new NullPointerException("Activity is null");  
263 - }  
264 -  
265 - ActivityScopedCache scopedCache = getOrCreateActivityScopedCache(activity);  
266 - scopedCache.putPresenter(viewId, presenter);  
267 - }  
268 -  
269 - /**  
270 - * Puts the presenter into the internal cache  
271 - *  
272 - * @param activity The parent activity  
273 - * @param viewId the view id (mosby internal)  
274 - * @param viewState the presenter  
275 - */  
276 - public static void putViewState(@NonNull Activity activity, @NonNull String viewId,  
277 - @NonNull Object viewState) {  
278 - if (activity == null) {  
279 - throw new NullPointerException("Activity is null");  
280 - }  
281 -  
282 - ActivityScopedCache scopedCache = getOrCreateActivityScopedCache(activity);  
283 - scopedCache.putViewState(viewId, viewState);  
284 - }  
285 -  
286 - /**  
287 - * Removes the Presenter (and ViewState) for the given View. Does nothing if no Presenter is  
288 - * stored internally with the given viewId  
289 - *  
290 - * @param activity The activity  
291 - * @param viewId The mosby internal view id  
292 - */  
293 - public static void remove(@NonNull Activity activity, @NonNull String viewId) {  
294 - if (activity == null) {  
295 - throw new NullPointerException("Activity is null");  
296 - }  
297 -  
298 - ActivityScopedCache activityScope = getActivityScope(activity);  
299 - if (activityScope != null) {  
300 - activityScope.remove(viewId);  
301 - }  
302 - }  
303 -}  
304 -  
305 -  
306 -  
core/base/src/main/java/com/hannesdorfmann/mosby3/mvp/MvpActivity.java deleted 100644 → 0
1 -/*  
2 - * Copyright 2015 Hannes Dorfmann.  
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.hannesdorfmann.mosby3.mvp;  
18 -  
19 -import android.os.Bundle;  
20 -  
21 -import androidx.annotation.NonNull;  
22 -import androidx.appcompat.app.AppCompatActivity;  
23 -  
24 -import com.hannesdorfmann.mosby3.mvp.delegate.ActivityMvpDelegate;  
25 -import com.hannesdorfmann.mosby3.mvp.delegate.ActivityMvpDelegateImpl;  
26 -  
27 -/**  
28 - * An Activity that uses a {@link MvpPresenter} to implement a Model-View-Presenter  
29 - * architecture.  
30 - *  
31 - * @author Hannes Dorfmann  
32 - * @since 1.0.0  
33 - */  
34 -public abstract class MvpActivity<V extends MvpView, P extends MvpPresenter<V>>  
35 - extends AppCompatActivity implements MvpView,  
36 - com.hannesdorfmann.mosby3.mvp.delegate.MvpDelegateCallback<V,P> {  
37 -  
38 - protected ActivityMvpDelegate mvpDelegate;  
39 - protected P presenter;  
40 - protected boolean retainInstance;  
41 -  
42 - @Override protected void onCreate(Bundle savedInstanceState) {  
43 - super.onCreate(savedInstanceState);  
44 - getMvpDelegate().onCreate(savedInstanceState);  
45 - }  
46 -  
47 - @Override protected void onDestroy() {  
48 - super.onDestroy();  
49 - getMvpDelegate().onDestroy();  
50 - }  
51 -  
52 - @Override protected void onSaveInstanceState(Bundle outState) {  
53 - super.onSaveInstanceState(outState);  
54 - getMvpDelegate().onSaveInstanceState(outState);  
55 - }  
56 -  
57 - @Override protected void onPause() {  
58 - super.onPause();  
59 - getMvpDelegate().onPause();  
60 - }  
61 -  
62 - @Override protected void onResume() {  
63 - super.onResume();  
64 - getMvpDelegate().onResume();  
65 - }  
66 -  
67 - @Override protected void onStart() {  
68 - super.onStart();  
69 - getMvpDelegate().onStart();  
70 - }  
71 -  
72 - @Override protected void onStop() {  
73 - super.onStop();  
74 - getMvpDelegate().onStop();  
75 - }  
76 -  
77 - @Override protected void onRestart() {  
78 - super.onRestart();  
79 - getMvpDelegate().onRestart();  
80 - }  
81 -  
82 - @Override public void onContentChanged() {  
83 - super.onContentChanged();  
84 - getMvpDelegate().onContentChanged();  
85 - }  
86 -  
87 - @Override protected void onPostCreate(Bundle savedInstanceState) {  
88 - super.onPostCreate(savedInstanceState);  
89 - getMvpDelegate().onPostCreate(savedInstanceState);  
90 - }  
91 -  
92 - /**  
93 - * Instantiate a presenter instance  
94 - *  
95 - * @return The {@link MvpPresenter} for this view  
96 - */  
97 - @NonNull  
98 - public abstract P createPresenter();  
99 -  
100 - /**  
101 - * Get the mvp delegate. This is internally used for creating presenter, attaching and detaching  
102 - * view from presenter.  
103 - *  
104 - * <p><b>Please note that only one instance of mvp delegate should be used per Activity  
105 - * instance</b>.  
106 - * </p>  
107 - *  
108 - * <p>  
109 - * Only override this method if you really know what you are doing.  
110 - * </p>  
111 - *  
112 - * @return {@link ActivityMvpDelegateImpl}  
113 - */  
114 - @NonNull protected ActivityMvpDelegate<V, P> getMvpDelegate() {  
115 - if (mvpDelegate == null) {  
116 - mvpDelegate = new ActivityMvpDelegateImpl(this, this, true);  
117 - }  
118 -  
119 - return mvpDelegate;  
120 - }  
121 -  
122 - @NonNull @Override public P getPresenter() {  
123 - return presenter;  
124 - }  
125 -  
126 - @Override public void setPresenter(@NonNull P presenter) {  
127 - this.presenter = presenter;  
128 - }  
129 -  
130 - @NonNull @Override public V getMvpView() {  
131 - return (V) this;  
132 - }  
133 -}  
core/base/src/main/java/com/hannesdorfmann/mosby3/mvp/MvpBasePresenter.java deleted 100644 → 0
1 -/*  
2 - * Copyright 2015 Hannes Dorfmann.  
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.hannesdorfmann.mosby3.mvp;  
18 -  
19 -  
20 -import androidx.annotation.NonNull;  
21 -import androidx.annotation.UiThread;  
22 -  
23 -import java.lang.ref.WeakReference;  
24 -  
25 -/**  
26 - * A base implementation of a {@link MvpPresenter} that uses a <b>WeakReference</b> for referring  
27 - * to the attached view.  
28 - * <p>  
29 - * Use {@link #ifViewAttached(ViewAction)} to interact with the view. Since the view is passive,  
30 - * usually a Presenter should not get any data from View: so calls like view.getUserId() should not be done.  
31 - * Rather write a method in your Presenter that takes the user id as parameter like this:  
32 - * {@code  
33 - * void doSomething(int userId){  
34 - * // do something  
35 - * ...  
36 - * <p>  
37 - * ifViewAttached( view -> view.showSuccessful())  
38 - * }  
39 - * <p>  
40 - * }  
41 - * </p>  
42 - *  
43 - * @param <V> type of the {@link MvpView}  
44 - * @author Hannes Dorfmann  
45 - * @since 1.0.0  
46 - */  
47 -public class MvpBasePresenter<V extends MvpView> implements MvpPresenter<V> {  
48 -  
49 - /**  
50 - * An Action that is executed to interact with the view.  
51 - * Usually a Presenter should not get any data from View: so calls like view.getUserId() should not be done.  
52 - * Rather write a method in your Presenter that takes the user id as parameter like this:  
53 - * {@code  
54 - * void doSomething(int userId){  
55 - * // do something  
56 - * ...  
57 - * <p>  
58 - * ifViewAttached( view -> view.showSuccessful())  
59 - * }  
60 - *  
61 - * @param <V> The Type of the View  
62 - */  
63 - public interface ViewAction<V> {  
64 -  
65 - /**  
66 - * This method will be invoked to run the action. Implement this method to interact with the view.  
67 - *  
68 - * @param view The reference to the view. Not null.  
69 - */  
70 - void run(@NonNull V view);  
71 - }  
72 -  
73 - private WeakReference<V> viewRef;  
74 - private boolean presenterDestroyed = false;  
75 -  
76 - @UiThread  
77 - @Override  
78 - public void attachView(V view) {  
79 - viewRef = new WeakReference<V>(view);  
80 - presenterDestroyed = false;  
81 - }  
82 -  
83 - /**  
84 - * Gets the attached view. You should always call {@link #isViewAttached()} to check if the view  
85 - * is attached to avoid NullPointerExceptions.  
86 - *  
87 - * @return <code>null</code>, if view is not attached, otherwise the concrete view instance  
88 - * @deprecated Use {@link #ifViewAttached(ViewAction)}  
89 - */  
90 - @Deprecated  
91 - @UiThread  
92 - public V getView() {  
93 - return viewRef == null ? null : viewRef.get();  
94 - }  
95 -  
96 - /**  
97 - * Checks if a view is attached to this presenter. You should always call this method before  
98 - * calling {@link #getView()} to get the view instance.  
99 - *  
100 - * @deprecated Use {@link #ifViewAttached(ViewAction)}  
101 - */  
102 - @Deprecated  
103 - @UiThread  
104 - public boolean isViewAttached() {  
105 - return viewRef != null && viewRef.get() != null;  
106 - }  
107 -  
108 - /**  
109 - * {@inheritDoc}  
110 - */  
111 - @Deprecated  
112 - @UiThread  
113 - @Override  
114 - public void detachView(boolean retainInstance) {  
115 - }  
116 -  
117 - /**  
118 - * Executes the passed Action only if the View is attached.  
119 - * If no View is attached, either an exception is thrown (if parameter exceptionIfViewNotAttached  
120 - * is true) or the action is just not executed (no exception thrown).  
121 - * Note that if no view is attached, this will not re-execute the given action if the View gets  
122 - * re-attached.  
123 - *  
124 - * @param exceptionIfViewNotAttached true, if an exception should be thrown if no view is  
125 - * attached while trying to execute the action. false, if no exception should be thrown (the action  
126 - * will not be executed since no view is attached)  
127 - * @param action The {@link ViewAction} that will be executed if a view is attached. This is  
128 - * where you call view.isLoading etc. Use the view reference passed as parameter to {@link  
129 - * ViewAction#run(Object)} and not deprecated method {@link #getView()}  
130 - */  
131 - protected final void ifViewAttached(boolean exceptionIfViewNotAttached, ViewAction<V> action) {  
132 - final V view = viewRef == null ? null : viewRef.get();  
133 - if (view != null) {  
134 - action.run(view);  
135 - } else if (exceptionIfViewNotAttached) {  
136 - throw new IllegalStateException(  
137 - "No View attached to Presenter. Presenter destroyed = " + presenterDestroyed);  
138 - }  
139 - }  
140 -  
141 - /**  
142 - * Calls {@link #ifViewAttached(boolean, ViewAction)} with false as first parameter (don't throw  
143 - * exception if view not attached).  
144 - *  
145 - * @see #ifViewAttached(boolean, ViewAction)  
146 - */  
147 - protected final void ifViewAttached(ViewAction<V> action) {  
148 - ifViewAttached(false, action);  
149 - }  
150 -  
151 - /**  
152 - * {@inheritDoc}  
153 - */  
154 - public void detachView() {  
155 - detachView(true);  
156 - if (viewRef != null) {  
157 - viewRef.clear();  
158 - viewRef = null;  
159 - }  
160 - }  
161 -  
162 - /**  
163 - * {@inheritDoc}  
164 - */  
165 - public void destroy() {  
166 -// detachView(false);  
167 - presenterDestroyed = true;  
168 - }  
169 -}  
core/base/src/main/java/com/hannesdorfmann/mosby3/mvp/MvpDialogFragment.java deleted 100644 → 0
1 -package com.hannesdorfmann.mosby3.mvp;  
2 -  
3 -import android.app.Activity;  
4 -import android.app.Dialog;  
5 -import android.content.Context;  
6 -import android.os.Bundle;  
7 -import android.view.View;  
8 -  
9 -import androidx.annotation.NonNull;  
10 -import androidx.annotation.Nullable;  
11 -import androidx.fragment.app.DialogFragment;  
12 -  
13 -import com.hannesdorfmann.mosby3.mvp.delegate.FragmentMvpDelegate;  
14 -import com.hannesdorfmann.mosby3.mvp.delegate.FragmentMvpDelegateImpl;  
15 -import com.hannesdorfmann.mosby3.mvp.delegate.MvpDelegateCallback;  
16 -  
17 -/**  
18 - * A DialogFragment that uses an {@link MvpPresenter} to implement a Model-View-Presenter  
19 - * architecture  
20 - *  
21 - * @author Hannes Dorfmann  
22 - * @author Michał Seroczyński  
23 - * @since 3.1.1  
24 - */  
25 -public abstract class MvpDialogFragment<V extends MvpView, P extends MvpPresenter<V>> extends DialogFragment  
26 - implements MvpDelegateCallback<V, P>, MvpView {  
27 -  
28 - protected FragmentMvpDelegate<V, P> mvpDelegate;  
29 -  
30 - /**  
31 - * The presenter for this view. Will be instantiated with {@link #createPresenter()}  
32 - */  
33 - protected P presenter;  
34 -  
35 - /**  
36 - * Creates a new presenter instance, if needed. Will reuse the previous presenter instance if  
37 - * {@link #setRetainInstance(boolean)} is set to true. This method will be called from  
38 - * {@link #onViewCreated(View, Bundle)}  
39 - */  
40 - public abstract P createPresenter();  
41 -  
42 - /**  
43 - * * Get the mvp delegate. This is internally used for creating presenter, attaching and  
44 - * detaching view from presenter.  
45 - *  
46 - * <p>  
47 - * <b>Please note that only one instance of mvp delegate should be used per fragment  
48 - * instance</b>.  
49 - * </p>  
50 - *  
51 - * <p>  
52 - * Only override this method if you really know what you are doing.  
53 - * </p>  
54 - *  
55 - * @return {@link FragmentMvpDelegateImpl}  
56 - */  
57 - @NonNull  
58 - protected FragmentMvpDelegate<V, P> getMvpDelegate() {  
59 - if (mvpDelegate == null) {  
60 - mvpDelegate = new FragmentMvpDelegateImpl<>(this, this, true, true);  
61 - }  
62 -  
63 - return mvpDelegate;  
64 - }  
65 -  
66 - @NonNull @Override public P getPresenter() {  
67 - return presenter;  
68 - }  
69 -  
70 - @Override public void setPresenter(@NonNull P presenter) {  
71 - this.presenter = presenter;  
72 - }  
73 -  
74 - @NonNull @Override public V getMvpView() {  
75 - return (V) this;  
76 - }  
77 -  
78 - @Override  
79 - public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {  
80 - super.onViewCreated(view, savedInstanceState);  
81 - getMvpDelegate().onViewCreated(view, savedInstanceState);  
82 - }  
83 -  
84 - @Override public void onDestroyView() {  
85 - Dialog dialog = getDialog();  
86 - // Handles https://code.google.com/p/android/issues/detail?id=17423  
87 - if (dialog != null && getRetainInstance()) {  
88 - dialog.setDismissMessage(null);  
89 - }  
90 -  
91 - super.onDestroyView();  
92 - getMvpDelegate().onDestroyView();  
93 - }  
94 -  
95 - @Override public void onCreate(Bundle savedInstanceState) {  
96 - super.onCreate(savedInstanceState);  
97 - getMvpDelegate().onCreate(savedInstanceState);  
98 - }  
99 -  
100 - @Override public void onDestroy() {  
101 - super.onDestroy();  
102 - getMvpDelegate().onDestroy();  
103 - }  
104 -  
105 - @Override public void onPause() {  
106 - super.onPause();  
107 - getMvpDelegate().onPause();  
108 - }  
109 -  
110 - @Override public void onResume() {  
111 - super.onResume();  
112 - getMvpDelegate().onResume();  
113 - }  
114 -  
115 - @Override public void onStart() {  
116 - super.onStart();  
117 - getMvpDelegate().onStart();  
118 - }  
119 -  
120 - @Override public void onStop() {  
121 - super.onStop();  
122 - getMvpDelegate().onStop();  
123 - }  
124 -  
125 - @Override public void onActivityCreated(@Nullable Bundle savedInstanceState) {  
126 - super.onActivityCreated(savedInstanceState);  
127 - getMvpDelegate().onActivityCreated(savedInstanceState);  
128 - }  
129 -  
130 - @Override public void onAttach(Activity activity) {  
131 - super.onAttach(activity);  
132 - getMvpDelegate().onAttach(activity);  
133 - }  
134 -  
135 - @Override public void onAttach(Context context) {  
136 - super.onAttach(context);  
137 - getMvpDelegate().onAttach(context);  
138 - }  
139 -  
140 - @Override public void onDetach() {  
141 - super.onDetach();  
142 - getMvpDelegate().onDetach();  
143 - }  
144 -  
145 - @Override public void onSaveInstanceState(Bundle outState) {  
146 - super.onSaveInstanceState(outState);  
147 - getMvpDelegate().onSaveInstanceState(outState);  
148 - }  
149 -  
150 -}  
151 \ No newline at end of file 0 \ No newline at end of file
core/base/src/main/java/com/hannesdorfmann/mosby3/mvp/MvpFragment.java deleted 100644 → 0
1 -/*  
2 - * Copyright 2015 Hannes Dorfmann.  
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.hannesdorfmann.mosby3.mvp;  
18 -  
19 -import android.app.Activity;  
20 -import android.content.Context;  
21 -import android.os.Bundle;  
22 -import android.view.View;  
23 -  
24 -import androidx.annotation.NonNull;  
25 -import androidx.annotation.Nullable;  
26 -import androidx.fragment.app.Fragment;  
27 -  
28 -import com.hannesdorfmann.mosby3.mvp.delegate.FragmentMvpDelegate;  
29 -import com.hannesdorfmann.mosby3.mvp.delegate.FragmentMvpDelegateImpl;  
30 -import com.hannesdorfmann.mosby3.mvp.delegate.MvpDelegateCallback;  
31 -  
32 -/**  
33 - * A Fragment that uses a {@link MvpPresenter} to implement a Model-View-Presenter architecture.  
34 - *  
35 - * @author Hannes Dorfmann  
36 - * @since 1.0.0  
37 - */  
38 -public abstract class MvpFragment<V extends MvpView, P extends MvpPresenter<V>> extends Fragment  
39 - implements MvpDelegateCallback<V, P>, MvpView {  
40 -  
41 - protected FragmentMvpDelegate<V, P> mvpDelegate;  
42 -  
43 - /**  
44 - * The presenter for this view. Will be instantiated with {@link #createPresenter()}  
45 - */  
46 - protected P presenter;  
47 -  
48 - /**  
49 - * Creates a new presenter instance, if needed. Will reuse the previous presenter instance if  
50 - * {@link #setRetainInstance(boolean)} is set to true. This method will be called from  
51 - * {@link #onViewCreated(View, Bundle)}  
52 - */  
53 - public abstract P createPresenter();  
54 -  
55 - /**  
56 - * Gets the mvp delegate. This is internally used for creating presenter, attaching and  
57 - * detaching view from presenter.  
58 - *  
59 - * <p>  
60 - * <b>Please note that only one instance of mvp delegate should be used per fragment instance</b>.  
61 - * </p>  
62 - *  
63 - * <p>  
64 - * Only override this method if you really know what you are doing.  
65 - * </p>  
66 - *  
67 - * @return {@link FragmentMvpDelegateImpl}  
68 - */  
69 - @NonNull  
70 - protected FragmentMvpDelegate<V, P> getMvpDelegate() {  
71 - if (mvpDelegate == null) {  
72 - mvpDelegate = new FragmentMvpDelegateImpl<>(this, this, true, true);  
73 - }  
74 -  
75 - return mvpDelegate;  
76 - }  
77 -  
78 - @NonNull @Override public P getPresenter() {  
79 - return presenter;  
80 - }  
81 -  
82 - @Override public void setPresenter(@NonNull P presenter) {  
83 - this.presenter = presenter;  
84 - }  
85 -  
86 - @NonNull @Override public V getMvpView() {  
87 - return (V) this;  
88 - }  
89 -  
90 - @Override public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {  
91 - super.onViewCreated(view, savedInstanceState);  
92 - getMvpDelegate().onViewCreated(view, savedInstanceState);  
93 - }  
94 -  
95 - @Override public void onDestroyView() {  
96 - super.onDestroyView();  
97 - getMvpDelegate().onDestroyView();  
98 - }  
99 -  
100 - @Override public void onCreate(Bundle savedInstanceState) {  
101 - super.onCreate(savedInstanceState);  
102 - getMvpDelegate().onCreate(savedInstanceState);  
103 - }  
104 -  
105 - @Override public void onDestroy() {  
106 - super.onDestroy();  
107 - getMvpDelegate().onDestroy();  
108 - }  
109 -  
110 - @Override public void onPause() {  
111 - super.onPause();  
112 - getMvpDelegate().onPause();  
113 - }  
114 -  
115 - @Override public void onResume() {  
116 - super.onResume();  
117 - getMvpDelegate().onResume();  
118 - }  
119 -  
120 - @Override public void onStart() {  
121 - super.onStart();  
122 - getMvpDelegate().onStart();  
123 - }  
124 -  
125 - @Override public void onStop() {  
126 - super.onStop();  
127 - getMvpDelegate().onStop();  
128 - }  
129 -  
130 - @Override public void onActivityCreated(@Nullable Bundle savedInstanceState) {  
131 - super.onActivityCreated(savedInstanceState);  
132 - getMvpDelegate().onActivityCreated(savedInstanceState);  
133 - }  
134 -  
135 - @Deprecated @Override public void onAttach(Activity activity) {  
136 - super.onAttach(activity);  
137 - getMvpDelegate().onAttach(activity);  
138 - }  
139 -  
140 - @Override public void onAttach(Context context) {  
141 - super.onAttach(context);  
142 - getMvpDelegate().onAttach(context);  
143 - }  
144 -  
145 - @Override public void onDetach() {  
146 - super.onDetach();  
147 - getMvpDelegate().onDetach();  
148 - }  
149 -  
150 - @Override public void onSaveInstanceState(Bundle outState) {  
151 - super.onSaveInstanceState(outState);  
152 - getMvpDelegate().onSaveInstanceState(outState);  
153 - }  
154 -}  
155 -  
core/base/src/main/java/com/hannesdorfmann/mosby3/mvp/MvpPresenter.java deleted 100644 → 0
1 -/*  
2 - * Copyright 2015 Hannes Dorfmann.  
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.hannesdorfmann.mosby3.mvp;  
18 -  
19 -  
20 -import androidx.annotation.NonNull;  
21 -import androidx.annotation.UiThread;  
22 -  
23 -/**  
24 - * The base interface for each mvp presenter.  
25 - *  
26 - * <p>  
27 - * Mosby assumes that all interaction (i.e. updating the View) between Presenter and View is  
28 - * executed on Android's main UI thread.  
29 - * </p>  
30 - *  
31 - * @author Hannes Dorfmann  
32 - * @since 1.0.0  
33 - */  
34 -public interface MvpPresenter<V extends MvpView> {  
35 -  
36 - /**  
37 - * Set or attach the view to this presenter  
38 - */  
39 - @UiThread  
40 - void attachView(@NonNull V view);  
41 -  
42 - /**  
43 - * Will be called if the view has been destroyed. Typically this method will be invoked from  
44 - * <code>Activity.detachView()</code> or <code>Fragment.onDestroyView()</code>  
45 - *  
46 - * @deprecated This method has been split into 2 methods: {@link #detachView()} and {@link #destroy()}  
47 - */  
48 - @UiThread  
49 - @Deprecated  
50 - void detachView(boolean retainInstance);  
51 -  
52 - /**  
53 - * Will be called if the view has been detached from the Presenter.  
54 - * Usually this happens on screen orientation changes or view (like fragment) has been put on the backstack.  
55 - */  
56 - @UiThread  
57 - void detachView();  
58 -  
59 - /**  
60 - * Will be called if the presenter is no longer needed because the View has been destroyed permanently.  
61 - * This is where you do clean up stuff.  
62 - */  
63 - @UiThread  
64 - void destroy();  
65 -}  
core/base/src/main/java/com/hannesdorfmann/mosby3/mvp/MvpView.java deleted 100644 → 0
1 -/*  
2 - * Copyright 2015 Hannes Dorfmann.  
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.hannesdorfmann.mosby3.mvp;  
18 -  
19 -/**  
20 - * The root view interface for every mvp view  
21 - *  
22 - * @author Hannes Dorfmann  
23 - * @since 1.0.0  
24 - */  
25 -public interface MvpView {  
26 -}  
core/base/src/main/java/com/hannesdorfmann/mosby3/mvp/delegate/ActivityMvpDelegate.java deleted 100644 → 0
1 -/*  
2 - * Copyright 2015 Hannes Dorfmann.  
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.hannesdorfmann.mosby3.mvp.delegate;  
18 -  
19 -import android.app.Activity;  
20 -import android.os.Bundle;  
21 -import com.hannesdorfmann.mosby3.mvp.MvpPresenter;  
22 -import com.hannesdorfmann.mosby3.mvp.MvpView;  
23 -  
24 -/**  
25 - * A delegate for Activities to attach them to Mosby mvp.  
26 - *  
27 - * <p>  
28 - * The following methods must be invoked from the corresponding Activities lifecycle methods:  
29 - * <ul>  
30 - * <li>{@link #onCreate(Bundle)}</li>  
31 - * <li>{@link #onDestroy()}</li>  
32 - * <li>{@link #onPause()} </li>  
33 - * <li>{@link #onResume()} </li>  
34 - * <li>{@link #onStart()} </li>  
35 - * <li>{@link #onStop()} </li>  
36 - * <li>{@link #onRestart()} </li>  
37 - * <li>{@link #onContentChanged()} </li>  
38 - * <li>{@link #onSaveInstanceState(Bundle)} </li>  
39 - * <li>{@link #onPostCreate(Bundle)} </li>  
40 - * <li></li>  
41 - * </ul>  
42 - * </p>  
43 - *  
44 - * @param <V> The type of {@link MvpView}  
45 - * @param <P> The type of {@link MvpPresenter}  
46 - * @author Hannes Dorfmann  
47 - * @since 1.1.0  
48 - */  
49 -public interface ActivityMvpDelegate<V extends MvpView, P extends MvpPresenter<V>> {  
50 -  
51 - /**  
52 - * This method must be called from {@link Activity#onCreate(Bundle)}.  
53 - * This method internally creates the presenter and attaches the view to it.  
54 - */  
55 - void onCreate(Bundle bundle);  
56 -  
57 - /**  
58 - * This method must be called from {@link Activity#onDestroy()}}.  
59 - * This method internally detaches the view from presenter  
60 - */  
61 - void onDestroy();  
62 -  
63 - /**  
64 - * This method must be called from {@link Activity#onPause()}  
65 - */  
66 - void onPause();  
67 -  
68 - /**  
69 - * This method must be called from {@link Activity#onResume()}  
70 - */  
71 - void onResume();  
72 -  
73 - /**  
74 - * This method must be called from {@link Activity#onStart()}  
75 - */  
76 - void onStart();  
77 -  
78 - /**  
79 - * This method must be called from {@link Activity#onStop()}  
80 - */  
81 - void onStop();  
82 -  
83 - /**  
84 - * This method must be called from {@link Activity#onRestart()}  
85 - */  
86 - void onRestart();  
87 -  
88 - /**  
89 - * This method must be called from {@link Activity#onContentChanged()}  
90 - */  
91 - void onContentChanged();  
92 -  
93 - /**  
94 - * This method must be called from {@link Activity#onSaveInstanceState(Bundle)}  
95 - */  
96 - void onSaveInstanceState(Bundle outState);  
97 -  
98 - /**  
99 - * This method must be called from {@link Activity#onPostCreate(Bundle)}  
100 - */  
101 - void onPostCreate(Bundle savedInstanceState);  
102 -  
103 -}  
core/base/src/main/java/com/hannesdorfmann/mosby3/mvp/delegate/ActivityMvpDelegateImpl.java deleted 100644 → 0
1 -/*  
2 - * Copyright 2015 Hannes Dorfmann.  
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.hannesdorfmann.mosby3.mvp.delegate;  
18 -  
19 -import android.app.Activity;  
20 -import android.os.Bundle;  
21 -import android.util.Log;  
22 -  
23 -import androidx.annotation.NonNull;  
24 -  
25 -import com.hannesdorfmann.mosby3.PresenterManager;  
26 -import com.hannesdorfmann.mosby3.mvp.MvpPresenter;  
27 -import com.hannesdorfmann.mosby3.mvp.MvpView;  
28 -import java.util.UUID;  
29 -  
30 -/**  
31 - * The concrete implementation of {@link}  
32 - *  
33 - * @param <V> The type of {@link MvpView}  
34 - * @param <P> The type of {@link MvpPresenter}  
35 - * @author Hannes Dorfmann  
36 - * @see ActivityMvpDelegate  
37 - * @since 1.1.0  
38 - */  
39 -public class ActivityMvpDelegateImpl<V extends MvpView, P extends MvpPresenter<V>>  
40 - implements ActivityMvpDelegate {  
41 -  
42 - protected static final String KEY_MOSBY_VIEW_ID = "com.hannesdorfmann.mosby3.activity.mvp.id";  
43 -  
44 - public static boolean DEBUG = false;  
45 - private static final String DEBUG_TAG = "ActivityMvpDelegateImpl";  
46 -  
47 - private MvpDelegateCallback<V, P> delegateCallback;  
48 - protected boolean keepPresenterInstance;  
49 - protected Activity activity;  
50 - protected String mosbyViewId = null;  
51 -  
52 - /**  
53 - * @param activity The Activity  
54 - * @param delegateCallback The callback  
55 - * @param keepPresenterInstance true, if the presenter instance should be kept across screen  
56 - * orientation changes. Otherwise false.  
57 - */  
58 - public ActivityMvpDelegateImpl(@NonNull Activity activity,  
59 - @NonNull MvpDelegateCallback<V, P> delegateCallback, boolean keepPresenterInstance) {  
60 -  
61 - if (activity == null) {  
62 - throw new NullPointerException("Activity is null!");  
63 - }  
64 -  
65 - if (delegateCallback == null) {  
66 - throw new NullPointerException("MvpDelegateCallback is null!");  
67 - }  
68 - this.delegateCallback = delegateCallback;  
69 - this.activity = activity;  
70 - this.keepPresenterInstance = keepPresenterInstance;  
71 - }  
72 -  
73 - /**  
74 - * Determines whether or not a Presenter Instance should be kept  
75 - *  
76 - * @param keepPresenterInstance true, if the delegate has enabled keep  
77 - */  
78 - static boolean retainPresenterInstance(boolean keepPresenterInstance, Activity activity) {  
79 - return keepPresenterInstance && (activity.isChangingConfigurations()  
80 - || !activity.isFinishing());  
81 - }  
82 -  
83 - /**  
84 - * Generates the unique (mosby internal) view id and calls {@link  
85 - * MvpDelegateCallback#createPresenter()}  
86 - * to create a new presenter instance  
87 - *  
88 - * @return The new created presenter instance  
89 - */  
90 - private P createViewIdAndCreatePresenter() {  
91 -  
92 - P presenter = delegateCallback.createPresenter();  
93 - if (presenter == null) {  
94 - throw new NullPointerException(  
95 - "Presenter returned from createPresenter() is null. Activity is " + activity);  
96 - }  
97 - if (keepPresenterInstance) {  
98 - mosbyViewId = UUID.randomUUID().toString();  
99 - PresenterManager.putPresenter(activity, mosbyViewId, presenter);  
100 - }  
101 - return presenter;  
102 - }  
103 -  
104 - @Override public void onCreate(Bundle bundle) {  
105 -  
106 - P presenter = null;  
107 -  
108 - if (bundle != null && keepPresenterInstance) {  
109 -  
110 - mosbyViewId = bundle.getString(KEY_MOSBY_VIEW_ID);  
111 -  
112 - if (DEBUG) {  
113 - Log.d(DEBUG_TAG,  
114 - "MosbyView ID = " + mosbyViewId + " for MvpView: " + delegateCallback.getMvpView());  
115 - }  
116 -  
117 - if (mosbyViewId != null  
118 - && (presenter = PresenterManager.getPresenter(activity, mosbyViewId)) != null) {  
119 - //  
120 - // Presenter restored from cache  
121 - //  
122 - if (DEBUG) {  
123 - Log.d(DEBUG_TAG,  
124 - "Reused presenter " + presenter + " for view " + delegateCallback.getMvpView());  
125 - }  
126 - } else {  
127 - //  
128 - // No presenter found in cache, most likely caused by process death  
129 - //  
130 - presenter = createViewIdAndCreatePresenter();  
131 - if (DEBUG) {  
132 - Log.d(DEBUG_TAG, "No presenter found although view Id was here: "  
133 - + mosbyViewId  
134 - + ". Most likely this was caused by a process death. New Presenter created"  
135 - + presenter  
136 - + " for view "  
137 - + getMvpView());  
138 - }  
139 - }  
140 - } else {  
141 - //  
142 - // Activity starting first time, so create a new presenter  
143 - //  
144 - presenter = createViewIdAndCreatePresenter();  
145 - if (DEBUG) {  
146 - Log.d(DEBUG_TAG, "New presenter " + presenter + " for view " + getMvpView());  
147 - }  
148 - }  
149 -  
150 - if (presenter == null) {  
151 - throw new IllegalStateException(  
152 - "Oops, Presenter is null. This seems to be a Mosby internal bug. Please report this issue here: https://github.com/sockeqwe/mosby/issues");  
153 - }  
154 -  
155 - delegateCallback.setPresenter(presenter);  
156 - getPresenter().attachView(getMvpView());  
157 -  
158 - if (DEBUG) {  
159 - Log.d(DEBUG_TAG, "View" + getMvpView() + " attached to Presenter " + presenter);  
160 - }  
161 - }  
162 -  
163 - private P getPresenter() {  
164 - P presenter = delegateCallback.getPresenter();  
165 - if (presenter == null) {  
166 - throw new NullPointerException("Presenter returned from getPresenter() is null");  
167 - }  
168 - return presenter;  
169 - }  
170 -  
171 - private V getMvpView() {  
172 - V view = delegateCallback.getMvpView();  
173 - if (view == null) {  
174 - throw new NullPointerException("View returned from getMvpView() is null");  
175 - }  
176 - return view;  
177 - }  
178 -  
179 - @Override public void onDestroy() {  
180 - boolean retainPresenterInstance = retainPresenterInstance(keepPresenterInstance, activity);  
181 - getPresenter().detachView();  
182 - if (!retainPresenterInstance){  
183 - getPresenter().destroy();  
184 - }  
185 - if (!retainPresenterInstance && mosbyViewId != null) {  
186 - PresenterManager.remove(activity, mosbyViewId);  
187 - }  
188 -  
189 - if (DEBUG) {  
190 - if (retainPresenterInstance) {  
191 - Log.d(DEBUG_TAG, "View"  
192 - + getMvpView()  
193 - + " destroyed temporarily. View detached from presenter "  
194 - + getPresenter());  
195 - } else {  
196 - Log.d(DEBUG_TAG, "View"  
197 - + getMvpView()  
198 - + " destroyed permanently. View detached permanently from presenter "  
199 - + getPresenter());  
200 - }  
201 - }  
202 - }  
203 -  
204 - @Override public void onPause() {  
205 -  
206 - }  
207 -  
208 - @Override public void onResume() {  
209 -  
210 - }  
211 -  
212 - @Override public void onStart() {  
213 -  
214 - }  
215 -  
216 - @Override public void onStop() {  
217 -  
218 - }  
219 -  
220 - @Override public void onRestart() {  
221 -  
222 - }  
223 -  
224 - @Override public void onContentChanged() {  
225 -  
226 - }  
227 -  
228 - @Override public void onSaveInstanceState(Bundle outState) {  
229 - if (keepPresenterInstance && outState != null) {  
230 - outState.putString(KEY_MOSBY_VIEW_ID, mosbyViewId);  
231 - if (DEBUG) {  
232 - Log.d(DEBUG_TAG,  
233 - "Saving MosbyViewId into Bundle. ViewId: " + mosbyViewId + " for view " + getMvpView());  
234 - }  
235 - }  
236 - }  
237 -  
238 - @Override public void onPostCreate(Bundle savedInstanceState) {  
239 - }  
240 -}  
core/base/src/main/java/com/hannesdorfmann/mosby3/mvp/delegate/BackstackAccessor.java deleted 100644 → 0
1 -/*  
2 - * Copyright 2016 Hannes Dorfmann.  
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 -  
18 -package com.hannesdorfmann.mosby3.mvp.delegate;  
19 -  
20 -import androidx.fragment.app.Fragment;  
21 -  
22 -import java.io.PrintWriter;  
23 -import java.io.StringWriter;  
24 -  
25 -/**  
26 - * With this utility class one can access the fragment backstack  
27 - *  
28 - * @author Hannes Dorfmann  
29 - */  
30 -public class BackstackAccessor {  
31 -  
32 - private BackstackAccessor() {  
33 - throw new IllegalStateException("Not instantiatable");  
34 - }  
35 -  
36 - /**  
37 - * Checks whether or not a given fragment is on the backstack of the fragment manager (could also  
38 - * be on top of the backstack and hence visible)  
39 - *  
40 - * @param fragment The fragment you want to check if its on the back stack  
41 - * @return true, if the given Fragment is on the back stack, otherwise false (not on the back  
42 - * stack)  
43 - */  
44 - //todo  
45 -// public static boolean isFragmentOnBackStack(Fragment fragment) {  
46 -// try {  
47 -//// return fragment.isInBackStack();  
48 -// return true;  
49 -// } catch (IllegalAccessError e) {  
50 -// return isInBackStackAndroidX(fragment);  
51 -// }  
52 -// }  
53 -  
54 - /**  
55 - * As of version 1.0 of AndroidX - fragment.isInBackStack() is package private which leads to  
56 - * an IllegalAccessError being thrown when trying to use it.  
57 - * This method is a temporary workaround until the issue is resolved in AndroidX.  
58 - */  
59 - public static boolean isInBackStackAndroidX(final Fragment fragment) {  
60 - final StringWriter writer = new StringWriter();  
61 - fragment.dump("", null, new PrintWriter(writer), null);  
62 - final String dump = writer.toString();  
63 - return !dump.contains("mBackStackNesting=0");  
64 - }  
65 -/*  
66 - public static boolean isFragmentOnBackStack(Fragment fragment) {  
67 -  
68 - FragmentManager fragmentManager = fragment.getFragmentManager();  
69 - int backStackSize = fragmentManager.getBackStackEntryCount();  
70 - for (int i = 0; i < backStackSize; i++) {  
71 - BackStackRecord stackEntry = (BackStackRecord) fragmentManager.getBackStackEntryAt(i);  
72 - int opsCount = stackEntry.mOps == null ? 0 : stackEntry.mOps.size();  
73 - if (opsCount > 0) {  
74 - BackStackRecord.Op op = stackEntry.mOps.get(opsCount-1);  
75 - if (op.fragment == fragment) {  
76 - return true;  
77 - }  
78 - }  
79 - }  
80 -  
81 - return false;  
82 - }  
83 -*/  
84 -  
85 -/*  
86 - private static boolean findNext(@NonNull Fragment toFind, @Nullable BackStackRecord.Op next) {  
87 - if (next == null) {  
88 - return false;  
89 - }  
90 -  
91 - if (toFind == next.fragment) {  
92 - return true;  
93 - } else {  
94 - return findNext(toFind, next.next);  
95 - }  
96 - }  
97 -  
98 - private static boolean findPrevious(@NonNull Fragment toFind,  
99 - @Nullable BackStackRecord.Op previous) {  
100 - if (previous == null) {  
101 - return false;  
102 - }  
103 -  
104 - if (toFind == previous.fragment) {  
105 - return true;  
106 - } else {  
107 - return findPrevious(toFind, previous.prev);  
108 - }  
109 - }  
110 - */  
111 -}  
core/base/src/main/java/com/hannesdorfmann/mosby3/mvp/delegate/FragmentMvpDelegate.java deleted 100644 → 0
1 -/*  
2 - * Copyright 2015 Hannes Dorfmann.  
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.hannesdorfmann.mosby3.mvp.delegate;  
18 -  
19 -import android.app.Activity;  
20 -import android.content.Context;  
21 -import android.os.Bundle;  
22 -import android.view.View;  
23 -  
24 -import androidx.annotation.Nullable;  
25 -  
26 -import com.hannesdorfmann.mosby3.mvp.MvpPresenter;  
27 -import com.hannesdorfmann.mosby3.mvp.MvpView;  
28 -  
29 -/**  
30 - * A delegate for Fragments to attach them to mosby mvp.  
31 - * <p>  
32 - * The following methods must be invoked from the corresponding Fragments lifecycle methods:  
33 - *  
34 - * <ul>  
35 - * <li>{@link #onCreate(Bundle)}</li>  
36 - * <li>{@link #onDestroy()}</li>  
37 - * <li>{@link #onPause()} </li>  
38 - * <li>{@link #onResume()} </li>  
39 - * <li>{@link #onStart()} </li>  
40 - * <li>{@link #onStop()} </li>  
41 - * <li>{@link #onViewCreated(View, Bundle)} </li>  
42 - * <li>{@link #onActivityCreated(Bundle)} </li>  
43 - * <li>{@link #onSaveInstanceState(Bundle)} </li>  
44 - * <li>{@link #onAttach(Activity)} </li>  
45 - * <li>{@link #onAttach(Context)} </li>  
46 - * <li>{@link #onDetach()}</li>  
47 - * <li></li>  
48 - * </ul>  
49 - * </p>  
50 - *  
51 - * @param <V> The type of {@link MvpView}  
52 - * @param <P> The type of {@link MvpPresenter}  
53 - * @author Hannes Dorfmann  
54 - * @since 1.1.0  
55 - */  
56 -public interface FragmentMvpDelegate<V extends MvpView, P extends MvpPresenter<V>> {  
57 -  
58 - /**  
59 - * Must be called from {@link Fragment#onCreate(Bundle)}  
60 - *  
61 - * @param saved The bundle  
62 - */  
63 - void onCreate(Bundle saved);  
64 -  
65 - /**  
66 - * Must be called from {@link Fragment#onDestroy()}  
67 - */  
68 - void onDestroy();  
69 -  
70 - /**  
71 - * Must be called from {@link Fragment#onViewCreated(View, Bundle)}  
72 - *  
73 - * @param view The inflated view  
74 - * @param savedInstanceState the bundle with the viewstate  
75 - */  
76 - void onViewCreated(View view, @Nullable Bundle savedInstanceState);  
77 -  
78 - /**  
79 - * Must be called from {@link Fragment#onDestroyView()}  
80 - */  
81 - void onDestroyView();  
82 -  
83 - /**  
84 - * Must be called from {@link Fragment#onPause()}  
85 - */  
86 - void onPause();  
87 -  
88 - /**  
89 - * Must be called from {@link Fragment#onResume()}  
90 - */  
91 - void onResume();  
92 -  
93 - /**  
94 - * Must be called from {@link Fragment#onStart()}  
95 - */  
96 - void onStart();  
97 -  
98 - /**  
99 - * Must be called from {@link Fragment#onStop()}  
100 - */  
101 - void onStop();  
102 -  
103 - /**  
104 - * Must be called from {@link Fragment#onActivityCreated(Bundle)}  
105 - *  
106 - * @param savedInstanceState The saved bundle  
107 - */  
108 - void onActivityCreated(Bundle savedInstanceState);  
109 -  
110 - /**  
111 - * Must be called from {@link Fragment#onAttach(Activity)}  
112 - *  
113 - * @param activity The activity the fragment is attached to  
114 - */  
115 - @Deprecated  
116 - void onAttach(Activity activity);  
117 -  
118 - /**  
119 - * Must be called from {@link Fragment#onAttach(Context)}  
120 - *  
121 - * @param context The context the fragment is attached to  
122 - */  
123 - void onAttach(Context context);  
124 -  
125 - /**  
126 - * Must be called from {@link Fragment#onDetach()}  
127 - */  
128 - void onDetach();  
129 -  
130 - /**  
131 - * Must be called from {@link Fragment#onSaveInstanceState(Bundle)}  
132 - */  
133 - void onSaveInstanceState(Bundle outState);  
134 -}  
core/base/src/main/java/com/hannesdorfmann/mosby3/mvp/delegate/FragmentMvpDelegateImpl.java deleted 100644 → 0
1 -/*  
2 - * Copyright 2015 Hannes Dorfmann.  
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.hannesdorfmann.mosby3.mvp.delegate;  
18 -  
19 -import android.app.Activity;  
20 -import android.content.Context;  
21 -import android.os.Bundle;  
22 -import android.util.Log;  
23 -import android.view.View;  
24 -  
25 -import androidx.annotation.NonNull;  
26 -import androidx.annotation.Nullable;  
27 -import androidx.fragment.app.Fragment;  
28 -  
29 -import com.hannesdorfmann.mosby3.PresenterManager;  
30 -import com.hannesdorfmann.mosby3.mvp.MvpPresenter;  
31 -import com.hannesdorfmann.mosby3.mvp.MvpView;  
32 -  
33 -import java.util.UUID;  
34 -  
35 -/**  
36 - * The default implementation of {@link FragmentMvpDelegate}  
37 - * Presenter is available (has view that is attached) in {@link #onViewCreated(View, Bundle)} (after  
38 - * super.onViewCreated() is called). View will be detached in {@link #onDestroyView()} from presenter,  
39 - * and eventually presenter will be destroyed in {@link #onDestroy()}.  
40 - *  
41 - * @param <V> The type of {@link MvpView}  
42 - * @param <P> The type of {@link MvpPresenter}  
43 - * @author Hannes Dorfmann  
44 - * @see FragmentMvpDelegate  
45 - * @since 1.1.0  
46 - */  
47 -public class FragmentMvpDelegateImpl<V extends MvpView, P extends MvpPresenter<V>>  
48 - implements FragmentMvpDelegate<V, P> {  
49 -  
50 - protected static final String KEY_MOSBY_VIEW_ID = "com.hannesdorfmann.mosby3.fragment.mvp.id";  
51 -  
52 - public static boolean DEBUG = false;  
53 - private static final String DEBUG_TAG = "FragmentMvpVSDelegate";  
54 -  
55 - private MvpDelegateCallback<V, P> delegateCallback;  
56 - protected Fragment fragment;  
57 - protected final boolean keepPresenterInstanceDuringScreenOrientationChanges;  
58 - protected final boolean keepPresenterOnBackstack;  
59 - private boolean onViewCreatedCalled = false;  
60 - protected String mosbyViewId;  
61 -  
62 - /**  
63 - * @param fragment The Fragment  
64 - * @param delegateCallback the DelegateCallback  
65 - * @param keepPresenterDuringScreenOrientationChange true, if the presenter should be kept during  
66 - * screen orientation  
67 - * changes. Otherwise, false  
68 - * @param keepPresenterOnBackstack true, if the presenter should be kept when the fragment is  
69 - * destroyed because it is put on the backstack, Otherwise false  
70 - */  
71 - public FragmentMvpDelegateImpl(@NonNull Fragment fragment,  
72 - @NonNull MvpDelegateCallback<V, P> delegateCallback,  
73 - boolean keepPresenterDuringScreenOrientationChange, boolean keepPresenterOnBackstack) {  
74 - if (delegateCallback == null) {  
75 - throw new NullPointerException("MvpDelegateCallback is null!");  
76 - }  
77 -  
78 - if (fragment == null) {  
79 - throw new NullPointerException("Fragment is null!");  
80 - }  
81 -  
82 - if (!keepPresenterDuringScreenOrientationChange && keepPresenterOnBackstack) {  
83 - throw new IllegalArgumentException("It is not possible to keep the presenter on backstack, "  
84 - + "but NOT keep presenter through screen orientation changes. Keep presenter on backstack also "  
85 - + "requires keep presenter through screen orientation changes to be enabled");  
86 - }  
87 -  
88 - this.fragment = fragment;  
89 - this.delegateCallback = delegateCallback;  
90 - this.keepPresenterInstanceDuringScreenOrientationChanges =  
91 - keepPresenterDuringScreenOrientationChange;  
92 - this.keepPresenterOnBackstack = keepPresenterOnBackstack;  
93 - }  
94 -  
95 - /**  
96 - * Generates the unique (mosby internal) view id and calls {@link  
97 - * MvpDelegateCallback#createPresenter()}  
98 - * to create a new presenter instance  
99 - *  
100 - * @return The new created presenter instance  
101 - */  
102 - private P createViewIdAndCreatePresenter() {  
103 -  
104 - P presenter = delegateCallback.createPresenter();  
105 - if (presenter == null) {  
106 - throw new NullPointerException(  
107 - "Presenter returned from createPresenter() is null. Activity is " + getActivity());  
108 - }  
109 - if (keepPresenterInstanceDuringScreenOrientationChanges) {  
110 - mosbyViewId = UUID.randomUUID().toString();  
111 - PresenterManager.putPresenter(getActivity(), mosbyViewId, presenter);  
112 - }  
113 - return presenter;  
114 - }  
115 -  
116 - @Override  
117 - public void onViewCreated(View view, @Nullable Bundle bundle) {  
118 -  
119 - P presenter = getPresenter();  
120 - presenter.attachView(getMvpView());  
121 -  
122 - if (DEBUG) {  
123 - Log.d(DEBUG_TAG, "View" + getMvpView() + " attached to Presenter " + presenter);  
124 - }  
125 -  
126 - onViewCreatedCalled = true;  
127 - }  
128 -  
129 - @NonNull  
130 - private Activity getActivity() {  
131 - Activity activity = fragment.getActivity();  
132 - if (activity == null) {  
133 - throw new NullPointerException(  
134 - "Activity returned by Fragment.getActivity() is null. Fragment is " + fragment);  
135 - }  
136 -  
137 - return activity;  
138 - }  
139 -  
140 - private P getPresenter() {  
141 - P presenter = delegateCallback.getPresenter();  
142 - if (presenter == null) {  
143 - throw new NullPointerException("Presenter returned from getPresenter() is null");  
144 - }  
145 - return presenter;  
146 - }  
147 -  
148 - private V getMvpView() {  
149 - V view = delegateCallback.getMvpView();  
150 - if (view == null) {  
151 - throw new NullPointerException("View returned from getMvpView() is null");  
152 - }  
153 - return view;  
154 - }  
155 -  
156 - static boolean retainPresenterInstance(Activity activity, Fragment fragment,  
157 - boolean keepPresenterInstanceDuringScreenOrientationChanges,  
158 - boolean keepPresenterOnBackstack) {  
159 -  
160 - if (activity.isChangingConfigurations()) {  
161 - return keepPresenterInstanceDuringScreenOrientationChanges;  
162 - }  
163 -  
164 - if (activity.isFinishing()) {  
165 - return false;  
166 - }  
167 -//todo 修改androidx  
168 - if (keepPresenterOnBackstack && BackstackAccessor.isInBackStackAndroidX(fragment)) {  
169 - return true;  
170 - }  
171 -  
172 - return !fragment.isRemoving();  
173 - }  
174 -  
175 - @Override  
176 - public void onDestroyView() {  
177 -  
178 - onViewCreatedCalled = false;  
179 -  
180 - getPresenter().detachView();  
181 -  
182 - if (DEBUG) {  
183 - Log.d(DEBUG_TAG, "detached MvpView from Presenter. MvpView "  
184 - + delegateCallback.getMvpView()  
185 - + " Presenter: "  
186 - + getPresenter());  
187 - }  
188 - }  
189 -  
190 - @Override  
191 - public void onPause() {  
192 -  
193 - }  
194 -  
195 - @Override  
196 - public void onResume() {  
197 -  
198 - }  
199 -  
200 - @Override  
201 - public void onStart() {  
202 -  
203 - if (!onViewCreatedCalled) {  
204 - throw new IllegalStateException("It seems that you are using "  
205 - + delegateCallback.getClass().getCanonicalName()  
206 - + " as headless (UI less) fragment (because onViewCreated() has not been called or maybe delegation misses that part). Having a Presenter without a View (UI) doesn't make sense. Simply use an usual fragment instead of an MvpFragment if you want to use a UI less Fragment");  
207 - }  
208 - }  
209 -  
210 - @Override  
211 - public void onStop() {  
212 -  
213 - }  
214 -  
215 - @Override  
216 - public void onActivityCreated(Bundle savedInstanceState) {  
217 -  
218 - }  
219 -  
220 - @Override  
221 - public void onAttach(Activity activity) {  
222 -  
223 - }  
224 -  
225 - @Override  
226 - public void onAttach(Context context) {  
227 -  
228 - }  
229 -  
230 - @Override  
231 - public void onDetach() {  
232 -  
233 - }  
234 -  
235 - @Override  
236 - public void onSaveInstanceState(Bundle outState) {  
237 - if ((keepPresenterInstanceDuringScreenOrientationChanges || keepPresenterOnBackstack)  
238 - && outState != null) {  
239 - outState.putString(KEY_MOSBY_VIEW_ID, mosbyViewId);  
240 -  
241 - if (DEBUG) {  
242 - Log.d(DEBUG_TAG, "Saving MosbyViewId into Bundle. ViewId: " + mosbyViewId);  
243 - }  
244 - }  
245 - }  
246 -  
247 - @Override  
248 - public void onCreate(Bundle bundle) {  
249 -  
250 - P presenter = null;  
251 -  
252 - if (bundle != null && keepPresenterInstanceDuringScreenOrientationChanges) {  
253 -  
254 - mosbyViewId = bundle.getString(KEY_MOSBY_VIEW_ID);  
255 -  
256 - if (DEBUG) {  
257 - Log.d(DEBUG_TAG,  
258 - "MosbyView ID = " + mosbyViewId + " for MvpView: " + delegateCallback.getMvpView());  
259 - }  
260 -  
261 - if (mosbyViewId != null  
262 - && (presenter = PresenterManager.getPresenter(getActivity(), mosbyViewId)) != null) {  
263 - //  
264 - // Presenter restored from cache  
265 - //  
266 - if (DEBUG) {  
267 - Log.d(DEBUG_TAG,  
268 - "Reused presenter " + presenter + " for view " + delegateCallback.getMvpView());  
269 - }  
270 - } else {  
271 - //  
272 - // No presenter found in cache, most likely caused by process death  
273 - //  
274 - presenter = createViewIdAndCreatePresenter();  
275 - if (DEBUG) {  
276 - Log.d(DEBUG_TAG, "No presenter found although view Id was here: "  
277 - + mosbyViewId  
278 - + ". Most likely this was caused by a process death. New Presenter created"  
279 - + presenter  
280 - + " for view "  
281 - + getMvpView());  
282 - }  
283 - }  
284 - } else {  
285 - //  
286 - // Activity starting first time, so create a new presenter  
287 - //  
288 - presenter = createViewIdAndCreatePresenter();  
289 - if (DEBUG) {  
290 - Log.d(DEBUG_TAG, "New presenter " + presenter + " for view " + getMvpView());  
291 - }  
292 - }  
293 -  
294 - if (presenter == null) {  
295 - throw new IllegalStateException(  
296 - "Oops, Presenter is null. This seems to be a Mosby internal bug. Please report this issue here: https://github.com/sockeqwe/mosby/issues");  
297 - }  
298 -  
299 - delegateCallback.setPresenter(presenter);  
300 - }  
301 -  
302 - @Override  
303 - public void onDestroy() {  
304 -  
305 - Activity activity = getActivity();  
306 - boolean retainPresenterInstance = retainPresenterInstance(activity, fragment,  
307 - keepPresenterInstanceDuringScreenOrientationChanges, keepPresenterOnBackstack);  
308 -  
309 - P presenter = getPresenter();  
310 - if (!retainPresenterInstance) {  
311 - presenter.destroy();  
312 - if (DEBUG) {  
313 - Log.d(DEBUG_TAG, "Presenter destroyed. MvpView "  
314 - + delegateCallback.getMvpView()  
315 - + " Presenter: "  
316 - + presenter);  
317 - }  
318 - }  
319 -  
320 - if (!retainPresenterInstance && mosbyViewId != null) {  
321 - // mosbyViewId is null if keepPresenterInstanceDuringScreenOrientationChanges == false  
322 - PresenterManager.remove(activity, mosbyViewId);  
323 - }  
324 - }  
325 -}  
core/base/src/main/java/com/hannesdorfmann/mosby3/mvp/delegate/MvpDelegateCallback.java deleted 100644 → 0
1 -/*  
2 - * Copyright 2015 Hannes Dorfmann.  
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.hannesdorfmann.mosby3.mvp.delegate;  
18 -  
19 -  
20 -import androidx.annotation.NonNull;  
21 -  
22 -import com.hannesdorfmann.mosby3.mvp.MvpPresenter;  
23 -import com.hannesdorfmann.mosby3.mvp.MvpView;  
24 -  
25 -/**  
26 - * The MvpDelegate callback that will be called from {@link  
27 - * FragmentMvpDelegate} or {@link ViewGroupMvpDelegate}. This interface must be implemented by all  
28 - * Fragment or android.view.View that you want to support Mosby mvp.  
29 - *  
30 - * @param <V> The type of {@link MvpView}  
31 - * @param <P> The type of {@link MvpPresenter}  
32 - * @author Hannes Dorfmann  
33 - * @since 1.1.0  
34 - */  
35 -public interface MvpDelegateCallback<V extends MvpView, P extends MvpPresenter<V>> {  
36 -  
37 - /**  
38 - * Creates the presenter instance  
39 - *  
40 - * @return the created presenter instance  
41 - */  
42 - @NonNull  
43 - P createPresenter();  
44 -  
45 - /**  
46 - * Gets the presenter. If null is returned, then a internally a new presenter instance gets  
47 - * created by calling {@link #createPresenter()}  
48 - *  
49 - * @return the presenter instance. can be null.  
50 - */  
51 - P getPresenter();  
52 -  
53 - /**  
54 - * Sets the presenter instance  
55 - *  
56 - * @param presenter The presenter instance  
57 - */  
58 - void setPresenter(P presenter);  
59 -  
60 - /**  
61 - * Gets the MvpView for the presenter  
62 - *  
63 - * @return The view associated with the presenter  
64 - */  
65 - V getMvpView();  
66 -}  
67 -  
core/base/src/main/java/com/hannesdorfmann/mosby3/mvp/delegate/ViewGroupDelegateCallback.java deleted 100644 → 0
1 -/*  
2 - * Copyright 2015 Hannes Dorfmann.  
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.hannesdorfmann.mosby3.mvp.delegate;  
18 -  
19 -import android.content.Context;  
20 -import android.os.Parcelable;  
21 -import com.hannesdorfmann.mosby3.mvp.MvpPresenter;  
22 -import com.hannesdorfmann.mosby3.mvp.MvpView;  
23 -  
24 -/**  
25 - * An enhanced version of {@link MvpDelegateCallback} that adds support for  
26 - * android.view.View like FrameLayout etc.  
27 - *  
28 - * @author Hannes Dorfmann  
29 - * @since 3.0  
30 - */  
31 -public interface ViewGroupDelegateCallback<V extends MvpView, P extends MvpPresenter<V>>  
32 - extends MvpDelegateCallback<V, P> {  
33 -  
34 - /**  
35 - * This method must call super.onSaveInstanceState() within any view  
36 - */  
37 - Parcelable superOnSaveInstanceState();  
38 -  
39 - /**  
40 - * This method must call super.onRestoreInstanceState(state)  
41 - *  
42 - * @param state The parcelable containing the state  
43 - */  
44 - void superOnRestoreInstanceState(Parcelable state);  
45 -  
46 - /**  
47 - * Get the context  
48 - *  
49 - * @return Get the context  
50 - * @since 3.0  
51 - */  
52 - Context getContext();  
53 -}  
core/base/src/main/java/com/hannesdorfmann/mosby3/mvp/delegate/ViewGroupMvpDelegate.java deleted 100644 → 0
1 -/*  
2 - * Copyright 2015 Hannes Dorfmann.  
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.hannesdorfmann.mosby3.mvp.delegate;  
18 -  
19 -import android.os.Parcelable;  
20 -import android.view.View;  
21 -import android.widget.FrameLayout;  
22 -import com.hannesdorfmann.mosby3.mvp.MvpPresenter;  
23 -import com.hannesdorfmann.mosby3.mvp.MvpView;  
24 -  
25 -/**  
26 - * The mvp delegate used for everything that derives from {@link View} like {@link FrameLayout}  
27 - * etc.  
28 - *  
29 - * <p>  
30 - * The following methods must be called from the corresponding View lifecycle method:  
31 - * <ul>  
32 - * <li>{@link #onAttachedToWindow()}</li>  
33 - * <li>{@link #onDetachedFromWindow()}</li>  
34 - * </ul>  
35 - * </p>  
36 - *  
37 - * @author Hannes Dorfmann  
38 - * @since 1.1.0  
39 - */  
40 -public interface ViewGroupMvpDelegate<V extends MvpView, P extends MvpPresenter<V>> {  
41 -  
42 - /**  
43 - * Must be called from {@link View#onAttachedToWindow()}  
44 - */  
45 - void onAttachedToWindow();  
46 -  
47 - /**  
48 - * Must be called from {@link View#onDetachedFromWindow()}  
49 - */  
50 - void onDetachedFromWindow();  
51 -  
52 - /**  
53 - * Must be called from {@link View#onRestoreInstanceState(Parcelable)}  
54 - *  
55 - * @param state The parcelable state  
56 - */  
57 - void onRestoreInstanceState(Parcelable state);  
58 -  
59 - /**  
60 - * Save the instatnce state  
61 - *  
62 - * @return The state with all the saved data  
63 - */  
64 - Parcelable onSaveInstanceState();  
65 -}  
core/base/src/main/java/com/hannesdorfmann/mosby3/mvp/delegate/ViewGroupMvpDelegateImpl.java deleted 100644 → 0
1 -/*  
2 - * Copyright 2017 Hannes Dorfmann.  
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 -  
18 -package com.hannesdorfmann.mosby3.mvp.delegate;  
19 -  
20 -import android.app.Activity;  
21 -import android.app.Application;  
22 -import android.content.Context;  
23 -import android.os.Bundle;  
24 -import android.os.Parcelable;  
25 -import android.util.Log;  
26 -import android.view.View;  
27 -import android.widget.FrameLayout;  
28 -  
29 -import androidx.annotation.NonNull;  
30 -  
31 -import com.hannesdorfmann.mosby3.MosbySavedState;  
32 -import com.hannesdorfmann.mosby3.PresenterManager;  
33 -import com.hannesdorfmann.mosby3.mvp.MvpPresenter;  
34 -import com.hannesdorfmann.mosby3.mvp.MvpView;  
35 -import java.util.UUID;  
36 -  
37 -/**  
38 - * The mvp delegate used for everything that derives from {@link View} like {@link FrameLayout}  
39 - * etc.  
40 - *  
41 - * <p>  
42 - * The following methods must be called from the corresponding View lifecycle method:  
43 - * <ul>  
44 - * <li>{@link #onAttachedToWindow()}</li>  
45 - * <li>{@link #onDetachedFromWindow()}</li>  
46 - * </ul>  
47 - * </p>  
48 - *  
49 - * @author Hannes Dorfmann  
50 - * @since 1.1.0  
51 - */  
52 -public class ViewGroupMvpDelegateImpl<V extends MvpView, P extends MvpPresenter<V>>  
53 - implements ViewGroupMvpDelegate<V, P>, Application.ActivityLifecycleCallbacks {  
54 -  
55 - // TODO allow custom save state hook in  
56 -  
57 - public static boolean DEBUG = false;  
58 - private static final String DEBUG_TAG = "ViewGroupMvpDelegateImp";  
59 -  
60 - private ViewGroupDelegateCallback<V, P> delegateCallback;  
61 - private String mosbyViewId;  
62 - private final boolean keepPresenterDuringScreenOrientationChange;  
63 - private final Activity activity;  
64 - private final boolean isInEditMode;  
65 -  
66 - private boolean checkedActivityFinishing = false;  
67 - private boolean presenterDetached = false;  
68 - private boolean presenterDestroyed = false;  
69 -  
70 - public ViewGroupMvpDelegateImpl(@NonNull View view,  
71 - @NonNull ViewGroupDelegateCallback<V, P> delegateCallback,  
72 - boolean keepPresenterDuringScreenOrientationChange) {  
73 - if (view == null) {  
74 - throw new NullPointerException("View is null!");  
75 - }  
76 -  
77 - if (delegateCallback == null) {  
78 - throw new NullPointerException("MvpDelegateCallback is null!");  
79 - }  
80 -  
81 - this.delegateCallback = delegateCallback;  
82 - this.keepPresenterDuringScreenOrientationChange = keepPresenterDuringScreenOrientationChange;  
83 -  
84 - isInEditMode = view.isInEditMode();  
85 -  
86 - if (!isInEditMode) {  
87 - this.activity = PresenterManager.getActivity(delegateCallback.getContext());  
88 - this.activity.getApplication().registerActivityLifecycleCallbacks(this);  
89 - } else {  
90 - this.activity = null;  
91 - }  
92 - }  
93 -  
94 - /**  
95 - * Generates the unique (mosby internal) viewState id and calls {@link  
96 - * MvpDelegateCallback#createPresenter()}  
97 - * to create a new presenter instance  
98 - *  
99 - * @return The new created presenter instance  
100 - */  
101 - protected P createViewIdAndCreatePresenter() {  
102 -  
103 - P presenter = delegateCallback.createPresenter();  
104 - if (presenter == null) {  
105 - throw new NullPointerException("Presenter returned from createPresenter() is null.");  
106 - }  
107 - if (keepPresenterDuringScreenOrientationChange) {  
108 - Context context = delegateCallback.getContext();  
109 - mosbyViewId = UUID.randomUUID().toString();  
110 - PresenterManager.putPresenter(PresenterManager.getActivity(context), mosbyViewId, presenter);  
111 - }  
112 - return presenter;  
113 - }  
114 -  
115 - @NonNull private Context getContext() {  
116 - Context c = delegateCallback.getContext();  
117 - if (c == null) {  
118 - throw new NullPointerException("Context returned from " + delegateCallback + " is null");  
119 - }  
120 - return c;  
121 - }  
122 -  
123 - @Override public void onAttachedToWindow() {  
124 - if (isInEditMode) return;  
125 -  
126 - P presenter = null;  
127 - if (mosbyViewId == null) {  
128 - // No presenter available,  
129 - // Activity is starting for the first time (or keepPresenterInstance == false)  
130 - presenter = createViewIdAndCreatePresenter();  
131 - if (DEBUG) {  
132 - Log.d(DEBUG_TAG, "new Presenter instance created: " + presenter);  
133 - }  
134 - } else {  
135 - presenter = PresenterManager.getPresenter(activity, mosbyViewId);  
136 - if (presenter == null) {  
137 - // Process death,  
138 - // hence no presenter with the given viewState id stored, although we have a viewState id  
139 - presenter = createViewIdAndCreatePresenter();  
140 - if (DEBUG) {  
141 - Log.d(DEBUG_TAG,  
142 - "No Presenter instance found in cache, although MosbyView ID present. This was caused by process death, therefore new Presenter instance created: "  
143 - + presenter);  
144 - }  
145 - } else {  
146 - if (DEBUG) {  
147 - Log.d(DEBUG_TAG, "Presenter instance reused from internal cache: " + presenter);  
148 - }  
149 - }  
150 - }  
151 -  
152 - // presenter is ready, so attach viewState  
153 - V view = delegateCallback.getMvpView();  
154 - if (view == null) {  
155 - throw new NullPointerException(  
156 - "MvpView returned from getMvpView() is null. Returned by " + delegateCallback);  
157 - }  
158 -  
159 - if (presenter == null) {  
160 - throw new IllegalStateException(  
161 - "Oops, Presenter is null. This seems to be a Mosby internal bug. Please report this issue here: https://github.com/sockeqwe/mosby/issues");  
162 - }  
163 -  
164 - /*  
165 - if (viewStateWillBeRestored) {  
166 - delegateCallback.setRestoringViewState(true);  
167 - }  
168 - */  
169 -  
170 - delegateCallback.setPresenter(presenter);  
171 - presenter.attachView(view);  
172 -  
173 - /*  
174 - if (viewStateWillBeRestored) {  
175 - delegateCallback.setRestoringViewState(false);  
176 - }  
177 - */  
178 -  
179 - if (DEBUG) {  
180 - Log.d(DEBUG_TAG,  
181 - "MvpView attached to Presenter. MvpView: " + view + " Presenter: " + presenter);  
182 - }  
183 - }  
184 -  
185 - /**  
186 - * Must be called from {@link View#onSaveInstanceState()}  
187 - */  
188 - public Parcelable onSaveInstanceState() {  
189 - if (isInEditMode) return null;  
190 -  
191 - Parcelable superState = delegateCallback.superOnSaveInstanceState();  
192 -  
193 - if (keepPresenterDuringScreenOrientationChange) {  
194 - return new MosbySavedState(superState, mosbyViewId);  
195 - } else {  
196 - return superState;  
197 - }  
198 - }  
199 -  
200 - /**  
201 - * Restore the data from SavedState  
202 - *  
203 - * @param state The state to read data from  
204 - */  
205 - private void restoreSavedState(MosbySavedState state) {  
206 - mosbyViewId = state.getMosbyViewId();  
207 - }  
208 -  
209 - /**  
210 - * Must be called from {@link View#onRestoreInstanceState(Parcelable)}  
211 - */  
212 - public void onRestoreInstanceState(Parcelable state) {  
213 - if (isInEditMode) return;  
214 -  
215 - if (!(state instanceof MosbySavedState)) {  
216 - delegateCallback.superOnRestoreInstanceState(state);  
217 - return;  
218 - }  
219 -  
220 - MosbySavedState savedState = (MosbySavedState) state;  
221 - restoreSavedState(savedState);  
222 - delegateCallback.superOnRestoreInstanceState(savedState.getSuperState());  
223 - }  
224 -  
225 - @Override public void onDetachedFromWindow() {  
226 - if (isInEditMode) return;  
227 -  
228 - detachPresenterIfNotDoneYet();  
229 -  
230 - if (!checkedActivityFinishing) {  
231 -  
232 - boolean destroyPermanently = !ActivityMvpDelegateImpl.retainPresenterInstance(  
233 - keepPresenterDuringScreenOrientationChange, activity);  
234 -  
235 - if (destroyPermanently) {  
236 - destroyPresenterIfNotDoneYet();  
237 - } else if (!activity.isChangingConfigurations()) {  
238 - // View removed manually from screen  
239 - destroyPresenterIfNotDoneYet();  
240 - }  
241 - } // else --> see onActivityDestroyed()  
242 - }  
243 -  
244 - @Override public void onActivityDestroyed(Activity activity) {  
245 -  
246 - if (activity == this.activity) {  
247 - // The hosting activity of this view has been destroyed, so time to destroy the presenter too?  
248 -  
249 - activity.getApplication().unregisterActivityLifecycleCallbacks(this);  
250 - checkedActivityFinishing = true;  
251 -  
252 - boolean destroyedPermanently = !ActivityMvpDelegateImpl.retainPresenterInstance(  
253 - keepPresenterDuringScreenOrientationChange, activity);  
254 -  
255 - if (destroyedPermanently) {  
256 - // Whole activity will be destroyed  
257 - detachPresenterIfNotDoneYet();  
258 - destroyPresenterIfNotDoneYet();  
259 - }  
260 - }  
261 -  
262 - }  
263 -  
264 - @Override public void onActivityCreated(Activity activity, Bundle savedInstanceState) {  
265 - }  
266 -  
267 - @Override public void onActivityStarted(Activity activity) {  
268 - }  
269 -  
270 - @Override public void onActivityResumed(Activity activity) {  
271 - }  
272 -  
273 - @Override public void onActivityPaused(Activity activity) {  
274 - }  
275 -  
276 - @Override public void onActivityStopped(Activity activity) {  
277 - }  
278 -  
279 - @Override public void onActivitySaveInstanceState(Activity activity, Bundle outState) {  
280 - }  
281 -  
282 - private void destroyPresenterIfNotDoneYet() {  
283 - if (!presenterDestroyed) {  
284 - P presenter = delegateCallback.getPresenter();  
285 - if (presenter != null) {  
286 - presenter.destroy();  
287 - }  
288 - presenterDestroyed = true;  
289 - activity.getApplication().unregisterActivityLifecycleCallbacks(this);  
290 - if (DEBUG) {  
291 - Log.d(DEBUG_TAG, "Presenter destroyed: " + presenter);  
292 - }  
293 -  
294 - if (mosbyViewId != null) {  
295 - // mosbyViewId == null if keepPresenterDuringScreenOrientationChange == false  
296 - PresenterManager.remove(activity, mosbyViewId);  
297 - }  
298 - mosbyViewId = null;  
299 - }  
300 - }  
301 -  
302 - private void detachPresenterIfNotDoneYet() {  
303 - if (!presenterDetached) {  
304 - P presenter = delegateCallback.getPresenter();  
305 - if (presenter != null) {  
306 - presenter.detachView();  
307 - }  
308 - presenterDetached = true;  
309 - if (DEBUG) {  
310 - Log.d(DEBUG_TAG,  
311 - "view " + delegateCallback.getMvpView() + " detached from Presenter " + presenter);  
312 - }  
313 - }  
314 - }  
315 -}