restructure detail activity

This commit is contained in:
Christian Schabesberger 2016-08-03 00:12:58 +02:00
parent 7a25588995
commit 06e2e548be
4 changed files with 269 additions and 167 deletions

View File

@ -0,0 +1,227 @@
package org.schabi.newpipe.detail;
import android.app.Activity;
import android.os.Handler;
import android.preference.PreferenceManager;
import android.util.Log;
import android.view.View;
import org.schabi.newpipe.Downloader;
import org.schabi.newpipe.ErrorActivity;
import org.schabi.newpipe.R;
import org.schabi.newpipe.extractor.ParsingException;
import org.schabi.newpipe.extractor.ServiceList;
import org.schabi.newpipe.extractor.StreamExtractor;
import org.schabi.newpipe.extractor.StreamInfo;
import org.schabi.newpipe.extractor.StreamingService;
import org.schabi.newpipe.extractor.services.youtube.YoutubeStreamExtractor;
import org.schabi.newpipe.search_fragment.StreamInfoListAdapter;
import java.io.IOException;
/**
* Created by the-scrabi on 02.08.16.
*/
public class StreamInfoWorker {
private static final String TAG = StreamInfoWorker.class.toString();
public interface OnStreamInfoReceivedListener {
void onReceive(StreamInfo info);
void onError(int messageId);
void onBlockedByGemaError();
void onContentErrorWithMessage(int messageId);
void onContentError();
}
private class StreamResultReturnedRunnable implements Runnable {
private final StreamInfo streamInfo;
public StreamResultReturnedRunnable(StreamInfo streamInfo) {
this.streamInfo = streamInfo;
}
@Override
public void run() {
/*
if(a != null) {
boolean showAgeRestrictedContent = PreferenceManager.getDefaultSharedPreferences(a)
.getBoolean(activity.getString(R.string.show_age_restricted_content), false);
if (streamInfo.age_limit == 0 || showAgeRestrictedContent) {
updateInfo(streamInfo);
} else {
onNotSpecifiedContentErrorWithMessage(R.string.video_is_age_restricted);
}
}
*/
}
}
private class StreamExtractorRunnable implements Runnable {
private final Handler h = new Handler();
private StreamExtractor streamExtractor;
private final int serviceId;
private final String videoUrl;
private Activity a;
public StreamExtractorRunnable(Activity a, String videoUrl, int serviceId) {
this.serviceId = serviceId;
this.videoUrl = videoUrl;
this.a = a;
}
@Override
public void run() {
StreamInfo streamInfo = null;
StreamingService service = null;
try {
service = ServiceList.getService(serviceId);
} catch (Exception e) {
e.printStackTrace();
ErrorActivity.reportError(h, a, e, VideoItemDetailFragment.class, null,
ErrorActivity.ErrorInfo.make(ErrorActivity.REQUESTED_STREAM,
"", videoUrl, R.string.could_not_get_stream));
return;
}
try {
streamExtractor = service.getExtractorInstance(videoUrl, new Downloader());
streamInfo = StreamInfo.getVideoInfo(streamExtractor, new Downloader());
final StreamInfo info = streamInfo;
h.post(new Runnable() {
@Override
public void run() {
onStreamInfoReceivedListener.onReceive(info);
}
});
// look for errors during extraction
// this if statement only covers extra information.
// if these are not available or caused an error, they are just not available
// but don't render the stream information unusalbe.
if(streamInfo != null &&
!streamInfo.errors.isEmpty()) {
Log.e(TAG, "OCCURRED ERRORS DURING EXTRACTION:");
for (Throwable e : streamInfo.errors) {
e.printStackTrace();
Log.e(TAG, "------");
}
View rootView = a != null ? a.findViewById(R.id.videoitem_detail) : null;
ErrorActivity.reportError(h, a,
streamInfo.errors, null, rootView,
ErrorActivity.ErrorInfo.make(ErrorActivity.REQUESTED_STREAM,
service.getServiceInfo().name, videoUrl, 0 /* no message for the user */));
}
// These errors render the stream information unusable.
} catch (IOException e) {
h.post(new Runnable() {
@Override
public void run() {
onStreamInfoReceivedListener.onError(R.string.network_error);
}
});
e.printStackTrace();
}
// custom service related exceptions
catch (YoutubeStreamExtractor.DecryptException de) {
h.post(new Runnable() {
@Override
public void run() {
onStreamInfoReceivedListener.onError(R.string.youtube_signature_decryption_error);
}
});
de.printStackTrace();
} catch (YoutubeStreamExtractor.GemaException ge) {
h.post(new Runnable() {
@Override
public void run() {
onStreamInfoReceivedListener.onBlockedByGemaError();
}
});
} catch(YoutubeStreamExtractor.LiveStreamException e) {
h.post(new Runnable() {
@Override
public void run() {
onStreamInfoReceivedListener
.onContentErrorWithMessage(R.string.live_streams_not_supported);
}
});
}
// ----------------------------------------
catch(StreamExtractor.ContentNotAvailableException e) {
h.post(new Runnable() {
@Override
public void run() {
onStreamInfoReceivedListener
.onContentError();
}
});
e.printStackTrace();
} catch(StreamInfo.StreamExctractException e) {
if(!streamInfo.errors.isEmpty()) {
// !!! if this case ever kicks in someone gets kicked out !!!
ErrorActivity.reportError(h, a, e, VideoItemDetailFragment.class, null,
ErrorActivity.ErrorInfo.make(ErrorActivity.REQUESTED_STREAM,
service.getServiceInfo().name, videoUrl, R.string.could_not_get_stream));
} else {
ErrorActivity.reportError(h, a, streamInfo.errors, VideoItemDetailFragment.class, null,
ErrorActivity.ErrorInfo.make(ErrorActivity.REQUESTED_STREAM,
service.getServiceInfo().name, videoUrl, R.string.could_not_get_stream));
}
h.post(new Runnable() {
@Override
public void run() {
a.finish();
}
});
e.printStackTrace();
} catch (ParsingException e) {
ErrorActivity.reportError(h, a, e, VideoItemDetailFragment.class, null,
ErrorActivity.ErrorInfo.make(ErrorActivity.REQUESTED_STREAM,
service.getServiceInfo().name, videoUrl, R.string.parsing_error));
h.post(new Runnable() {
@Override
public void run() {
a.finish();
}
});
e.printStackTrace();
} catch(Exception e) {
ErrorActivity.reportError(h, a, e, VideoItemDetailFragment.class, null,
ErrorActivity.ErrorInfo.make(ErrorActivity.REQUESTED_STREAM,
service.getServiceInfo().name, videoUrl, R.string.general_error));
h.post(new Runnable() {
@Override
public void run() {
a.finish();
}
});
e.printStackTrace();
}
}
}
private static StreamInfoWorker streamInfoWorker = null;
private StreamExtractorRunnable runnable = null;
private OnStreamInfoReceivedListener onStreamInfoReceivedListener = null;
private StreamInfoWorker() {
}
public static StreamInfoWorker getInstance() {
return streamInfoWorker == null ? (streamInfoWorker = new StreamInfoWorker()) : streamInfoWorker;
}
public void search(int serviceId, String url, Activity a) {
runnable = new StreamExtractorRunnable(a, url, serviceId);
Thread thread = new Thread(runnable);
thread.start();
}
public void setOnStreamInfoReceivedListener(
OnStreamInfoReceivedListener onStreamInfoReceivedListener) {
this.onStreamInfoReceivedListener = onStreamInfoReceivedListener;
}
}

View File

@ -130,144 +130,6 @@ public class VideoItemDetailFragment extends Fragment {
private OnInvokeCreateOptionsMenuListener onInvokeCreateOptionsMenuListener; private OnInvokeCreateOptionsMenuListener onInvokeCreateOptionsMenuListener;
private class VideoExtractorRunnable implements Runnable {
private final Handler h = new Handler();
private StreamExtractor streamExtractor;
private final StreamingService service;
private final String videoUrl;
public VideoExtractorRunnable(String videoUrl, StreamingService service) {
this.service = service;
this.videoUrl = videoUrl;
}
@Override
public void run() {
StreamInfo streamInfo = null;
try {
streamExtractor = service.getExtractorInstance(videoUrl, new Downloader());
streamInfo = StreamInfo.getVideoInfo(streamExtractor, new Downloader());
h.post(new VideoResultReturnedRunnable(streamInfo));
// look for errors during extraction
// this if statement only covers extra information.
// if these are not available or caused an error, they are just not available
// but don't render the stream information unusalbe.
if(streamInfo != null &&
!streamInfo.errors.isEmpty()) {
Log.e(TAG, "OCCURRED ERRORS DURING EXTRACTION:");
for (Throwable e : streamInfo.errors) {
e.printStackTrace();
Log.e(TAG, "------");
}
Activity a = getActivity();
View rootView = a != null ? a.findViewById(R.id.videoitem_detail) : null;
ErrorActivity.reportError(h, getActivity(),
streamInfo.errors, null, rootView,
ErrorActivity.ErrorInfo.make(ErrorActivity.REQUESTED_STREAM,
service.getServiceInfo().name, videoUrl, 0 /* no message for the user */));
}
// These errors render the stream information unusable.
} catch (IOException e) {
postNewErrorToast(h, R.string.network_error);
e.printStackTrace();
}
// custom service related exceptions
catch (YoutubeStreamExtractor.DecryptException de) {
postNewErrorToast(h, R.string.youtube_signature_decryption_error);
de.printStackTrace();
} catch (YoutubeStreamExtractor.GemaException ge) {
h.post(new Runnable() {
@Override
public void run() {
onErrorBlockedByGema();
}
});
} catch(YoutubeStreamExtractor.LiveStreamException e) {
h.post(new Runnable() {
@Override
public void run() {
onNotSpecifiedContentErrorWithMessage(R.string.live_streams_not_supported);
}
});
}
// ----------------------------------------
catch(StreamExtractor.ContentNotAvailableException e) {
h.post(new Runnable() {
@Override
public void run() {
onNotSpecifiedContentError();
}
});
e.printStackTrace();
} catch(StreamInfo.StreamExctractException e) {
if(!streamInfo.errors.isEmpty()) {
// !!! if this case ever kicks in someone gets kicked out !!!
ErrorActivity.reportError(h, getActivity(), e, VideoItemDetailFragment.class, null,
ErrorActivity.ErrorInfo.make(ErrorActivity.REQUESTED_STREAM,
service.getServiceInfo().name, videoUrl, R.string.could_not_get_stream));
} else {
ErrorActivity.reportError(h, getActivity(), streamInfo.errors, VideoItemDetailFragment.class, null,
ErrorActivity.ErrorInfo.make(ErrorActivity.REQUESTED_STREAM,
service.getServiceInfo().name, videoUrl, R.string.could_not_get_stream));
}
h.post(new Runnable() {
@Override
public void run() {
getActivity().finish();
}
});
e.printStackTrace();
} catch (ParsingException e) {
ErrorActivity.reportError(h, getActivity(), e, VideoItemDetailFragment.class, null,
ErrorActivity.ErrorInfo.make(ErrorActivity.REQUESTED_STREAM,
service.getServiceInfo().name, videoUrl, R.string.parsing_error));
h.post(new Runnable() {
@Override
public void run() {
getActivity().finish();
}
});
e.printStackTrace();
} catch(Exception e) {
ErrorActivity.reportError(h, getActivity(), e, VideoItemDetailFragment.class, null,
ErrorActivity.ErrorInfo.make(ErrorActivity.REQUESTED_STREAM,
service.getServiceInfo().name, videoUrl, R.string.general_error));
h.post(new Runnable() {
@Override
public void run() {
getActivity().finish();
}
});
e.printStackTrace();
}
}
}
private class VideoResultReturnedRunnable implements Runnable {
private final StreamInfo streamInfo;
public VideoResultReturnedRunnable(StreamInfo streamInfo) {
this.streamInfo = streamInfo;
}
@Override
public void run() {
Activity a = getActivity();
if(a != null) {
boolean showAgeRestrictedContent = PreferenceManager.getDefaultSharedPreferences(a)
.getBoolean(activity.getString(R.string.show_age_restricted_content), false);
if (streamInfo.age_limit == 0 || showAgeRestrictedContent) {
updateInfo(streamInfo);
} else {
onNotSpecifiedContentErrorWithMessage(R.string.video_is_age_restricted);
}
}
}
}
private void updateInfo(final StreamInfo info) { private void updateInfo(final StreamInfo info) {
try { try {
Context c = getContext(); Context c = getContext();
@ -768,6 +630,34 @@ public class VideoItemDetailFragment extends Fragment {
showNextVideoItem = PreferenceManager.getDefaultSharedPreferences(getActivity()) showNextVideoItem = PreferenceManager.getDefaultSharedPreferences(getActivity())
.getBoolean(activity.getString(R.string.show_next_video_key), true); .getBoolean(activity.getString(R.string.show_next_video_key), true);
StreamInfoWorker siw = StreamInfoWorker.getInstance();
siw.setOnStreamInfoReceivedListener(new StreamInfoWorker.OnStreamInfoReceivedListener() {
@Override
public void onReceive(StreamInfo info) {
updateInfo(info);
}
@Override
public void onError(int messageId) {
postNewErrorToast(messageId);
}
@Override
public void onBlockedByGemaError() {
onErrorBlockedByGema();
}
@Override
public void onContentErrorWithMessage(int messageId) {
onNotSpecifiedContentErrorWithMessage(messageId);
}
@Override
public void onContentError() {
onNotSpecifiedContentError();
}
});
} }
@Override @Override
@ -800,17 +690,12 @@ public class VideoItemDetailFragment extends Fragment {
// then we must not try to access objects of this fragment. // then we must not try to access objects of this fragment.
// Otherwise the applications would crash. // Otherwise the applications would crash.
if(backgroundButton != null) { if(backgroundButton != null) {
try { streamingServiceId = getArguments().getInt(STREAMING_SERVICE);
streamingServiceId = getArguments().getInt(STREAMING_SERVICE); String videoUrl = getArguments().getString(VIDEO_URL);
StreamingService streamingService = ServiceList.getService(streamingServiceId); StreamInfoWorker siw = StreamInfoWorker.getInstance();
Thread videoExtractorThread = new Thread(new VideoExtractorRunnable( siw.search(streamingServiceId, videoUrl, getActivity());
getArguments().getString(VIDEO_URL), streamingService));
autoPlayEnabled = getArguments().getBoolean(AUTO_PLAY); autoPlayEnabled = getArguments().getBoolean(AUTO_PLAY);
videoExtractorThread.start();
} catch (Exception e) {
e.printStackTrace();
}
if(Build.VERSION.SDK_INT >= 18) { if(Build.VERSION.SDK_INT >= 18) {
ImageView thumbnailView = (ImageView) activity.findViewById(R.id.detailThumbnailView); ImageView thumbnailView = (ImageView) activity.findViewById(R.id.detailThumbnailView);
@ -932,23 +817,13 @@ public class VideoItemDetailFragment extends Fragment {
this.onInvokeCreateOptionsMenuListener = listener; this.onInvokeCreateOptionsMenuListener = listener;
} }
private void postNewErrorToast(Handler h, final int stringResource) { private void postNewErrorToast(final int stringResource) {
h.post(new Runnable() { Toast.makeText(VideoItemDetailFragment.this.getActivity(),
@Override stringResource, Toast.LENGTH_LONG).show();
public void run() {
Toast.makeText(VideoItemDetailFragment.this.getActivity(),
stringResource, Toast.LENGTH_LONG).show();
}
});
} }
private void postNewErrorToast(Handler h, final String message) { private void postNewErrorToast(final String message) {
h.post(new Runnable() { Toast.makeText(VideoItemDetailFragment.this.getActivity(),
@Override message, Toast.LENGTH_LONG).show();
public void run() {
Toast.makeText(VideoItemDetailFragment.this.getActivity(),
message, Toast.LENGTH_LONG).show();
}
});
} }
} }

View File

@ -10,4 +10,5 @@
android:layout_marginRight="16dp" android:layout_marginRight="16dp"
app:layoutManager="LinearLayoutManager" app:layoutManager="LinearLayoutManager"
tools:context=".search_fragment.SearchInfoItemFragment" tools:context=".search_fragment.SearchInfoItemFragment"
tools:listitem="@layout/video_item" /> tools:listitem="@layout/video_item"
android:scrollbars="vertical"/>

View File

@ -4,8 +4,7 @@
android:orientation="vertical" android:layout_width="match_parent" android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:id="@+id/mainBG" android:id="@+id/mainBG"
tools:context=".detail.VideoItemDetailActivity" tools:context=".detail.VideoItemDetailActivity">
tools:showIn="@layout/activity_videoitem_list">
<TextView <TextView
android:layout_width="wrap_content" android:layout_width="wrap_content"