Merge remote-tracking branch 'origin/master'

This commit is contained in:
Weblate 2017-02-21 17:48:35 +01:00
commit b79ed8185f
19 changed files with 318 additions and 102 deletions

View File

@ -8,8 +8,8 @@ android {
applicationId "org.schabi.newpipe" applicationId "org.schabi.newpipe"
minSdkVersion 15 minSdkVersion 15
targetSdkVersion 25 targetSdkVersion 25
versionCode 23 versionCode 24
versionName "0.8.9" versionName "0.8.10"
} }
buildTypes { buildTypes {
release { release {

View File

@ -156,6 +156,7 @@
<activity <activity
android:name=".ChannelActivity" android:name=".ChannelActivity"
android:label="@string/title_activity_channel" android:label="@string/title_activity_channel"
android:launchMode="singleTask"
android:theme="@style/AppTheme.NoActionBar" /> android:theme="@style/AppTheme.NoActionBar" />
<activity <activity

View File

@ -36,6 +36,7 @@ import org.schabi.newpipe.extractor.exceptions.ParsingException;
import org.schabi.newpipe.info_list.InfoItemBuilder; import org.schabi.newpipe.info_list.InfoItemBuilder;
import org.schabi.newpipe.info_list.InfoListAdapter; import org.schabi.newpipe.info_list.InfoListAdapter;
import org.schabi.newpipe.report.ErrorActivity; import org.schabi.newpipe.report.ErrorActivity;
import org.schabi.newpipe.util.NavStack;
import java.io.IOException; import java.io.IOException;
import java.util.Objects; import java.util.Objects;
@ -62,15 +63,9 @@ import static android.os.Build.VERSION.SDK_INT;
*/ */
public class ChannelActivity extends AppCompatActivity { public class ChannelActivity extends AppCompatActivity {
private static final String TAG = ChannelActivity.class.toString(); private static final String TAG = ChannelActivity.class.toString();
private View rootView = null; private View rootView = null;
// intent const
public static final String CHANNEL_URL = "channel_url";
public static final String SERVICE_ID = "service_id";
private int serviceId = -1; private int serviceId = -1;
private String channelUrl = ""; private String channelUrl = "";
private int pageNumber = 0; private int pageNumber = 0;
@ -82,21 +77,31 @@ public class ChannelActivity extends AppCompatActivity {
@Override @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//since we set themeing we have to set translucent statusBar by hand
if (PreferenceManager.getDefaultSharedPreferences(this) if (PreferenceManager.getDefaultSharedPreferences(this)
.getString("theme", getResources().getString(R.string.light_theme_title)). .getString("theme", getResources().getString(R.string.light_theme_title)).
equals(getResources().getString(R.string.dark_theme_title))) { equals(getResources().getString(R.string.dark_theme_title))) {
setTheme(R.style.DarkTheme_NoActionBar); setTheme(R.style.DarkTheme_NoActionBar);
} }
super.onCreate(savedInstanceState); setTranslucentStatusBar(getWindow());
setContentView(R.layout.activity_channel); setContentView(R.layout.activity_channel);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
rootView = findViewById(R.id.rootView); rootView = findViewById(R.id.rootView);
setSupportActionBar(toolbar); setSupportActionBar(toolbar);
Intent i = getIntent(); if(savedInstanceState == null) {
channelUrl = i.getStringExtra(CHANNEL_URL); Intent i = getIntent();
serviceId = i.getIntExtra(SERVICE_ID, -1); channelUrl = i.getStringExtra(NavStack.URL);
serviceId = i.getIntExtra(NavStack.SERVICE_ID, -1);
} else {
channelUrl = savedInstanceState.getString(NavStack.URL);
serviceId = savedInstanceState.getInt(NavStack.SERVICE_ID);
NavStack.getInstance()
.restoreSavedInstanceState(savedInstanceState);
}
setTranslucentStatusBar(getWindow());
infoListAdapter = new InfoListAdapter(this, rootView); infoListAdapter = new InfoListAdapter(this, rootView);
RecyclerView recyclerView = (RecyclerView) findViewById(R.id.channel_streams_view); RecyclerView recyclerView = (RecyclerView) findViewById(R.id.channel_streams_view);
@ -107,11 +112,8 @@ public class ChannelActivity extends AppCompatActivity {
new InfoItemBuilder.OnInfoItemSelectedListener() { new InfoItemBuilder.OnInfoItemSelectedListener() {
@Override @Override
public void selected(String url, int serviceId) { public void selected(String url, int serviceId) {
Intent detailIntent = new Intent(ChannelActivity.this, VideoItemDetailActivity.class); NavStack.getInstance()
detailIntent.putExtra(VideoItemDetailFragment.VIDEO_URL, url); .openDetailActivity(ChannelActivity.this, url, serviceId);
detailIntent.putExtra(
VideoItemDetailFragment.STREAMING_SERVICE, serviceId);
startActivity(detailIntent);
} }
}); });
@ -141,7 +143,14 @@ public class ChannelActivity extends AppCompatActivity {
requestData(false); requestData(false);
} }
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putString(NavStack.URL, channelUrl);
outState.putInt(NavStack.SERVICE_ID, serviceId);
NavStack.getInstance()
.onSaveInstanceState(outState);
}
private void updateUi(final ChannelInfo info) { private void updateUi(final ChannelInfo info) {
CollapsingToolbarLayout ctl = (CollapsingToolbarLayout) findViewById(R.id.channel_toolbar_layout); CollapsingToolbarLayout ctl = (CollapsingToolbarLayout) findViewById(R.id.channel_toolbar_layout);
@ -312,4 +321,14 @@ public class ChannelActivity extends AppCompatActivity {
window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
} }
@Override
public void onBackPressed() {
try {
NavStack.getInstance()
.navBack(this);
} catch (Exception e) {
ErrorActivity.reportUiError(this, e);
}
}
} }

View File

@ -86,4 +86,9 @@ public class MainActivity extends ThemableActivity {
return super.onOptionsItemSelected(item); return super.onOptionsItemSelected(item);
} }
} }
@Override
public void onBackPressed() {
//ignore back
}
} }

View File

@ -1,5 +1,6 @@
package org.schabi.newpipe.detail; package org.schabi.newpipe.detail;
import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.media.AudioManager; import android.media.AudioManager;
import android.os.Bundle; import android.os.Bundle;
@ -16,10 +17,14 @@ import org.schabi.newpipe.R;
import org.schabi.newpipe.ThemableActivity; import org.schabi.newpipe.ThemableActivity;
import org.schabi.newpipe.extractor.NewPipe; import org.schabi.newpipe.extractor.NewPipe;
import org.schabi.newpipe.extractor.StreamingService; import org.schabi.newpipe.extractor.StreamingService;
import org.schabi.newpipe.report.ErrorActivity;
import org.schabi.newpipe.util.NavStack;
import java.util.Collection; import java.util.Collection;
import java.util.HashSet; import java.util.HashSet;
import static android.os.Build.VERSION.SDK_INT;
/** /**
* Copyright (C) Christian Schabesberger 2015 <chris.schabesberger@mailbox.org> * Copyright (C) Christian Schabesberger 2015 <chris.schabesberger@mailbox.org>
@ -81,8 +86,10 @@ public class VideoItemDetailActivity extends ThemableActivity {
if (savedInstanceState == null) { if (savedInstanceState == null) {
handleIntent(getIntent()); handleIntent(getIntent());
} else { } else {
videoUrl = savedInstanceState.getString(VideoItemDetailFragment.VIDEO_URL); videoUrl = savedInstanceState.getString(NavStack.URL);
currentStreamingService = savedInstanceState.getInt(VideoItemDetailFragment.STREAMING_SERVICE); currentStreamingService = savedInstanceState.getInt(NavStack.SERVICE_ID);
NavStack.getInstance()
.restoreSavedInstanceState(savedInstanceState);
addFragment(savedInstanceState); addFragment(savedInstanceState);
} }
} }
@ -114,12 +121,12 @@ public class VideoItemDetailActivity extends ThemableActivity {
currentStreamingService = getServiceIdByUrl(videoUrl); currentStreamingService = getServiceIdByUrl(videoUrl);
} else { } else {
//this is if the video was called through another NewPipe activity //this is if the video was called through another NewPipe activity
videoUrl = intent.getStringExtra(VideoItemDetailFragment.VIDEO_URL); videoUrl = intent.getStringExtra(NavStack.URL);
currentStreamingService = intent.getIntExtra(VideoItemDetailFragment.STREAMING_SERVICE, -1); currentStreamingService = intent.getIntExtra(NavStack.SERVICE_ID, -1);
} }
arguments.putBoolean(VideoItemDetailFragment.AUTO_PLAY, autoplay); arguments.putBoolean(VideoItemDetailFragment.AUTO_PLAY, autoplay);
arguments.putString(VideoItemDetailFragment.VIDEO_URL, videoUrl); arguments.putString(NavStack.URL, videoUrl);
arguments.putInt(VideoItemDetailFragment.STREAMING_SERVICE, currentStreamingService); arguments.putInt(NavStack.SERVICE_ID, currentStreamingService);
addFragment(arguments); addFragment(arguments);
} }
@ -142,9 +149,11 @@ public class VideoItemDetailActivity extends ThemableActivity {
@Override @Override
public void onSaveInstanceState(Bundle outState) { public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState); super.onSaveInstanceState(outState);
outState.putString(VideoItemDetailFragment.VIDEO_URL, videoUrl); outState.putString(NavStack.URL, videoUrl);
outState.putInt(VideoItemDetailFragment.STREAMING_SERVICE, currentStreamingService); outState.putInt(NavStack.SERVICE_ID, currentStreamingService);
outState.putBoolean(VideoItemDetailFragment.AUTO_PLAY, false); outState.putBoolean(VideoItemDetailFragment.AUTO_PLAY, false);
NavStack.getInstance()
.onSaveInstanceState(outState);
} }
@Override @Override
@ -159,15 +168,24 @@ public class VideoItemDetailActivity extends ThemableActivity {
// http://developer.android.com/design/patterns/navigation.html#up-vs-back // http://developer.android.com/design/patterns/navigation.html#up-vs-back
Intent intent = new Intent(this, MainActivity.class); NavStack.getInstance()
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); .openMainActivity(this);
NavUtils.navigateUpTo(this, intent);
return true; return true;
} else { } else {
return super.onOptionsItemSelected(item); return super.onOptionsItemSelected(item);
} }
} }
@Override
public void onBackPressed() {
try {
NavStack.getInstance()
.navBack(this);
} catch (Exception e) {
ErrorActivity.reportUiError(this, e);
}
}
/** /**
* Retrieves all Strings which look remotely like URLs from a text. * Retrieves all Strings which look remotely like URLs from a text.
* Used if NewPipe was called through share menu. * Used if NewPipe was called through share menu.
@ -224,7 +242,7 @@ public class VideoItemDetailActivity extends ThemableActivity {
StreamingService[] serviceList = NewPipe.getServices(); StreamingService[] serviceList = NewPipe.getServices();
int service = -1; int service = -1;
for (int i = 0; i < serviceList.length; i++) { for (int i = 0; i < serviceList.length; i++) {
if (serviceList[i].getUrlIdHandlerInstance().acceptUrl(videoUrl)) { if (serviceList[i].getStreamUrlIdHandlerInstance().acceptUrl(videoUrl)) {
service = i; service = i;
//videoExtractor = ServiceList.getService(i).getExtractorInstance(); //videoExtractor = ServiceList.getService(i).getExtractorInstance();
break; break;

View File

@ -40,7 +40,6 @@ import com.nostra13.universalimageloader.core.assist.FailReason;
import com.nostra13.universalimageloader.core.listener.ImageLoadingListener; import com.nostra13.universalimageloader.core.listener.ImageLoadingListener;
import org.schabi.newpipe.ActivityCommunicator; import org.schabi.newpipe.ActivityCommunicator;
import org.schabi.newpipe.ChannelActivity;
import org.schabi.newpipe.ImageErrorLoadingListener; import org.schabi.newpipe.ImageErrorLoadingListener;
import org.schabi.newpipe.Localization; import org.schabi.newpipe.Localization;
import org.schabi.newpipe.R; import org.schabi.newpipe.R;
@ -51,7 +50,6 @@ import org.schabi.newpipe.extractor.MediaFormat;
import org.schabi.newpipe.extractor.NewPipe; import org.schabi.newpipe.extractor.NewPipe;
import org.schabi.newpipe.extractor.stream_info.AudioStream; import org.schabi.newpipe.extractor.stream_info.AudioStream;
import org.schabi.newpipe.extractor.stream_info.StreamInfo; import org.schabi.newpipe.extractor.stream_info.StreamInfo;
import org.schabi.newpipe.extractor.stream_info.StreamInfoItem;
import org.schabi.newpipe.extractor.stream_info.VideoStream; import org.schabi.newpipe.extractor.stream_info.VideoStream;
import org.schabi.newpipe.info_list.InfoItemBuilder; import org.schabi.newpipe.info_list.InfoItemBuilder;
import org.schabi.newpipe.player.BackgroundPlayer; import org.schabi.newpipe.player.BackgroundPlayer;
@ -59,6 +57,8 @@ import org.schabi.newpipe.player.ExoPlayerActivity;
import org.schabi.newpipe.player.PlayVideoActivity; import org.schabi.newpipe.player.PlayVideoActivity;
import org.schabi.newpipe.report.ErrorActivity; import org.schabi.newpipe.report.ErrorActivity;
import java.util.Vector; import java.util.Vector;
import org.schabi.newpipe.util.NavStack;
import org.schabi.newpipe.util.PermissionHelper; import org.schabi.newpipe.util.PermissionHelper;
import static android.app.Activity.RESULT_OK; import static android.app.Activity.RESULT_OK;
@ -92,8 +92,6 @@ public class VideoItemDetailFragment extends Fragment {
* The fragment argument representing the item ID that this fragment * The fragment argument representing the item ID that this fragment
* represents. * represents.
*/ */
public static final String VIDEO_URL = "video_url";
public static final String STREAMING_SERVICE = "streaming_service";
public static final String AUTO_PLAY = "auto_play"; public static final String AUTO_PLAY = "auto_play";
private AppCompatActivity activity; private AppCompatActivity activity;
@ -289,10 +287,8 @@ public class VideoItemDetailFragment extends Fragment {
channelButton.setOnClickListener(new View.OnClickListener() { channelButton.setOnClickListener(new View.OnClickListener() {
@Override @Override
public void onClick(View view) { public void onClick(View view) {
Intent i = new Intent(activity, ChannelActivity.class); NavStack.getInstance()
i.putExtra(ChannelActivity.CHANNEL_URL, info.channel_url); .openChannelActivity(getActivity(), info.channel_url, info.service_id);
i.putExtra(ChannelActivity.SERVICE_ID, info.service_id);
startActivity(i);
} }
}); });
} else { } else {
@ -544,7 +540,8 @@ public class VideoItemDetailFragment extends Fragment {
new InfoItemBuilder.OnInfoItemSelectedListener() { new InfoItemBuilder.OnInfoItemSelectedListener() {
@Override @Override
public void selected(String url, int serviceId) { public void selected(String url, int serviceId) {
openStreamUrl(url); NavStack.getInstance()
.openDetailActivity(getContext(), url, serviceId);
} }
}); });
} }
@ -679,8 +676,8 @@ 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) {
streamingServiceId = getArguments().getInt(STREAMING_SERVICE); streamingServiceId = getArguments().getInt(NavStack.SERVICE_ID);
String videoUrl = getArguments().getString(VIDEO_URL); String videoUrl = getArguments().getString(NavStack.URL);
StreamInfoWorker siw = StreamInfoWorker.getInstance(); StreamInfoWorker siw = StreamInfoWorker.getInstance();
siw.search(streamingServiceId, videoUrl, getActivity()); siw.search(streamingServiceId, videoUrl, getActivity());
@ -813,21 +810,13 @@ public class VideoItemDetailFragment extends Fragment {
stringResource, Toast.LENGTH_LONG).show(); stringResource, Toast.LENGTH_LONG).show();
} }
private void openStreamUrl(String url) {
Intent detailIntent = new Intent(activity, VideoItemDetailActivity.class);
detailIntent.putExtra(VideoItemDetailFragment.VIDEO_URL, url);
detailIntent.putExtra(
VideoItemDetailFragment.STREAMING_SERVICE, streamingServiceId);
activity.startActivity(detailIntent);
}
@Override @Override
public void onActivityResult(int requestCode, int resultCode, Intent data) { public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data); super.onActivityResult(requestCode, resultCode, data);
switch (requestCode) { switch (requestCode) {
case RECAPTCHA_REQUEST: case RECAPTCHA_REQUEST:
if (resultCode == RESULT_OK) { if (resultCode == RESULT_OK) {
String videoUrl = getArguments().getString(VIDEO_URL); String videoUrl = getArguments().getString(NavStack.URL);
StreamInfoWorker siw = StreamInfoWorker.getInstance(); StreamInfoWorker siw = StreamInfoWorker.getInstance();
siw.search(streamingServiceId, videoUrl, getActivity()); siw.search(streamingServiceId, videoUrl, getActivity());
} else { } else {

View File

@ -242,9 +242,7 @@ public class DownloadActivity extends ThemableActivity implements AdapterView.On
switch (id) { switch (id) {
case android.R.id.home: { case android.R.id.home: {
Intent intent = new Intent(this, org.schabi.newpipe.MainActivity.class); onBackPressed();
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
NavUtils.navigateUpTo(this, intent);
return true; return true;
} }
case R.id.action_settings: { case R.id.action_settings: {
@ -252,14 +250,6 @@ public class DownloadActivity extends ThemableActivity implements AdapterView.On
startActivity(intent); startActivity(intent);
return true; return true;
} }
case R.id.action_report_error: {
ErrorActivity.reportError(DownloadActivity.this, new Vector<Throwable>(),
null, null,
ErrorActivity.ErrorInfo.make(ErrorActivity.USER_REPORT,
null,
"user_report", R.string.user_report));
return true;
}
default: default:
return super.onOptionsItemSelected(item); return super.onOptionsItemSelected(item);
} }

View File

@ -34,25 +34,22 @@ public class NewPipe {
private static final String TAG = NewPipe.class.toString(); private static final String TAG = NewPipe.class.toString();
private static final StreamingService[] serviceList = {
new YoutubeService(0)
};
private static Downloader downloader = null; private static Downloader downloader = null;
public static StreamingService[] getServices() { public static StreamingService[] getServices() {
return serviceList; return ServiceList.serviceList;
} }
public static StreamingService getService(int serviceId)throws ExtractionException { public static StreamingService getService(int serviceId)throws ExtractionException {
for(StreamingService s : serviceList) { for(StreamingService s : ServiceList.serviceList) {
if(s.getServiceId() == serviceId) { if(s.getServiceId() == serviceId) {
return s; return s;
} }
} }
throw new ExtractionException("Service not known: " + Integer.toString(serviceId)); return null;
} }
public static StreamingService getService(String serviceName) throws ExtractionException { public static StreamingService getService(String serviceName) throws ExtractionException {
return serviceList[getIdOfService(serviceName)]; return ServiceList.serviceList[getIdOfService(serviceName)];
} }
public static String getNameOfService(int id) { public static String getNameOfService(int id) {
try { try {
@ -63,13 +60,13 @@ public class NewPipe {
return ""; return "";
} }
} }
public static int getIdOfService(String serviceName) throws ExtractionException { public static int getIdOfService(String serviceName) {
for(int i = 0; i < serviceList.length; i++) { for(int i = 0; i < ServiceList.serviceList.length; i++) {
if(serviceList[i].getServiceInfo().name.equals(serviceName)) { if(ServiceList.serviceList[i].getServiceInfo().name.equals(serviceName)) {
return i; return i;
} }
} }
throw new ExtractionException("Error: Service " + serviceName + " not known."); return -1;
} }
public static void init(Downloader d) { public static void init(Downloader d) {
@ -79,4 +76,13 @@ public class NewPipe {
public static Downloader getDownloader() { public static Downloader getDownloader() {
return downloader; return downloader;
} }
public static StreamingService getServiceByUrl(String url) {
for(StreamingService s : ServiceList.serviceList) {
if(s.getLinkTypeByUrl(url) != StreamingService.LinkType.NONE) {
return s;
}
}
return null;
}
} }

View File

@ -0,0 +1,13 @@
package org.schabi.newpipe.extractor;
import org.schabi.newpipe.extractor.services.youtube.YoutubeService;
/**
* Created by the-scrabi on 18.02.17.
*/
class ServiceList {
public static final StreamingService[] serviceList = {
new YoutubeService(0)
};
}

View File

@ -32,6 +32,13 @@ public abstract class StreamingService {
public String name = ""; public String name = "";
} }
public enum LinkType {
NONE,
STREAM,
CHANNEL,
PLAYLIST
}
private int serviceId; private int serviceId;
public StreamingService(int id) { public StreamingService(int id) {
@ -43,7 +50,7 @@ public abstract class StreamingService {
public abstract StreamExtractor getExtractorInstance(String url) public abstract StreamExtractor getExtractorInstance(String url)
throws IOException, ExtractionException; throws IOException, ExtractionException;
public abstract SearchEngine getSearchEngineInstance(); public abstract SearchEngine getSearchEngineInstance();
public abstract UrlIdHandler getUrlIdHandlerInstance(); public abstract UrlIdHandler getStreamUrlIdHandlerInstance();
public abstract UrlIdHandler getChannelUrlIdHandlerInstance(); public abstract UrlIdHandler getChannelUrlIdHandlerInstance();
public abstract ChannelExtractor getChannelExtractorInstance(String url, int page) public abstract ChannelExtractor getChannelExtractorInstance(String url, int page)
throws ExtractionException, IOException; throws ExtractionException, IOException;
@ -52,4 +59,20 @@ public abstract class StreamingService {
public final int getServiceId() { public final int getServiceId() {
return serviceId; return serviceId;
} }
/**
* figure out where the link is pointing to (a channel, video, playlist, etc.)
*/
public final LinkType getLinkTypeByUrl(String url) {
UrlIdHandler sH = getStreamUrlIdHandlerInstance();
UrlIdHandler cH = getChannelUrlIdHandlerInstance();
if(sH.acceptUrl(url)) {
return LinkType.STREAM;
} else if(cH.acceptUrl(url)) {
return LinkType.CHANNEL;
} else {
return LinkType.NONE;
}
}
} }

View File

@ -23,6 +23,7 @@ import org.schabi.newpipe.extractor.exceptions.ParsingException;
*/ */
public interface UrlIdHandler { public interface UrlIdHandler {
String getUrl(String videoId); String getUrl(String videoId);
String getId(String siteUrl) throws ParsingException; String getId(String siteUrl) throws ParsingException;
String cleanUrl(String siteUrl) throws ParsingException; String cleanUrl(String siteUrl) throws ParsingException;

View File

@ -56,11 +56,11 @@ public class YoutubeService extends StreamingService {
} }
@Override @Override
public SearchEngine getSearchEngineInstance() { public SearchEngine getSearchEngineInstance() {
return new YoutubeSearchEngine(getUrlIdHandlerInstance(), getServiceId()); return new YoutubeSearchEngine(getStreamUrlIdHandlerInstance(), getServiceId());
} }
@Override @Override
public UrlIdHandler getUrlIdHandlerInstance() { public UrlIdHandler getStreamUrlIdHandlerInstance() {
return YoutubeStreamUrlIdHandler.getInstance(); return YoutubeStreamUrlIdHandler.getInstance();
} }

View File

@ -150,7 +150,17 @@ public class YoutubeStreamUrlIdHandler implements UrlIdHandler {
@Override @Override
public boolean acceptUrl(String videoUrl) { public boolean acceptUrl(String videoUrl) {
videoUrl = videoUrl.toLowerCase(); videoUrl = videoUrl.toLowerCase();
return videoUrl.contains("youtube") || if(videoUrl.contains("youtube") ||
videoUrl.contains("youtu.be"); videoUrl.contains("youtu.be")) {
// bad programming I know
try {
getId(videoUrl);
return true;
} catch (Exception e) {
return false;
}
} else {
return false;
}
} }
} }

View File

@ -52,7 +52,7 @@ public class StreamInfoItemCollector extends InfoItemCollector {
throw new ParsingException("Error: UrlIdHandler not set"); throw new ParsingException("Error: UrlIdHandler not set");
} else if (!resultItem.webpage_url.isEmpty()) { } else if (!resultItem.webpage_url.isEmpty()) {
resultItem.id = NewPipe.getService(getServiceId()) resultItem.id = NewPipe.getService(getServiceId())
.getUrlIdHandlerInstance() .getStreamUrlIdHandlerInstance()
.getId(resultItem.webpage_url); .getId(resultItem.webpage_url);
} }
resultItem.title = extractor.getTitle(); resultItem.title = extractor.getTitle();

View File

@ -27,6 +27,7 @@ import org.schabi.newpipe.BuildConfig;
import org.schabi.newpipe.R; import org.schabi.newpipe.R;
import org.schabi.newpipe.detail.VideoItemDetailActivity; import org.schabi.newpipe.detail.VideoItemDetailActivity;
import org.schabi.newpipe.detail.VideoItemDetailFragment; import org.schabi.newpipe.detail.VideoItemDetailFragment;
import org.schabi.newpipe.util.NavStack;
import java.io.IOException; import java.io.IOException;
import java.util.Arrays; import java.util.Arrays;
@ -355,8 +356,8 @@ public class BackgroundPlayer extends Service /*implements MediaPlayer.OnPrepare
//build intent to return to video, on tapping notification //build intent to return to video, on tapping notification
Intent openDetailViewIntent = new Intent(getApplicationContext(), Intent openDetailViewIntent = new Intent(getApplicationContext(),
VideoItemDetailActivity.class); VideoItemDetailActivity.class);
openDetailViewIntent.putExtra(VideoItemDetailFragment.STREAMING_SERVICE, serviceId); openDetailViewIntent.putExtra(NavStack.SERVICE_ID, serviceId);
openDetailViewIntent.putExtra(VideoItemDetailFragment.VIDEO_URL, webUrl); openDetailViewIntent.putExtra(NavStack.URL, webUrl);
openDetailViewIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); openDetailViewIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
PendingIntent openDetailView = PendingIntent.getActivity(owner, noteID, PendingIntent openDetailView = PendingIntent.getActivity(owner, noteID,
openDetailViewIntent, PendingIntent.FLAG_UPDATE_CURRENT); openDetailViewIntent, PendingIntent.FLAG_UPDATE_CURRENT);

View File

@ -16,6 +16,7 @@ import android.support.v4.app.NavUtils;
import android.support.v7.app.ActionBar; import android.support.v7.app.ActionBar;
import android.os.Bundle; import android.os.Bundle;
import android.os.Handler; import android.os.Handler;
import android.support.v7.app.AppCompatActivity;
import android.util.Log; import android.util.Log;
import android.view.Menu; import android.view.Menu;
import android.view.MenuInflater; import android.view.MenuInflater;
@ -161,6 +162,10 @@ public class ErrorActivity extends ThemableActivity {
private TextView infoView; private TextView infoView;
private TextView errorMessageView; private TextView errorMessageView;
public static void reportUiError(final AppCompatActivity activity, final Throwable el) {
reportError(activity, el, activity.getClass(), null, ErrorInfo.make(UI_ERROR, "none", "", R.string.app_ui_crash));
}
public static void reportError(final Context context, final List<Throwable> el, public static void reportError(final Context context, final List<Throwable> el,
final Class returnAcitivty, View rootView, final ErrorInfo errorInfo) { final Class returnAcitivty, View rootView, final ErrorInfo errorInfo) {

View File

@ -30,6 +30,7 @@ import org.schabi.newpipe.R;
import org.schabi.newpipe.detail.VideoItemDetailActivity; import org.schabi.newpipe.detail.VideoItemDetailActivity;
import org.schabi.newpipe.detail.VideoItemDetailFragment; import org.schabi.newpipe.detail.VideoItemDetailFragment;
import org.schabi.newpipe.info_list.InfoListAdapter; import org.schabi.newpipe.info_list.InfoListAdapter;
import org.schabi.newpipe.util.NavStack;
import java.util.EnumSet; import java.util.EnumSet;
@ -224,13 +225,15 @@ public class SearchInfoItemFragment extends Fragment {
new InfoItemBuilder.OnInfoItemSelectedListener() { new InfoItemBuilder.OnInfoItemSelectedListener() {
@Override @Override
public void selected(String url, int serviceId) { public void selected(String url, int serviceId) {
startDetailActivity(url); NavStack.getInstance()
.openDetailActivity(getContext(), url, serviceId);
} }
}); });
infoListAdapter.setOnChannelInfoItemSelectedListener(new InfoItemBuilder.OnInfoItemSelectedListener() { infoListAdapter.setOnChannelInfoItemSelectedListener(new InfoItemBuilder.OnInfoItemSelectedListener() {
@Override @Override
public void selected(String url, int serviceId) { public void selected(String url, int serviceId) {
startChannelActivity(url, serviceId); NavStack.getInstance()
.openChannelActivity(getContext(), url, serviceId);
} }
}); });
recyclerView.setAdapter(infoListAdapter); recyclerView.setAdapter(infoListAdapter);
@ -257,20 +260,6 @@ public class SearchInfoItemFragment extends Fragment {
return view; return view;
} }
private void startDetailActivity(String url) {
Intent i = new Intent(getActivity(), VideoItemDetailActivity.class);
i.putExtra(VideoItemDetailFragment.STREAMING_SERVICE, streamingServiceId);
i.putExtra(VideoItemDetailFragment.VIDEO_URL, url);
getActivity().startActivity(i);
}
private void startChannelActivity(String url, int serviceId) {
Intent i = new Intent(getActivity(), ChannelActivity.class);
i.putExtra(ChannelActivity.CHANNEL_URL, url);
i.putExtra(ChannelActivity.SERVICE_ID, serviceId);
startActivity(i);
}
@Override @Override
public void onStart() { public void onStart() {
super.onStart(); super.onStart();

View File

@ -0,0 +1,151 @@
package org.schabi.newpipe.util;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.support.v4.app.NavUtils;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import org.schabi.newpipe.ChannelActivity;
import org.schabi.newpipe.MainActivity;
import org.schabi.newpipe.detail.VideoItemDetailActivity;
import org.schabi.newpipe.detail.VideoItemDetailFragment;
import org.schabi.newpipe.extractor.NewPipe;
import org.schabi.newpipe.extractor.StreamingService;
import java.util.ArrayList;
import java.util.Stack;
/**
* Created by Christian Schabesberger on 16.02.17.
*
* Copyright (C) Christian Schabesberger 2016 <chris.schabesberger@mailbox.org>
* NavStack.java is part of NewPipe.
*
* NewPipe is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* NewPipe is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with NewPipe. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* class helps to navigate within the app
* IMPORTAND: the top of the stack is the current activity !!!
*/
public class NavStack {
private static final String TAG = NavStack.class.toString();
public static final String SERVICE_ID = "service_id";
public static final String URL = "url";
private static final String NAV_STACK="nav_stack";
private enum ActivityId {
CHANNEL,
DETAIL
}
private class NavEntry {
public NavEntry(String url, int serviceId) {
this.url = url;
this.serviceId = serviceId;
}
public String url;
public int serviceId;
}
private static NavStack instance = new NavStack();
private Stack<NavEntry> stack = new Stack<NavEntry>();
private NavStack() {
}
public static NavStack getInstance() {
return instance;
}
private void addEntry(String url, Class ac, int serviceId) {
stack.push(new NavEntry(url, serviceId));
}
public void navBack(Activity activity) throws Exception {
if(stack.size() == 0) { // if stack is already empty here, activity was probably called
// from another app
activity.finish();
return;
}
stack.pop(); // remove curent activty, since we dont want to return to itself
if (stack.size() == 0) {
openMainActivity(activity); // if no more page is on the stack this means we are home
return;
}
NavEntry entry = stack.pop(); // this element will reapear, since by calling the old page
// this element will be pushed on top again
try {
StreamingService service = NewPipe.getService(entry.serviceId);
switch (service.getLinkTypeByUrl(entry.url)) {
case STREAM:
openDetailActivity(activity, entry.url, entry.serviceId);
break;
case CHANNEL:
openChannelActivity(activity, entry.url, entry.serviceId);
break;
case NONE:
throw new Exception("Url not known to service. service="
+ Integer.toString(entry.serviceId) + " url=" + entry.url);
default:
openMainActivity(activity);
}
} catch (Exception e) {
e.printStackTrace();
}
}
public void openChannelActivity(Context context, String url, int serviceId) {
openActivity(context, url, serviceId, ChannelActivity.class);
}
public void openDetailActivity(Context context, String url, int serviceId) {
openActivity(context, url, serviceId, VideoItemDetailActivity.class);
}
private void openActivity(Context context, String url, int serviceId, Class acitivtyClass) {
stack.push(new NavEntry(url, serviceId));
Intent i = new Intent(context, acitivtyClass);
i.putExtra(SERVICE_ID, serviceId);
i.putExtra(URL, url);
context.startActivity(i);
}
public void openMainActivity(Activity a) {
stack.clear();
Intent i = new Intent(a, MainActivity.class);
i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
NavUtils.navigateUpTo(a, i);
}
public void onSaveInstanceState(Bundle state) {
ArrayList<String> sa = new ArrayList<>();
for(NavEntry entry : stack) {
sa.add(entry.url);
}
state.putStringArrayList(NAV_STACK, sa);
}
public void restoreSavedInstanceState(Bundle state) {
ArrayList<String> sa = state.getStringArrayList(NAV_STACK);
for(String url : sa) {
stack.push(new NavEntry(url, NewPipe.getServiceByUrl(url).getServiceId()));
}
}
}

View File

@ -2,12 +2,7 @@
<menu xmlns:android="http://schemas.android.com/apk/res/android" <menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"> xmlns:app="http://schemas.android.com/apk/res-auto">
<item android:id="@+id/action_settings" <item android:id="@+id/action_settings"
app:showAsAction="never" app:showAsAction="never"
android:title="@string/settings"/> android:title="@string/settings"/>
<item android:id="@+id/action_report_error"
app:showAsAction="never"
android:title="@string/report_error" />
</menu> </menu>