mirror of
https://github.com/TeamNewPipe/NewPipe
synced 2025-09-27 06:40:51 +02:00
Compare commits
93 Commits
v0.11.4
...
v0.11.6-be
Author | SHA1 | Date | |
---|---|---|---|
![]() |
f65f2da890 | ||
![]() |
30ab58c33d | ||
![]() |
87ba5a7eb6 | ||
![]() |
6e8593af91 | ||
![]() |
0ab1d3fc40 | ||
![]() |
f22d13e695 | ||
![]() |
cdde61a460 | ||
![]() |
989ce126f1 | ||
![]() |
28618e822e | ||
![]() |
6772381afc | ||
![]() |
75b45beabc | ||
![]() |
56d53e9b01 | ||
![]() |
3a8b04e2d1 | ||
![]() |
1ce7d66fb1 | ||
![]() |
7b5a9b69fe | ||
![]() |
837b22ccac | ||
![]() |
7146719393 | ||
![]() |
71ee604c69 | ||
![]() |
9945a5b813 | ||
![]() |
7254387042 | ||
![]() |
3a7f2a94a6 | ||
![]() |
6bea4aa96b | ||
![]() |
fa262bbceb | ||
![]() |
3139fe0170 | ||
![]() |
ef6c5de65b | ||
![]() |
07799563b5 | ||
![]() |
b1de4b7bd6 | ||
![]() |
2b8ae9a5ea | ||
![]() |
7c52d3ec5d | ||
![]() |
aefaa7619e | ||
![]() |
ca202290bf | ||
![]() |
cbdbc4cba2 | ||
![]() |
8abf904a78 | ||
![]() |
ecf7969c46 | ||
![]() |
a473e3d623 | ||
![]() |
1f8e90858e | ||
![]() |
2c2edca8fa | ||
![]() |
50e86ff1ca | ||
![]() |
02ecc5011a | ||
![]() |
6e666a018b | ||
![]() |
66fbb2ce1e | ||
![]() |
b00722ec0a | ||
![]() |
77b1413319 | ||
![]() |
87b8d60c9d | ||
![]() |
db5203e1ff | ||
![]() |
ea022670c4 | ||
![]() |
54b009cc49 | ||
![]() |
80c3acace9 | ||
![]() |
cea9428b47 | ||
![]() |
f8ffbfabbe | ||
![]() |
836a1e652b | ||
![]() |
d8544e0b84 | ||
![]() |
4817d7fddc | ||
![]() |
e6a385a85e | ||
![]() |
3634f68364 | ||
![]() |
f17ffa94fe | ||
![]() |
d52bcd46a1 | ||
![]() |
7e58b0b6fe | ||
![]() |
f451f1f65d | ||
![]() |
4d12e71fba | ||
![]() |
66fde7a212 | ||
![]() |
86eccf219d | ||
![]() |
677865f347 | ||
![]() |
eb4b3810e9 | ||
![]() |
5f26501ddf | ||
![]() |
b33a72f864 | ||
![]() |
675f43b968 | ||
![]() |
9f117a2e59 | ||
![]() |
a0844229a3 | ||
![]() |
114fcc144c | ||
![]() |
43372ff648 | ||
![]() |
b8ebbc5404 | ||
![]() |
28309f82f3 | ||
![]() |
c70fa391b6 | ||
![]() |
caab589dce | ||
![]() |
20370054e7 | ||
![]() |
f1882cb1e1 | ||
![]() |
2ed149852d | ||
![]() |
ac7226a0df | ||
![]() |
5705650ca8 | ||
![]() |
60855ca7c5 | ||
![]() |
b8d8d181f3 | ||
![]() |
6309160fc6 | ||
![]() |
fc0e6ed273 | ||
![]() |
f5f8371865 | ||
![]() |
1191455d37 | ||
![]() |
011e151c91 | ||
![]() |
54aa40eac1 | ||
![]() |
621a1909ec | ||
![]() |
25db3c2940 | ||
![]() |
442290d7f0 | ||
![]() |
a6eb871f5e | ||
![]() |
b500c3f526 |
@@ -8,8 +8,8 @@ android {
|
||||
applicationId "org.schabi.newpipe"
|
||||
minSdkVersion 15
|
||||
targetSdkVersion 27
|
||||
versionCode 45
|
||||
versionName "0.11.4"
|
||||
versionCode 47
|
||||
versionName "0.11.6"
|
||||
|
||||
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
|
||||
vectorDrawables.useSupportLibrary = true
|
||||
@@ -55,7 +55,7 @@ dependencies {
|
||||
exclude module: 'support-annotations'
|
||||
}
|
||||
|
||||
implementation 'com.github.TeamNewPipe:NewPipeExtractor:9de63f8c0a170a066'
|
||||
implementation 'com.github.TeamNewPipe:NewPipeExtractor:7fd21ec08581d'
|
||||
|
||||
testImplementation 'junit:junit:4.12'
|
||||
testImplementation 'org.mockito:mockito-core:1.10.19'
|
||||
|
@@ -16,7 +16,7 @@
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:label="@string/app_name"
|
||||
android:logo="@mipmap/ic_launcher"
|
||||
android:theme="@style/DarkTheme"
|
||||
android:theme="@style/OpeningTheme"
|
||||
tools:ignore="AllowBackup">
|
||||
<activity
|
||||
android:name=".MainActivity"
|
||||
@@ -31,7 +31,7 @@
|
||||
<activity
|
||||
android:name=".player.old.PlayVideoActivity"
|
||||
android:configChanges="orientation|keyboardHidden|screenSize"
|
||||
android:theme="@style/VideoPlayerTheme"
|
||||
android:theme="@style/OldVideoPlayerTheme"
|
||||
tools:ignore="UnusedAttribute"/>
|
||||
|
||||
<service
|
||||
@@ -56,8 +56,7 @@
|
||||
android:name=".player.MainVideoPlayer"
|
||||
android:configChanges="keyboard|keyboardHidden|orientation|screenSize"
|
||||
android:label="@string/app_name"
|
||||
android:launchMode="singleTask"
|
||||
android:theme="@style/PlayerTheme"/>
|
||||
android:launchMode="singleTask"/>
|
||||
|
||||
<activity
|
||||
android:name=".settings.SettingsActivity"
|
||||
@@ -124,7 +123,7 @@
|
||||
<activity
|
||||
android:name=".RouterActivity"
|
||||
android:taskAffinity=""
|
||||
android:theme="@android:style/Theme.NoDisplay">
|
||||
android:theme="@style/RouterActivityThemeDark">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.VIEW"/>
|
||||
<action android:name="android.media.action.MEDIA_PLAY_FROM_SEARCH"/>
|
||||
@@ -175,17 +174,21 @@
|
||||
</intent-filter>
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.SEND"/>
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT"/>
|
||||
|
||||
<data android:mimeType="text/plain"/>
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<service
|
||||
android:name=".RouterPlayerActivity$FetcherService"
|
||||
android:exported="false"/>
|
||||
|
||||
<activity
|
||||
android:name=".RouterPopupActivity"
|
||||
android:label="@string/popup_mode_share_menu_title"
|
||||
android:name=".RouterPlayerActivity"
|
||||
android:excludeFromRecents="true"
|
||||
android:label="@string/preferred_player_share_menu_title"
|
||||
android:taskAffinity=""
|
||||
android:theme="@style/PopupPermissionsTheme">
|
||||
android:theme="@style/RouterActivityThemeDark">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.VIEW"/>
|
||||
<action android:name="android.media.action.MEDIA_PLAY_FROM_SEARCH"/>
|
||||
@@ -204,6 +207,11 @@
|
||||
<data android:pathPrefix="/embed/"/>
|
||||
<data android:pathPrefix="/watch"/>
|
||||
<data android:pathPrefix="/attribution_link"/>
|
||||
<!-- channel prefix -->
|
||||
<data android:pathPrefix="/channel/"/>
|
||||
<data android:pathPrefix="/user/"/>
|
||||
<!-- playlist prefix -->
|
||||
<data android:pathPrefix="/playlist"/>
|
||||
</intent-filter>
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.VIEW"/>
|
||||
|
@@ -1,9 +1,12 @@
|
||||
package org.schabi.newpipe;
|
||||
|
||||
import android.app.AlarmManager;
|
||||
import android.app.Application;
|
||||
import android.app.NotificationChannel;
|
||||
import android.app.NotificationManager;
|
||||
import android.app.PendingIntent;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Build;
|
||||
import android.util.Log;
|
||||
|
||||
@@ -116,7 +119,6 @@ public class App extends Application {
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
private void initACRA() {
|
||||
try {
|
||||
final ACRAConfiguration acraConfig = new ConfigurationBuilder(this)
|
||||
@@ -149,4 +151,5 @@ public class App extends Application {
|
||||
NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
|
||||
mNotificationManager.createNotificationChannel(mChannel);
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -77,17 +77,6 @@ public abstract class BaseFragment extends Fragment {
|
||||
protected void initListeners() {
|
||||
}
|
||||
|
||||
/*//////////////////////////////////////////////////////////////////////////
|
||||
// Utils
|
||||
//////////////////////////////////////////////////////////////////////////*/
|
||||
|
||||
protected final int resolveResourceIdFromAttr(@AttrRes int attr) {
|
||||
TypedArray a = activity.getTheme().obtainStyledAttributes(new int[]{attr});
|
||||
int attributeResourceId = a.getResourceId(0, 0);
|
||||
a.recycle();
|
||||
return attributeResourceId;
|
||||
}
|
||||
|
||||
/*//////////////////////////////////////////////////////////////////////////
|
||||
// DisplayImageOptions default configurations
|
||||
//////////////////////////////////////////////////////////////////////////*/
|
||||
|
@@ -28,8 +28,12 @@ import android.os.Looper;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.design.widget.NavigationView;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.v4.view.GravityCompat;
|
||||
import android.support.v4.widget.DrawerLayout;
|
||||
import android.support.v7.app.ActionBar;
|
||||
import android.support.v7.app.ActionBarDrawerToggle;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.support.v7.widget.Toolbar;
|
||||
import android.util.Log;
|
||||
@@ -50,11 +54,13 @@ import org.schabi.newpipe.extractor.stream.AudioStream;
|
||||
import org.schabi.newpipe.extractor.stream.StreamInfo;
|
||||
import org.schabi.newpipe.extractor.stream.VideoStream;
|
||||
import org.schabi.newpipe.fragments.BackPressable;
|
||||
import org.schabi.newpipe.fragments.MainFragment;
|
||||
import org.schabi.newpipe.fragments.detail.VideoDetailFragment;
|
||||
import org.schabi.newpipe.fragments.list.search.SearchFragment;
|
||||
import org.schabi.newpipe.history.HistoryListener;
|
||||
import org.schabi.newpipe.util.Constants;
|
||||
import org.schabi.newpipe.util.NavigationHelper;
|
||||
import org.schabi.newpipe.util.ServiceHelper;
|
||||
import org.schabi.newpipe.util.StateSaver;
|
||||
import org.schabi.newpipe.util.ThemeHelper;
|
||||
|
||||
@@ -67,8 +73,10 @@ import io.reactivex.subjects.PublishSubject;
|
||||
|
||||
public class MainActivity extends AppCompatActivity implements HistoryListener {
|
||||
private static final String TAG = "MainActivity";
|
||||
public static final boolean DEBUG = false;
|
||||
public static final boolean DEBUG = !BuildConfig.BUILD_TYPE.equals("release");
|
||||
|
||||
private SharedPreferences sharedPreferences;
|
||||
private ActionBarDrawerToggle toggle = null;
|
||||
|
||||
/*//////////////////////////////////////////////////////////////////////////
|
||||
// Activity's LifeCycle
|
||||
@@ -77,7 +85,10 @@ public class MainActivity extends AppCompatActivity implements HistoryListener {
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
if (DEBUG) Log.d(TAG, "onCreate() called with: savedInstanceState = [" + savedInstanceState + "]");
|
||||
ThemeHelper.setTheme(this);
|
||||
|
||||
sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
|
||||
ThemeHelper.setTheme(this, ServiceHelper.getSelectedServiceId(this));
|
||||
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_main);
|
||||
|
||||
@@ -85,13 +96,53 @@ public class MainActivity extends AppCompatActivity implements HistoryListener {
|
||||
initFragments();
|
||||
}
|
||||
|
||||
Toolbar toolbar = findViewById(R.id.toolbar);
|
||||
setSupportActionBar(toolbar);
|
||||
sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
|
||||
|
||||
setSupportActionBar(findViewById(R.id.toolbar));
|
||||
setupDrawer();
|
||||
initHistory();
|
||||
}
|
||||
|
||||
private void setupDrawer() {
|
||||
final Toolbar toolbar = findViewById(R.id.toolbar);
|
||||
final DrawerLayout drawer = findViewById(R.id.drawer_layout);
|
||||
final NavigationView drawerItems = findViewById(R.id.navigation);
|
||||
|
||||
//drawerItems.setItemIconTintList(null); // Set null to use the original icon
|
||||
drawerItems.getMenu().getItem(ServiceHelper.getSelectedServiceId(this)).setChecked(true);
|
||||
|
||||
if (!BuildConfig.BUILD_TYPE.equals("release")) {
|
||||
toggle = new ActionBarDrawerToggle(this, drawer, toolbar, R.string.drawer_open, R.string.drawer_close);
|
||||
toggle.syncState();
|
||||
drawer.addDrawerListener(toggle);
|
||||
drawer.addDrawerListener(new DrawerLayout.SimpleDrawerListener() {
|
||||
private int lastService;
|
||||
|
||||
@Override
|
||||
public void onDrawerOpened(View drawerView) {
|
||||
lastService = ServiceHelper.getSelectedServiceId(MainActivity.this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDrawerClosed(View drawerView) {
|
||||
if (lastService != ServiceHelper.getSelectedServiceId(MainActivity.this)) {
|
||||
new Handler(Looper.getMainLooper()).post(MainActivity.this::recreate);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
drawerItems.setNavigationItemSelectedListener(item -> {
|
||||
if (item.getGroupId() == R.id.menu_services_group) {
|
||||
drawerItems.getMenu().getItem(ServiceHelper.getSelectedServiceId(this)).setChecked(false);
|
||||
ServiceHelper.setSelectedServiceId(this, item.getTitle().toString());
|
||||
drawerItems.getMenu().getItem(ServiceHelper.getSelectedServiceId(this)).setChecked(true);
|
||||
}
|
||||
drawer.closeDrawers();
|
||||
return true;
|
||||
});
|
||||
} else {
|
||||
drawer.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
@@ -112,20 +163,14 @@ public class MainActivity extends AppCompatActivity implements HistoryListener {
|
||||
sharedPreferences.edit().putBoolean(Constants.KEY_THEME_CHANGE, false).apply();
|
||||
// https://stackoverflow.com/questions/10844112/runtimeexception-performing-pause-of-activity-that-is-not-resumed
|
||||
// Briefly, let the activity resume properly posting the recreate call to end of the message queue
|
||||
new Handler(Looper.getMainLooper()).post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
MainActivity.this.recreate();
|
||||
}
|
||||
});
|
||||
new Handler(Looper.getMainLooper()).post(MainActivity.this::recreate);
|
||||
}
|
||||
|
||||
if(sharedPreferences.getBoolean(Constants.KEY_MAIN_PAGE_CHANGE, false)) {
|
||||
if (sharedPreferences.getBoolean(Constants.KEY_MAIN_PAGE_CHANGE, false)) {
|
||||
if (DEBUG) Log.d(TAG, "main page has changed, recreating main fragment...");
|
||||
sharedPreferences.edit().putBoolean(Constants.KEY_MAIN_PAGE_CHANGE, false).apply();
|
||||
NavigationHelper.openMainActivity(this);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -159,6 +204,38 @@ public class MainActivity extends AppCompatActivity implements HistoryListener {
|
||||
} else super.onBackPressed();
|
||||
}
|
||||
|
||||
/**
|
||||
* Implement the following diagram behavior for the up button:
|
||||
* <pre>
|
||||
* +---------------+
|
||||
* | Main Screen +----+
|
||||
* +-------+-------+ |
|
||||
* | |
|
||||
* ▲ Up | Search Button
|
||||
* | |
|
||||
* +----+-----+ |
|
||||
* +------------+ Search |◄-----+
|
||||
* | +----+-----+
|
||||
* | Open |
|
||||
* | something ▲ Up
|
||||
* | |
|
||||
* | +------------+-------------+
|
||||
* | | |
|
||||
* | | Video <-> Channel |
|
||||
* +---►| Channel <-> Playlist |
|
||||
* | Video <-> .... |
|
||||
* | |
|
||||
* +--------------------------+
|
||||
* </pre>
|
||||
*/
|
||||
private void onHomeButtonPressed() {
|
||||
// If search fragment wasn't found in the backstack...
|
||||
if (!NavigationHelper.tryGotoSearchFragment(getSupportFragmentManager())) {
|
||||
// ...go to the main fragment
|
||||
NavigationHelper.gotoMainFragment(getSupportFragmentManager());
|
||||
}
|
||||
}
|
||||
|
||||
/*//////////////////////////////////////////////////////////////////////////
|
||||
// Menu
|
||||
//////////////////////////////////////////////////////////////////////////*/
|
||||
@@ -184,6 +261,9 @@ public class MainActivity extends AppCompatActivity implements HistoryListener {
|
||||
if (actionBar != null) {
|
||||
actionBar.setDisplayHomeAsUpEnabled(false);
|
||||
}
|
||||
|
||||
updateDrawerNavigation();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -194,7 +274,7 @@ public class MainActivity extends AppCompatActivity implements HistoryListener {
|
||||
|
||||
switch (id) {
|
||||
case android.R.id.home:
|
||||
NavigationHelper.gotoMainFragment(getSupportFragmentManager());
|
||||
onHomeButtonPressed();
|
||||
return true;
|
||||
case R.id.action_settings:
|
||||
NavigationHelper.openSettings(this);
|
||||
@@ -228,6 +308,27 @@ public class MainActivity extends AppCompatActivity implements HistoryListener {
|
||||
// Utils
|
||||
//////////////////////////////////////////////////////////////////////////*/
|
||||
|
||||
private void updateDrawerNavigation() {
|
||||
if (getSupportActionBar() == null) return;
|
||||
|
||||
final Toolbar toolbar = findViewById(R.id.toolbar);
|
||||
final DrawerLayout drawer = findViewById(R.id.drawer_layout);
|
||||
|
||||
final Fragment fragment = getSupportFragmentManager().findFragmentById(R.id.fragment_holder);
|
||||
if (fragment instanceof MainFragment) {
|
||||
getSupportActionBar().setDisplayHomeAsUpEnabled(false);
|
||||
if (toggle != null) {
|
||||
toggle.syncState();
|
||||
toolbar.setNavigationOnClickListener(v -> drawer.openDrawer(GravityCompat.START));
|
||||
drawer.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNDEFINED);
|
||||
}
|
||||
} else {
|
||||
drawer.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED);
|
||||
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
|
||||
toolbar.setNavigationOnClickListener(v -> onHomeButtonPressed());
|
||||
}
|
||||
}
|
||||
|
||||
private void handleIntent(Intent intent) {
|
||||
if (DEBUG) Log.d(TAG, "handleIntent() called with: intent = [" + intent + "]");
|
||||
|
||||
|
@@ -3,14 +3,25 @@ package org.schabi.newpipe;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.text.TextUtils;
|
||||
import android.widget.Toast;
|
||||
|
||||
import org.schabi.newpipe.extractor.exceptions.ExtractionException;
|
||||
import org.schabi.newpipe.report.UserAction;
|
||||
import org.schabi.newpipe.util.ExtractorHelper;
|
||||
import org.schabi.newpipe.util.NavigationHelper;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
|
||||
/**
|
||||
import icepick.Icepick;
|
||||
import icepick.State;
|
||||
import io.reactivex.Observable;
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||
import io.reactivex.disposables.CompositeDisposable;
|
||||
import io.reactivex.schedulers.Schedulers;
|
||||
|
||||
/*
|
||||
* Copyright (C) Christian Schabesberger 2017 <chris.schabesberger@mailbox.org>
|
||||
* RouterActivity.java is part of NewPipe.
|
||||
*
|
||||
@@ -34,23 +45,71 @@ import java.util.HashSet;
|
||||
*/
|
||||
public class RouterActivity extends AppCompatActivity {
|
||||
|
||||
@State
|
||||
protected String currentUrl;
|
||||
protected CompositeDisposable disposables = new CompositeDisposable();
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
Icepick.restoreInstanceState(this, savedInstanceState);
|
||||
|
||||
String videoUrl = getUrl(getIntent());
|
||||
handleUrl(videoUrl);
|
||||
if (TextUtils.isEmpty(currentUrl)) {
|
||||
currentUrl = getUrl(getIntent());
|
||||
|
||||
if (TextUtils.isEmpty(currentUrl)) {
|
||||
Toast.makeText(this, R.string.invalid_url_toast, Toast.LENGTH_LONG).show();
|
||||
finish();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSaveInstanceState(Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
Icepick.saveInstanceState(this, outState);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStart() {
|
||||
super.onStart();
|
||||
handleUrl(currentUrl);
|
||||
}
|
||||
|
||||
protected void handleUrl(String url) {
|
||||
boolean success = NavigationHelper.openByLink(this, url);
|
||||
if (!success) {
|
||||
disposables.add(Observable
|
||||
.fromCallable(() -> NavigationHelper.getIntentByLink(this, url))
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(intent -> {
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
|
||||
startActivity(intent);
|
||||
|
||||
finish();
|
||||
}, this::handleError)
|
||||
);
|
||||
}
|
||||
|
||||
protected void handleError(Throwable error) {
|
||||
error.printStackTrace();
|
||||
|
||||
if (error instanceof ExtractionException) {
|
||||
Toast.makeText(this, R.string.url_not_supported_toast, Toast.LENGTH_LONG).show();
|
||||
} else {
|
||||
ExtractorHelper.handleGeneralException(this, -1, null, error, UserAction.SOMETHING_ELSE, null);
|
||||
}
|
||||
|
||||
finish();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
|
||||
disposables.clear();
|
||||
}
|
||||
|
||||
/*//////////////////////////////////////////////////////////////////////////
|
||||
// Utils
|
||||
//////////////////////////////////////////////////////////////////////////*/
|
||||
@@ -71,7 +130,8 @@ public class RouterActivity extends AppCompatActivity {
|
||||
} else if (intent.getStringExtra(Intent.EXTRA_TEXT) != null) {
|
||||
//this means that vidoe was called through share menu
|
||||
String extraText = intent.getStringExtra(Intent.EXTRA_TEXT);
|
||||
videoUrl = getUris(extraText)[0];
|
||||
final String[] uris = getUris(extraText);
|
||||
videoUrl = uris.length > 0 ? uris[0] : null;
|
||||
}
|
||||
|
||||
return videoUrl;
|
||||
|
413
app/src/main/java/org/schabi/newpipe/RouterPlayerActivity.java
Normal file
413
app/src/main/java/org/schabi/newpipe/RouterPlayerActivity.java
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,49 +0,0 @@
|
||||
package org.schabi.newpipe;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.os.Build;
|
||||
import android.widget.Toast;
|
||||
|
||||
import org.schabi.newpipe.extractor.NewPipe;
|
||||
import org.schabi.newpipe.extractor.StreamingService;
|
||||
import org.schabi.newpipe.extractor.exceptions.ExtractionException;
|
||||
import org.schabi.newpipe.player.PopupVideoPlayer;
|
||||
import org.schabi.newpipe.util.Constants;
|
||||
import org.schabi.newpipe.util.PermissionHelper;
|
||||
|
||||
/**
|
||||
* Get the url from the intent and open a popup player
|
||||
*/
|
||||
public class RouterPopupActivity extends RouterActivity {
|
||||
|
||||
@Override
|
||||
protected void handleUrl(String url) {
|
||||
if (!PermissionHelper.isPopupEnabled(this)) {
|
||||
PermissionHelper.showPopupEnablementToast(this);
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
StreamingService service;
|
||||
try {
|
||||
service = NewPipe.getServiceByUrl(url);
|
||||
} catch (ExtractionException e) {
|
||||
Toast.makeText(this, R.string.url_not_supported_toast, Toast.LENGTH_LONG).show();
|
||||
return;
|
||||
}
|
||||
|
||||
Intent callIntent = new Intent(this, PopupVideoPlayer.class);
|
||||
switch (service.getLinkTypeByUrl(url)) {
|
||||
case STREAM:
|
||||
break;
|
||||
default:
|
||||
Toast.makeText(this, R.string.url_not_supported_toast, Toast.LENGTH_LONG).show();
|
||||
return;
|
||||
}
|
||||
|
||||
callIntent.putExtra(Constants.KEY_URL, url);
|
||||
callIntent.putExtra(Constants.KEY_SERVICE_ID, service.getServiceId());
|
||||
startService(callIntent);
|
||||
|
||||
finish();
|
||||
}
|
||||
}
|
@@ -19,7 +19,6 @@ import org.schabi.newpipe.MainActivity;
|
||||
import org.schabi.newpipe.R;
|
||||
import org.schabi.newpipe.ReCaptchaActivity;
|
||||
import org.schabi.newpipe.extractor.exceptions.ReCaptchaException;
|
||||
import org.schabi.newpipe.extractor.stream.StreamInfo;
|
||||
import org.schabi.newpipe.report.ErrorActivity;
|
||||
import org.schabi.newpipe.report.UserAction;
|
||||
import org.schabi.newpipe.util.ExtractorHelper;
|
||||
@@ -247,6 +246,12 @@ public abstract class BaseStateFragment<I> extends BaseFragment implements ViewC
|
||||
// Utils
|
||||
//////////////////////////////////////////////////////////////////////////*/
|
||||
|
||||
public void setTitle(String title) {
|
||||
if (DEBUG) Log.d(TAG, "setTitle() called with: title = [" + title + "]");
|
||||
if (activity != null && activity.getSupportActionBar() != null) {
|
||||
activity.getSupportActionBar().setTitle(title);
|
||||
}
|
||||
}
|
||||
|
||||
protected void openUrlInBrowser(String url) {
|
||||
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
|
||||
|
@@ -23,6 +23,7 @@ import android.view.ViewGroup;
|
||||
import org.schabi.newpipe.BaseFragment;
|
||||
import org.schabi.newpipe.R;
|
||||
import org.schabi.newpipe.extractor.NewPipe;
|
||||
import org.schabi.newpipe.extractor.ServiceList;
|
||||
import org.schabi.newpipe.extractor.StreamingService;
|
||||
import org.schabi.newpipe.extractor.kiosk.KioskList;
|
||||
import org.schabi.newpipe.fragments.list.channel.ChannelFragment;
|
||||
@@ -33,23 +34,20 @@ import org.schabi.newpipe.report.ErrorActivity;
|
||||
import org.schabi.newpipe.report.UserAction;
|
||||
import org.schabi.newpipe.util.KioskTranslator;
|
||||
import org.schabi.newpipe.util.NavigationHelper;
|
||||
import org.schabi.newpipe.util.ServiceHelper;
|
||||
import org.schabi.newpipe.util.ThemeHelper;
|
||||
|
||||
public class MainFragment extends BaseFragment implements TabLayout.OnTabSelectedListener {
|
||||
private ViewPager viewPager;
|
||||
private boolean showBlankTab = false;
|
||||
|
||||
public int currentServiceId = -1;
|
||||
|
||||
private ViewPager viewPager;
|
||||
|
||||
/*//////////////////////////////////////////////////////////////////////////
|
||||
// Constants
|
||||
//////////////////////////////////////////////////////////////////////////*/
|
||||
|
||||
|
||||
private static final int FALLBACK_SERVICE_ID = 0; // Youtube
|
||||
private static final String FALLBACK_CHANNEL_URL =
|
||||
"https://www.youtube.com/channel/UC-9-kyTW8ZkZNDHQJ6FgpwQ";
|
||||
private static final int FALLBACK_SERVICE_ID = ServiceList.YouTube.getId();
|
||||
private static final String FALLBACK_CHANNEL_URL = "https://www.youtube.com/channel/UC-9-kyTW8ZkZNDHQJ6FgpwQ";
|
||||
private static final String FALLBACK_CHANNEL_NAME = "Music";
|
||||
private static final String FALLBACK_KIOSK_ID = "Trending";
|
||||
private static final int KIOSK_MENU_OFFSET = 2000;
|
||||
@@ -66,8 +64,7 @@ public class MainFragment extends BaseFragment implements TabLayout.OnTabSelecte
|
||||
|
||||
@Override
|
||||
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
|
||||
currentServiceId = Integer.parseInt(PreferenceManager.getDefaultSharedPreferences(getActivity())
|
||||
.getString(getString(R.string.current_service_key), "0"));
|
||||
currentServiceId = ServiceHelper.getSelectedServiceId(activity);
|
||||
return inflater.inflate(R.layout.fragment_main, container, false);
|
||||
}
|
||||
|
||||
@@ -85,22 +82,10 @@ public class MainFragment extends BaseFragment implements TabLayout.OnTabSelecte
|
||||
|
||||
tabLayout.setupWithViewPager(viewPager);
|
||||
|
||||
int channelIcon;
|
||||
int whatsHotIcon;
|
||||
int channelIcon = ThemeHelper.resolveResourceIdFromAttr(activity, R.attr.ic_channel);
|
||||
int whatsHotIcon = ThemeHelper.resolveResourceIdFromAttr(activity, R.attr.ic_hot);
|
||||
|
||||
if (ThemeHelper.isLightThemeSelected(getActivity())) {
|
||||
tabLayout.setBackgroundColor(getResources().getColor(R.color.light_youtube_primary_color));
|
||||
channelIcon = R.drawable.ic_channel_black_24dp;
|
||||
whatsHotIcon = R.drawable.ic_whatshot_black_24dp;
|
||||
} else {
|
||||
channelIcon = R.drawable.ic_channel_white_24dp;
|
||||
whatsHotIcon = R.drawable.ic_whatshot_white_24dp;
|
||||
}
|
||||
|
||||
|
||||
if (PreferenceManager.getDefaultSharedPreferences(getActivity())
|
||||
.getString(getString(R.string.main_page_content_key), getString(R.string.blank_page_key))
|
||||
.equals(getString(R.string.subscription_page_key))) {
|
||||
if (isSubscriptionsPageOnlySelected()) {
|
||||
tabLayout.getTabAt(0).setIcon(channelIcon);
|
||||
} else {
|
||||
tabLayout.getTabAt(0).setIcon(whatsHotIcon);
|
||||
@@ -138,7 +123,7 @@ public class MainFragment extends BaseFragment implements TabLayout.OnTabSelecte
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
switch (item.getItemId()) {
|
||||
case R.id.action_search:
|
||||
NavigationHelper.openSearchFragment(getFragmentManager(), 0, "");
|
||||
NavigationHelper.openSearchFragment(getFragmentManager(), ServiceHelper.getSelectedServiceId(activity), "");
|
||||
return true;
|
||||
}
|
||||
return super.onOptionsItemSelected(item);
|
||||
@@ -163,11 +148,6 @@ public class MainFragment extends BaseFragment implements TabLayout.OnTabSelecte
|
||||
|
||||
private class PagerAdapter extends FragmentPagerAdapter {
|
||||
|
||||
private int[] tabTitles = new int[]{
|
||||
R.string.tab_main,
|
||||
R.string.tab_subscriptions
|
||||
};
|
||||
|
||||
PagerAdapter(FragmentManager fm) {
|
||||
super(fm);
|
||||
}
|
||||
@@ -176,13 +156,7 @@ public class MainFragment extends BaseFragment implements TabLayout.OnTabSelecte
|
||||
public Fragment getItem(int position) {
|
||||
switch (position) {
|
||||
case 0:
|
||||
if(PreferenceManager.getDefaultSharedPreferences(getActivity())
|
||||
.getString(getString(R.string.main_page_content_key), getString(R.string.blank_page_key))
|
||||
.equals(getString(R.string.subscription_page_key))) {
|
||||
return new SubscriptionFragment();
|
||||
} else {
|
||||
return getMainPageFragment();
|
||||
}
|
||||
return isSubscriptionsPageOnlySelected() ? new SubscriptionFragment() : getMainPageFragment();
|
||||
case 1:
|
||||
return new SubscriptionFragment();
|
||||
default:
|
||||
@@ -198,13 +172,7 @@ public class MainFragment extends BaseFragment implements TabLayout.OnTabSelecte
|
||||
|
||||
@Override
|
||||
public int getCount() {
|
||||
if(PreferenceManager.getDefaultSharedPreferences(getActivity())
|
||||
.getString(getString(R.string.main_page_content_key), getString(R.string.blank_page_key))
|
||||
.equals(getString(R.string.subscription_page_key))) {
|
||||
return 1;
|
||||
} else {
|
||||
return 2;
|
||||
}
|
||||
return isSubscriptionsPageOnlySelected() ? 1 : 2;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -212,28 +180,33 @@ public class MainFragment extends BaseFragment implements TabLayout.OnTabSelecte
|
||||
// Main page content
|
||||
//////////////////////////////////////////////////////////////////////////*/
|
||||
|
||||
private boolean isSubscriptionsPageOnlySelected() {
|
||||
return PreferenceManager.getDefaultSharedPreferences(activity)
|
||||
.getString(getString(R.string.main_page_content_key), getString(R.string.blank_page_key))
|
||||
.equals(getString(R.string.subscription_page_key));
|
||||
}
|
||||
|
||||
private Fragment getMainPageFragment() {
|
||||
try {
|
||||
SharedPreferences preferences =
|
||||
PreferenceManager.getDefaultSharedPreferences(getActivity());
|
||||
final String setMainPage = preferences.getString(getString(R.string.main_page_content_key),
|
||||
getString(R.string.main_page_selectd_kiosk_id));
|
||||
if(setMainPage.equals(getString(R.string.blank_page_key))) {
|
||||
getString(R.string.main_page_selectd_kiosk_id));
|
||||
if (setMainPage.equals(getString(R.string.blank_page_key))) {
|
||||
return new BlankFragment();
|
||||
} else if(setMainPage.equals(getString(R.string.kiosk_page_key))) {
|
||||
} else if (setMainPage.equals(getString(R.string.kiosk_page_key))) {
|
||||
int serviceId = preferences.getInt(getString(R.string.main_page_selected_service),
|
||||
FALLBACK_SERVICE_ID);
|
||||
String kioskId = preferences.getString(getString(R.string.main_page_selectd_kiosk_id),
|
||||
FALLBACK_KIOSK_ID);
|
||||
KioskFragment fragment = KioskFragment.getInstance(serviceId, kioskId
|
||||
);
|
||||
KioskFragment fragment = KioskFragment.getInstance(serviceId, kioskId);
|
||||
fragment.useAsFrontPage(true);
|
||||
return fragment;
|
||||
} else if(setMainPage.equals(getString(R.string.feed_page_key))) {
|
||||
} else if (setMainPage.equals(getString(R.string.feed_page_key))) {
|
||||
FeedFragment fragment = new FeedFragment();
|
||||
fragment.useAsFrontPage(true);
|
||||
return fragment;
|
||||
} else if(setMainPage.equals(getString(R.string.channel_page_key))) {
|
||||
} else if (setMainPage.equals(getString(R.string.channel_page_key))) {
|
||||
int serviceId = preferences.getInt(getString(R.string.main_page_selected_service),
|
||||
FALLBACK_SERVICE_ID);
|
||||
String url = preferences.getString(getString(R.string.main_page_selected_channel_url),
|
||||
@@ -266,7 +239,7 @@ public class MainFragment extends BaseFragment implements TabLayout.OnTabSelecte
|
||||
StreamingService service = NewPipe.getService(currentServiceId);
|
||||
KioskList kl = service.getKioskList();
|
||||
int i = 0;
|
||||
for(final String ks : kl.getAvailableKiosks()) {
|
||||
for (final String ks : kl.getAvailableKiosks()) {
|
||||
menu.add(0, KIOSK_MENU_OFFSET + i, Menu.NONE,
|
||||
KioskTranslator.getTranslatedKioskName(ks, getContext()))
|
||||
.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
|
||||
|
@@ -13,7 +13,6 @@ import android.support.annotation.DrawableRes;
|
||||
import android.support.annotation.FloatRange;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.v4.content.ContextCompat;
|
||||
import android.support.v4.text.TextUtilsCompat;
|
||||
import android.support.v4.view.animation.FastOutSlowInInterpolator;
|
||||
import android.support.v7.app.ActionBar;
|
||||
import android.support.v7.app.AlertDialog;
|
||||
@@ -25,7 +24,6 @@ import android.text.util.Linkify;
|
||||
import android.util.DisplayMetrics;
|
||||
import android.util.Log;
|
||||
import android.util.TypedValue;
|
||||
import android.view.Gravity;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuInflater;
|
||||
@@ -37,7 +35,6 @@ import android.widget.FrameLayout;
|
||||
import android.widget.ImageButton;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.PopupMenu;
|
||||
import android.widget.RelativeLayout;
|
||||
import android.widget.Spinner;
|
||||
import android.widget.TextView;
|
||||
@@ -51,7 +48,6 @@ import org.schabi.newpipe.R;
|
||||
import org.schabi.newpipe.ReCaptchaActivity;
|
||||
import org.schabi.newpipe.download.DownloadDialog;
|
||||
import org.schabi.newpipe.extractor.InfoItem;
|
||||
import org.schabi.newpipe.extractor.MediaFormat;
|
||||
import org.schabi.newpipe.extractor.NewPipe;
|
||||
import org.schabi.newpipe.extractor.exceptions.ContentNotAvailableException;
|
||||
import org.schabi.newpipe.extractor.exceptions.ParsingException;
|
||||
@@ -80,6 +76,7 @@ import org.schabi.newpipe.util.ListHelper;
|
||||
import org.schabi.newpipe.util.Localization;
|
||||
import org.schabi.newpipe.util.NavigationHelper;
|
||||
import org.schabi.newpipe.util.PermissionHelper;
|
||||
import org.schabi.newpipe.util.ThemeHelper;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
@@ -342,7 +339,11 @@ public class VideoDetailFragment extends BaseStateFragment<StreamInfo> implement
|
||||
}
|
||||
break;
|
||||
case R.id.detail_thumbnail_root_layout:
|
||||
openVideoPlayer();
|
||||
if (currentInfo.video_streams.isEmpty() && currentInfo.video_only_streams.isEmpty()) {
|
||||
openBackgroundPlayer(false);
|
||||
} else {
|
||||
openVideoPlayer();
|
||||
}
|
||||
break;
|
||||
case R.id.detail_title_root_layout:
|
||||
toggleTitleAndDescription();
|
||||
@@ -390,7 +391,7 @@ public class VideoDetailFragment extends BaseStateFragment<StreamInfo> implement
|
||||
|
||||
if (relatedStreamsView.getChildCount() > initialCount) {
|
||||
relatedStreamsView.removeViews(initialCount, relatedStreamsView.getChildCount() - (initialCount));
|
||||
relatedStreamExpandButton.setImageDrawable(ContextCompat.getDrawable(activity, resolveResourceIdFromAttr(R.attr.expand)));
|
||||
relatedStreamExpandButton.setImageDrawable(ContextCompat.getDrawable(activity, ThemeHelper.resolveResourceIdFromAttr(activity, R.attr.expand)));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -400,7 +401,7 @@ public class VideoDetailFragment extends BaseStateFragment<StreamInfo> implement
|
||||
//Log.d(TAG, "i = " + i);
|
||||
relatedStreamsView.addView(infoItemBuilder.buildView(relatedStreamsView, item));
|
||||
}
|
||||
relatedStreamExpandButton.setImageDrawable(ContextCompat.getDrawable(activity, resolveResourceIdFromAttr(R.attr.collapse)));
|
||||
relatedStreamExpandButton.setImageDrawable(ContextCompat.getDrawable(activity, ThemeHelper.resolveResourceIdFromAttr(activity, R.attr.collapse)));
|
||||
}
|
||||
|
||||
/*//////////////////////////////////////////////////////////////////////////
|
||||
@@ -575,7 +576,7 @@ public class VideoDetailFragment extends BaseStateFragment<StreamInfo> implement
|
||||
relatedStreamRootLayout.setVisibility(View.VISIBLE);
|
||||
relatedStreamExpandButton.setVisibility(View.VISIBLE);
|
||||
|
||||
relatedStreamExpandButton.setImageDrawable(ContextCompat.getDrawable(activity, resolveResourceIdFromAttr(R.attr.expand)));
|
||||
relatedStreamExpandButton.setImageDrawable(ContextCompat.getDrawable(activity, ThemeHelper.resolveResourceIdFromAttr(activity, R.attr.expand)));
|
||||
} else {
|
||||
if (info.getNextVideo() == null) relatedStreamRootLayout.setVisibility(View.GONE);
|
||||
relatedStreamExpandButton.setVisibility(View.GONE);
|
||||
@@ -803,7 +804,7 @@ public class VideoDetailFragment extends BaseStateFragment<StreamInfo> implement
|
||||
if (!useExternalAudioPlayer && android.os.Build.VERSION.SDK_INT >= 16) {
|
||||
openNormalBackgroundPlayer(append);
|
||||
} else {
|
||||
openExternalBackgroundPlayer(audioStream);
|
||||
NavigationHelper.playOnExternalPlayer(activity, currentInfo.getName(), currentInfo.getUploaderName(), audioStream);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -837,13 +838,12 @@ public class VideoDetailFragment extends BaseStateFragment<StreamInfo> implement
|
||||
}
|
||||
|
||||
if (PreferenceManager.getDefaultSharedPreferences(activity).getBoolean(this.getString(R.string.use_external_video_player_key), false)) {
|
||||
openExternalVideoPlayer(selectedVideoStream);
|
||||
NavigationHelper.playOnExternalPlayer(activity, currentInfo.getName(), currentInfo.getUploaderName(), selectedVideoStream);
|
||||
} else {
|
||||
openNormalPlayer(selectedVideoStream);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void openNormalBackgroundPlayer(final boolean append) {
|
||||
final PlayQueue itemQueue = new SinglePlayQueue(currentInfo);
|
||||
if (append) {
|
||||
@@ -853,40 +853,6 @@ public class VideoDetailFragment extends BaseStateFragment<StreamInfo> implement
|
||||
}
|
||||
}
|
||||
|
||||
private void openExternalBackgroundPlayer(AudioStream audioStream) {
|
||||
Intent intent;
|
||||
intent = new Intent();
|
||||
try {
|
||||
intent.setAction(Intent.ACTION_VIEW);
|
||||
intent.setDataAndType(Uri.parse(audioStream.getUrl()), audioStream.getFormat().getMimeType());
|
||||
intent.putExtra(Intent.EXTRA_TITLE, currentInfo.getName());
|
||||
intent.putExtra("title", currentInfo.getName());
|
||||
activity.startActivity(intent);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(activity);
|
||||
builder.setMessage(R.string.no_player_found)
|
||||
.setPositiveButton(R.string.install, new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
Intent intent = new Intent();
|
||||
intent.setAction(Intent.ACTION_VIEW);
|
||||
intent.setData(Uri.parse(activity.getString(R.string.fdroid_vlc_url)));
|
||||
activity.startActivity(intent);
|
||||
}
|
||||
})
|
||||
.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
Log.i(TAG, "You unlocked a secret unicorn.");
|
||||
}
|
||||
});
|
||||
builder.create().show();
|
||||
Log.e(TAG, "Either no Streaming player for audio was installed, or something important crashed:");
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private void openNormalPlayer(VideoStream selectedVideoStream) {
|
||||
Intent mIntent;
|
||||
boolean useOldPlayer = PlayerHelper.isUsingOldPlayer(activity) || (Build.VERSION.SDK_INT < 16);
|
||||
@@ -905,33 +871,6 @@ public class VideoDetailFragment extends BaseStateFragment<StreamInfo> implement
|
||||
startActivity(mIntent);
|
||||
}
|
||||
|
||||
private void openExternalVideoPlayer(VideoStream selectedVideoStream) {
|
||||
// External Player
|
||||
Intent intent = new Intent();
|
||||
try {
|
||||
intent.setAction(Intent.ACTION_VIEW)
|
||||
.setDataAndType(Uri.parse(selectedVideoStream.getUrl()), selectedVideoStream.getFormat().getMimeType())
|
||||
.putExtra(Intent.EXTRA_TITLE, currentInfo.getName())
|
||||
.putExtra("title", currentInfo.getName());
|
||||
this.startActivity(intent);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(activity);
|
||||
builder.setMessage(R.string.no_player_found)
|
||||
.setPositiveButton(R.string.install, new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
Intent intent = new Intent()
|
||||
.setAction(Intent.ACTION_VIEW)
|
||||
.setData(Uri.parse(getString(R.string.fdroid_vlc_url)));
|
||||
startActivity(intent);
|
||||
}
|
||||
})
|
||||
.setNegativeButton(R.string.cancel, null);
|
||||
builder.create().show();
|
||||
}
|
||||
}
|
||||
|
||||
/*//////////////////////////////////////////////////////////////////////////
|
||||
// Utils
|
||||
//////////////////////////////////////////////////////////////////////////*/
|
||||
@@ -1158,6 +1097,13 @@ public class VideoDetailFragment extends BaseStateFragment<StreamInfo> implement
|
||||
showSnackBarError(info.getErrors(), UserAction.REQUESTED_STREAM, NewPipe.getNameOfService(info.getServiceId()), info.getUrl(), 0);
|
||||
}
|
||||
|
||||
if (info.video_streams.isEmpty() && info.video_only_streams.isEmpty()) {
|
||||
detailControlsBackground.setVisibility(View.GONE);
|
||||
detailControlsPopup.setVisibility(View.GONE);
|
||||
spinnerToolbar.setVisibility(View.GONE);
|
||||
thumbnailPlayButton.setImageResource(R.drawable.ic_headset_white_24dp);
|
||||
}
|
||||
|
||||
if (autoPlayEnabled) {
|
||||
openVideoPlayer();
|
||||
// Only auto play in the first open
|
||||
|
@@ -84,17 +84,6 @@ public abstract class BaseListInfoFragment<I extends ListInfo> extends BaseListF
|
||||
currentNextItemsUrl = (String) savedObjects.poll();
|
||||
}
|
||||
|
||||
/*//////////////////////////////////////////////////////////////////////////
|
||||
// Utils
|
||||
//////////////////////////////////////////////////////////////////////////*/
|
||||
|
||||
public void setTitle(String title) {
|
||||
Log.d(TAG, "setTitle() called with: title = [" + title + "]");
|
||||
if (activity.getSupportActionBar() != null) {
|
||||
activity.getSupportActionBar().setTitle(title);
|
||||
}
|
||||
}
|
||||
|
||||
/*//////////////////////////////////////////////////////////////////////////
|
||||
// Load and handle
|
||||
//////////////////////////////////////////////////////////////////////////*/
|
||||
@@ -124,20 +113,12 @@ public abstract class BaseListInfoFragment<I extends ListInfo> extends BaseListF
|
||||
currentWorker = loadResult(forceLoad)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(new Consumer<I>() {
|
||||
@Override
|
||||
public void accept(@NonNull I result) throws Exception {
|
||||
isLoading.set(false);
|
||||
currentInfo = result;
|
||||
currentNextItemsUrl = result.next_streams_url;
|
||||
handleResult(result);
|
||||
}
|
||||
}, new Consumer<Throwable>() {
|
||||
@Override
|
||||
public void accept(@NonNull Throwable throwable) throws Exception {
|
||||
onError(throwable);
|
||||
}
|
||||
});
|
||||
.subscribe((@NonNull I result) -> {
|
||||
isLoading.set(false);
|
||||
currentInfo = result;
|
||||
currentNextItemsUrl = result.next_streams_url;
|
||||
handleResult(result);
|
||||
}, (@NonNull Throwable throwable) -> onError(throwable));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -153,18 +134,12 @@ public abstract class BaseListInfoFragment<I extends ListInfo> extends BaseListF
|
||||
currentWorker = loadMoreItemsLogic()
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(new Consumer<ListExtractor.NextItemsResult>() {
|
||||
@Override
|
||||
public void accept(@io.reactivex.annotations.NonNull ListExtractor.NextItemsResult nextItemsResult) throws Exception {
|
||||
isLoading.set(false);
|
||||
handleNextItems(nextItemsResult);
|
||||
}
|
||||
}, new Consumer<Throwable>() {
|
||||
@Override
|
||||
public void accept(@io.reactivex.annotations.NonNull Throwable throwable) throws Exception {
|
||||
isLoading.set(false);
|
||||
onError(throwable);
|
||||
}
|
||||
.subscribe((@io.reactivex.annotations.NonNull ListExtractor.NextItemsResult nextItemsResult) -> {
|
||||
isLoading.set(false);
|
||||
handleNextItems(nextItemsResult);
|
||||
}, (@io.reactivex.annotations.NonNull Throwable throwable) -> {
|
||||
isLoading.set(false);
|
||||
onError(throwable);
|
||||
});
|
||||
}
|
||||
|
||||
|
@@ -43,7 +43,6 @@ import org.schabi.newpipe.util.AnimationUtils;
|
||||
import org.schabi.newpipe.util.ExtractorHelper;
|
||||
import org.schabi.newpipe.util.Localization;
|
||||
import org.schabi.newpipe.util.NavigationHelper;
|
||||
import org.schabi.newpipe.util.PermissionHelper;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
@@ -102,11 +101,7 @@ public class ChannelFragment extends BaseListInfoFragment<ChannelInfo> {
|
||||
if(activity != null
|
||||
&& useAsFrontPage
|
||||
&& isVisibleToUser) {
|
||||
try {
|
||||
activity.getSupportActionBar().setTitle(currentInfo.getName());
|
||||
} catch (Exception e) {
|
||||
onError(e);
|
||||
}
|
||||
setTitle(currentInfo != null ? currentInfo.getName() : name);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -57,6 +57,7 @@ public class KioskFragment extends BaseListInfoFragment<KioskInfo> {
|
||||
|
||||
@State
|
||||
protected String kioskId = "";
|
||||
protected String kioskTranslatedName;
|
||||
|
||||
/*//////////////////////////////////////////////////////////////////////////
|
||||
// Views
|
||||
@@ -87,16 +88,11 @@ public class KioskFragment extends BaseListInfoFragment<KioskInfo> {
|
||||
//////////////////////////////////////////////////////////////////////////*/
|
||||
|
||||
@Override
|
||||
public void onActivityCreated(Bundle savedState) {
|
||||
super.onActivityCreated(savedState);
|
||||
try {
|
||||
activity.getSupportActionBar()
|
||||
.setTitle(KioskTranslator.getTranslatedKioskName(kioskId, getActivity()));
|
||||
} catch (Exception e) {
|
||||
onUnrecoverableError(e, UserAction.UI_ERROR,
|
||||
"none",
|
||||
"none", R.string.app_ui_crash);
|
||||
}
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
kioskTranslatedName = KioskTranslator.getTranslatedKioskName(kioskId, activity);
|
||||
name = kioskTranslatedName;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -104,8 +100,7 @@ public class KioskFragment extends BaseListInfoFragment<KioskInfo> {
|
||||
super.setUserVisibleHint(isVisibleToUser);
|
||||
if(useAsFrontPage && isVisibleToUser && activity != null) {
|
||||
try {
|
||||
activity.getSupportActionBar()
|
||||
.setTitle(KioskTranslator.getTranslatedKioskName(kioskId, getActivity()));
|
||||
setTitle(kioskTranslatedName);
|
||||
} catch (Exception e) {
|
||||
onUnrecoverableError(e, UserAction.UI_ERROR,
|
||||
"none",
|
||||
@@ -115,11 +110,8 @@ public class KioskFragment extends BaseListInfoFragment<KioskInfo> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
|
||||
View view = inflater.inflate(R.layout.fragment_kiosk, container, false);
|
||||
activity.getSupportActionBar()
|
||||
.setTitle(KioskTranslator.getTranslatedKioskName(kioskId, getActivity()));
|
||||
return view;
|
||||
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
|
||||
return inflater.inflate(R.layout.fragment_kiosk, container, false);
|
||||
}
|
||||
|
||||
/*//////////////////////////////////////////////////////////////////////////
|
||||
@@ -171,9 +163,8 @@ public class KioskFragment extends BaseListInfoFragment<KioskInfo> {
|
||||
public void handleResult(@NonNull final KioskInfo result) {
|
||||
super.handleResult(result);
|
||||
|
||||
String title = KioskTranslator.getTranslatedKioskName(result.id, getActivity());
|
||||
ActionBar supportActionBar = activity.getSupportActionBar();
|
||||
supportActionBar.setTitle(title);
|
||||
name = kioskTranslatedName;
|
||||
setTitle(kioskTranslatedName);
|
||||
|
||||
if (!result.getErrors().isEmpty()) {
|
||||
showSnackBarError(result.getErrors(),
|
||||
|
@@ -4,6 +4,7 @@ import android.content.Intent;
|
||||
import android.view.MenuItem;
|
||||
|
||||
import org.schabi.newpipe.R;
|
||||
import org.schabi.newpipe.util.PermissionHelper;
|
||||
|
||||
import static org.schabi.newpipe.player.BackgroundPlayer.ACTION_CLOSE;
|
||||
|
||||
@@ -48,6 +49,12 @@ public final class BackgroundPlayerActivity extends ServicePlayerActivity {
|
||||
@Override
|
||||
public boolean onPlayerOptionSelected(MenuItem item) {
|
||||
if (item.getItemId() == R.id.action_switch_popup) {
|
||||
|
||||
if (!PermissionHelper.isPopupEnabled(this)) {
|
||||
PermissionHelper.showPopupEnablementToast(this);
|
||||
return true;
|
||||
}
|
||||
|
||||
this.player.setRecovery();
|
||||
getApplicationContext().sendBroadcast(getPlayerShutdownIntent());
|
||||
getApplicationContext().startService(getSwitchIntent(PopupVideoPlayer.class));
|
||||
|
@@ -111,6 +111,7 @@ public abstract class BasePlayer implements Player.EventListener, PlaybackListen
|
||||
public static final String PLAYBACK_QUALITY = "playback_quality";
|
||||
public static final String PLAY_QUEUE = "play_queue";
|
||||
public static final String APPEND_ONLY = "append_only";
|
||||
public static final String SELECT_ON_APPEND = "select_on_append";
|
||||
|
||||
/*//////////////////////////////////////////////////////////////////////////
|
||||
// Playback
|
||||
@@ -218,7 +219,13 @@ public abstract class BasePlayer implements Player.EventListener, PlaybackListen
|
||||
|
||||
// Resolve append intents
|
||||
if (intent.getBooleanExtra(APPEND_ONLY, false) && playQueue != null) {
|
||||
int sizeBeforeAppend = playQueue.size();
|
||||
playQueue.append(queue.getStreams());
|
||||
|
||||
if (intent.getBooleanExtra(SELECT_ON_APPEND, false) && queue.getStreams().size() > 0) {
|
||||
playQueue.setIndex(sizeBeforeAppend);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@@ -37,7 +37,6 @@ import android.support.v7.widget.RecyclerView;
|
||||
import android.support.v7.widget.helper.ItemTouchHelper;
|
||||
import android.util.Log;
|
||||
import android.view.GestureDetector;
|
||||
import android.view.MenuItem;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.view.WindowManager;
|
||||
@@ -62,10 +61,9 @@ import org.schabi.newpipe.util.AnimationUtils;
|
||||
import org.schabi.newpipe.util.ListHelper;
|
||||
import org.schabi.newpipe.util.NavigationHelper;
|
||||
import org.schabi.newpipe.util.PermissionHelper;
|
||||
import org.schabi.newpipe.util.PopupMenuIconHacker;
|
||||
import org.schabi.newpipe.util.ThemeHelper;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.List;
|
||||
|
||||
import static org.schabi.newpipe.util.AnimationUtils.animateView;
|
||||
@@ -326,7 +324,7 @@ public final class MainVideoPlayer extends Activity {
|
||||
this.playNextButton = rootView.findViewById(R.id.playNextButton);
|
||||
this.moreOptionsButton = rootView.findViewById(R.id.moreOptionsButton);
|
||||
this.moreOptionsPopupMenu = new PopupMenu(context, moreOptionsButton);
|
||||
this.moreOptionsPopupMenu.getMenuInflater().inflate(R.menu.menu_videooptions, moreOptionsPopupMenu.getMenu());
|
||||
buildMoreOptionsMenu();
|
||||
|
||||
titleTextView.setSelected(true);
|
||||
channelTextView.setSelected(true);
|
||||
@@ -379,7 +377,7 @@ public final class MainVideoPlayer extends Activity {
|
||||
titleTextView.setText(getVideoTitle());
|
||||
channelTextView.setText(getUploaderName());
|
||||
|
||||
playPauseButton.setImageResource(R.drawable.ic_pause_white);
|
||||
//playPauseButton.setImageResource(R.drawable.ic_pause_white);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -399,9 +397,8 @@ public final class MainVideoPlayer extends Activity {
|
||||
if (DEBUG) Log.d(TAG, "onFullScreenButtonClicked() called");
|
||||
if (simpleExoPlayer == null) return;
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M
|
||||
&& !PermissionHelper.checkSystemAlertWindowPermission(MainVideoPlayer.this)) {
|
||||
Toast.makeText(MainVideoPlayer.this, R.string.msg_popup_permission, Toast.LENGTH_LONG).show();
|
||||
if (!PermissionHelper.isPopupEnabled(context)) {
|
||||
PermissionHelper.showPopupEnablementToast(context);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -499,25 +496,7 @@ public final class MainVideoPlayer extends Activity {
|
||||
|
||||
private void onMoreOptionsClicked() {
|
||||
if (DEBUG) Log.d(TAG, "onMoreOptionsClicked() called");
|
||||
buildMoreOptionsMenu();
|
||||
|
||||
try {
|
||||
Field[] fields = moreOptionsPopupMenu.getClass().getDeclaredFields();
|
||||
for (Field field : fields) {
|
||||
if ("mPopup".equals(field.getName())) {
|
||||
field.setAccessible(true);
|
||||
Object menuPopupHelper = field.get(moreOptionsPopupMenu);
|
||||
Class<?> classPopupHelper = Class.forName(menuPopupHelper
|
||||
.getClass().getName());
|
||||
Method setForceIcons = classPopupHelper.getMethod(
|
||||
"setForceShowIcon", boolean.class);
|
||||
setForceIcons.invoke(menuPopupHelper, true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
moreOptionsPopupMenu.show();
|
||||
isSomePopupMenuVisible = true;
|
||||
showControls(300);
|
||||
@@ -659,7 +638,9 @@ public final class MainVideoPlayer extends Activity {
|
||||
}
|
||||
|
||||
private void buildMoreOptionsMenu() {
|
||||
if (moreOptionsPopupMenu == null) return;
|
||||
this.moreOptionsPopupMenu.getMenuInflater().inflate(R.menu.menu_videooptions,
|
||||
moreOptionsPopupMenu.getMenu());
|
||||
|
||||
moreOptionsPopupMenu.setOnMenuItemClickListener(menuItem -> {
|
||||
switch (menuItem.getItemId()) {
|
||||
case R.id.toggleOrientation:
|
||||
@@ -674,6 +655,22 @@ public final class MainVideoPlayer extends Activity {
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
try {
|
||||
PopupMenuIconHacker.setShowPopupIcon(moreOptionsPopupMenu);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
// fix icon theme
|
||||
if(ThemeHelper.isLightThemeSelected(MainVideoPlayer.this)) {
|
||||
moreOptionsPopupMenu.getMenu()
|
||||
.findItem(R.id.toggleOrientation)
|
||||
.setIcon(R.drawable.ic_screen_rotation_black_24dp);
|
||||
moreOptionsPopupMenu.getMenu()
|
||||
.findItem(R.id.switchPopup)
|
||||
.setIcon(R.drawable.ic_fullscreen_exit_black_24dp);
|
||||
}
|
||||
}
|
||||
|
||||
private void buildQueue() {
|
||||
|
@@ -31,7 +31,6 @@ import android.content.res.Configuration;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.PixelFormat;
|
||||
import android.os.Build;
|
||||
import android.os.Handler;
|
||||
import android.os.IBinder;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.support.annotation.NonNull;
|
||||
@@ -49,20 +48,12 @@ import android.widget.PopupMenu;
|
||||
import android.widget.RemoteViews;
|
||||
import android.widget.SeekBar;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.google.android.exoplayer2.PlaybackParameters;
|
||||
import com.google.android.exoplayer2.Player;
|
||||
|
||||
import org.schabi.newpipe.BuildConfig;
|
||||
import org.schabi.newpipe.MainActivity;
|
||||
import org.schabi.newpipe.R;
|
||||
import org.schabi.newpipe.ReCaptchaActivity;
|
||||
import org.schabi.newpipe.extractor.NewPipe;
|
||||
import org.schabi.newpipe.extractor.exceptions.ContentNotAvailableException;
|
||||
import org.schabi.newpipe.extractor.exceptions.ParsingException;
|
||||
import org.schabi.newpipe.extractor.exceptions.ReCaptchaException;
|
||||
import org.schabi.newpipe.extractor.services.youtube.YoutubeStreamExtractor;
|
||||
import org.schabi.newpipe.extractor.stream.StreamInfo;
|
||||
import org.schabi.newpipe.extractor.stream.VideoStream;
|
||||
import org.schabi.newpipe.player.event.PlayerEventListener;
|
||||
@@ -70,22 +61,12 @@ import org.schabi.newpipe.player.helper.LockManager;
|
||||
import org.schabi.newpipe.player.helper.PlayerHelper;
|
||||
import org.schabi.newpipe.player.old.PlayVideoActivity;
|
||||
import org.schabi.newpipe.playlist.PlayQueueItem;
|
||||
import org.schabi.newpipe.playlist.SinglePlayQueue;
|
||||
import org.schabi.newpipe.report.ErrorActivity;
|
||||
import org.schabi.newpipe.report.UserAction;
|
||||
import org.schabi.newpipe.util.Constants;
|
||||
import org.schabi.newpipe.util.ExtractorHelper;
|
||||
import org.schabi.newpipe.util.ListHelper;
|
||||
import org.schabi.newpipe.util.NavigationHelper;
|
||||
import org.schabi.newpipe.util.ThemeHelper;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||
import io.reactivex.disposables.Disposable;
|
||||
import io.reactivex.schedulers.Schedulers;
|
||||
|
||||
import static org.schabi.newpipe.player.helper.PlayerHelper.isUsingOldPlayer;
|
||||
import static org.schabi.newpipe.util.AnimationUtils.animateView;
|
||||
|
||||
@@ -125,8 +106,8 @@ public final class PopupVideoPlayer extends Service {
|
||||
private RemoteViews notRemoteView;
|
||||
|
||||
private VideoPlayerImpl playerImpl;
|
||||
private Disposable currentWorker;
|
||||
private LockManager lockManager;
|
||||
|
||||
/*//////////////////////////////////////////////////////////////////////////
|
||||
// Service-Activity Binder
|
||||
//////////////////////////////////////////////////////////////////////////*/
|
||||
@@ -157,21 +138,8 @@ public final class PopupVideoPlayer extends Service {
|
||||
if (playerImpl.getPlayer() == null) initPopup();
|
||||
if (!playerImpl.isPlaying()) playerImpl.getPlayer().setPlayWhenReady(true);
|
||||
|
||||
if (intent != null && intent.getStringExtra(Constants.KEY_URL) != null) {
|
||||
final int serviceId = intent.getIntExtra(Constants.KEY_SERVICE_ID, 0);
|
||||
final String url = intent.getStringExtra(Constants.KEY_URL);
|
||||
playerImpl.handleIntent(intent);
|
||||
|
||||
playerImpl.setStartedFromNewPipe(false);
|
||||
|
||||
final FetcherHandler fetcherRunnable = new FetcherHandler(this, serviceId, url);
|
||||
currentWorker = ExtractorHelper.getStreamInfo(serviceId,url,false)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(fetcherRunnable::onReceive, fetcherRunnable::onError);
|
||||
} else {
|
||||
playerImpl.setStartedFromNewPipe(true);
|
||||
playerImpl.handleIntent(intent);
|
||||
}
|
||||
return START_NOT_STICKY;
|
||||
}
|
||||
|
||||
@@ -302,7 +270,6 @@ public final class PopupVideoPlayer extends Service {
|
||||
}
|
||||
if (lockManager != null) lockManager.releaseWifiAndCpu();
|
||||
if (notificationManager != null) notificationManager.cancel(NOTIFICATION_ID);
|
||||
if (currentWorker != null) currentWorker.dispose();
|
||||
mBinder = null;
|
||||
playerImpl = null;
|
||||
|
||||
@@ -452,7 +419,6 @@ public final class PopupVideoPlayer extends Service {
|
||||
this.getPlaybackPitch(),
|
||||
this.getPlaybackQuality()
|
||||
);
|
||||
if (!isStartedFromNewPipe()) intent.putExtra(VideoPlayer.STARTED_FROM_NEWPIPE, false);
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
} else {
|
||||
intent = new Intent(PopupVideoPlayer.this, PlayVideoActivity.class)
|
||||
@@ -862,63 +828,4 @@ public final class PopupVideoPlayer extends Service {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetcher handler used if open by a link out of NewPipe
|
||||
*/
|
||||
private class FetcherHandler {
|
||||
private final int serviceId;
|
||||
private final String url;
|
||||
|
||||
private final Context context;
|
||||
private final Handler mainHandler;
|
||||
|
||||
private FetcherHandler(Context context, int serviceId, String url) {
|
||||
this.mainHandler = new Handler(PopupVideoPlayer.this.getMainLooper());
|
||||
this.context = context;
|
||||
this.url = url;
|
||||
this.serviceId = serviceId;
|
||||
}
|
||||
|
||||
private void onReceive(final StreamInfo info) {
|
||||
mainHandler.post(() -> {
|
||||
final Intent intent = NavigationHelper.getPlayerIntent(getApplicationContext(),
|
||||
PopupVideoPlayer.class, new SinglePlayQueue(info));
|
||||
playerImpl.handleIntent(intent);
|
||||
});
|
||||
}
|
||||
|
||||
private void onError(final Throwable exception) {
|
||||
if (DEBUG) Log.d(TAG, "onError() called with: exception = [" + exception + "]");
|
||||
exception.printStackTrace();
|
||||
mainHandler.post(() -> {
|
||||
if (exception instanceof ReCaptchaException) {
|
||||
onReCaptchaException();
|
||||
} else if (exception instanceof IOException) {
|
||||
Toast.makeText(context, R.string.network_error, Toast.LENGTH_LONG).show();
|
||||
} else if (exception instanceof YoutubeStreamExtractor.GemaException) {
|
||||
Toast.makeText(context, R.string.blocked_by_gema, Toast.LENGTH_LONG).show();
|
||||
} else if (exception instanceof YoutubeStreamExtractor.LiveStreamException) {
|
||||
Toast.makeText(context, R.string.live_streams_not_supported, Toast.LENGTH_LONG).show();
|
||||
} else if (exception instanceof ContentNotAvailableException) {
|
||||
Toast.makeText(context, R.string.content_not_available, Toast.LENGTH_LONG).show();
|
||||
} else {
|
||||
int errorId = exception instanceof YoutubeStreamExtractor.DecryptException ? R.string.youtube_signature_decryption_error :
|
||||
exception instanceof ParsingException ? R.string.parsing_error : R.string.general_error;
|
||||
ErrorActivity.reportError(mainHandler, context, exception, MainActivity.class, null, ErrorActivity.ErrorInfo.make(UserAction.REQUESTED_STREAM, NewPipe.getNameOfService(serviceId), url, errorId));
|
||||
}
|
||||
});
|
||||
stopSelf();
|
||||
}
|
||||
|
||||
private void onReCaptchaException() {
|
||||
Toast.makeText(context, R.string.recaptcha_request_toast, Toast.LENGTH_LONG).show();
|
||||
// Starting ReCaptcha Challenge Activity
|
||||
Intent intent = new Intent(context, ReCaptchaActivity.class);
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
context.startActivity(intent);
|
||||
stopSelf();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@@ -183,7 +183,7 @@ public abstract class ServicePlayerActivity extends AppCompatActivity
|
||||
this.player.getPlaybackSpeed(),
|
||||
this.player.getPlaybackPitch(),
|
||||
null
|
||||
);
|
||||
).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
}
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Service Connection
|
||||
|
@@ -39,7 +39,6 @@ import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.SurfaceView;
|
||||
import android.view.View;
|
||||
import android.widget.ImageButton;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.PopupMenu;
|
||||
import android.widget.ProgressBar;
|
||||
@@ -85,12 +84,6 @@ public abstract class VideoPlayer extends BasePlayer
|
||||
public static final boolean DEBUG = BasePlayer.DEBUG;
|
||||
public final String TAG;
|
||||
|
||||
/*//////////////////////////////////////////////////////////////////////////
|
||||
// Intent
|
||||
//////////////////////////////////////////////////////////////////////////*/
|
||||
|
||||
public static final String STARTED_FROM_NEWPIPE = "started_from_newpipe";
|
||||
|
||||
/*//////////////////////////////////////////////////////////////////////////
|
||||
// Player
|
||||
//////////////////////////////////////////////////////////////////////////*/
|
||||
@@ -102,7 +95,6 @@ public abstract class VideoPlayer extends BasePlayer
|
||||
|
||||
protected String playbackQuality;
|
||||
|
||||
private boolean startedFromNewPipe = true;
|
||||
protected boolean wasPlaying = false;
|
||||
|
||||
/*//////////////////////////////////////////////////////////////////////////
|
||||
@@ -695,14 +687,6 @@ public abstract class VideoPlayer extends BasePlayer
|
||||
return availableStreams.get(selectedStreamIndex);
|
||||
}
|
||||
|
||||
public boolean isStartedFromNewPipe() {
|
||||
return startedFromNewPipe;
|
||||
}
|
||||
|
||||
public void setStartedFromNewPipe(boolean startedFromNewPipe) {
|
||||
this.startedFromNewPipe = startedFromNewPipe;
|
||||
}
|
||||
|
||||
public Handler getControlsVisibilityHandler() {
|
||||
return controlsVisibilityHandler;
|
||||
}
|
||||
|
@@ -15,6 +15,10 @@ public final class ChannelPlayQueue extends AbstractInfoPlayQueue<ChannelInfo, C
|
||||
super(item);
|
||||
}
|
||||
|
||||
public ChannelPlayQueue(final ChannelInfo info) {
|
||||
this(info.getServiceId(), info.getUrl(), info.getNextStreamsUrl(), info.getRelatedStreams(), 0);
|
||||
}
|
||||
|
||||
public ChannelPlayQueue(final int serviceId,
|
||||
final String url,
|
||||
final String nextPageUrl,
|
||||
|
@@ -15,6 +15,10 @@ public final class PlaylistPlayQueue extends AbstractInfoPlayQueue<PlaylistInfo,
|
||||
super(item);
|
||||
}
|
||||
|
||||
public PlaylistPlayQueue(final PlaylistInfo info) {
|
||||
this(info.getServiceId(), info.getUrl(), info.getNextStreamsUrl(), info.getRelatedStreams(), 0);
|
||||
}
|
||||
|
||||
public PlaylistPlayQueue(final int serviceId,
|
||||
final String url,
|
||||
final String nextPageUrl,
|
||||
|
@@ -44,6 +44,7 @@ import java.io.StringWriter;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.TimeZone;
|
||||
import java.util.Vector;
|
||||
|
||||
@@ -144,12 +145,7 @@ public class ErrorActivity extends AppCompatActivity {
|
||||
// async call
|
||||
public static void reportError(Handler handler, final Context context, final List<Throwable> el,
|
||||
final Class returnActivity, final View rootView, final ErrorInfo errorInfo) {
|
||||
handler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
reportError(context, el, returnActivity, rootView, errorInfo);
|
||||
}
|
||||
});
|
||||
handler.post(() -> reportError(context, el, returnActivity, rootView, errorInfo));
|
||||
}
|
||||
|
||||
public static void reportError(final Context context, final CrashReportData report, final ErrorInfo errorInfo) {
|
||||
@@ -218,17 +214,13 @@ public class ErrorActivity extends AppCompatActivity {
|
||||
addGuruMeditaion();
|
||||
currentTimeStamp = getCurrentTimeStamp();
|
||||
|
||||
reportButton.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
reportButton.setOnClickListener((View v) -> {
|
||||
Intent i = new Intent(Intent.ACTION_SENDTO);
|
||||
i.setData(Uri.parse("mailto:" + ERROR_EMAIL_ADDRESS))
|
||||
.putExtra(Intent.EXTRA_SUBJECT, ERROR_EMAIL_SUBJECT)
|
||||
.putExtra(Intent.EXTRA_TEXT, buildJson());
|
||||
|
||||
Intent intent = new Intent(Intent.ACTION_SENDTO);
|
||||
intent.setData(Uri.parse("mailto:" + ERROR_EMAIL_ADDRESS))
|
||||
.putExtra(Intent.EXTRA_SUBJECT, ERROR_EMAIL_SUBJECT)
|
||||
.putExtra(Intent.EXTRA_TEXT, buildJson());
|
||||
|
||||
startActivity(Intent.createChooser(intent, "Send Email"));
|
||||
}
|
||||
startActivity(Intent.createChooser(i, "Send Email"));
|
||||
});
|
||||
reportButton.setEnabled(false);
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -46,7 +46,8 @@ public class DownloadSettingsFragment extends BasePreferenceFragment {
|
||||
Log.d(TAG, "onPreferenceTreeClick() called with: preference = [" + preference + "]");
|
||||
}
|
||||
|
||||
if (preference.getKey().equals(DOWNLOAD_PATH_PREFERENCE) || preference.getKey().equals(DOWNLOAD_PATH_AUDIO_PREFERENCE)) {
|
||||
if (preference.getKey().equals(DOWNLOAD_PATH_PREFERENCE)
|
||||
|| preference.getKey().equals(DOWNLOAD_PATH_AUDIO_PREFERENCE)) {
|
||||
Intent i = new Intent(getActivity(), FilePickerActivityHelper.class)
|
||||
.putExtra(FilePickerActivityHelper.EXTRA_ALLOW_MULTIPLE, false)
|
||||
.putExtra(FilePickerActivityHelper.EXTRA_ALLOW_CREATE_DIR, true)
|
||||
|
@@ -14,21 +14,17 @@ import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import org.schabi.newpipe.R;
|
||||
import org.schabi.newpipe.database.subscription.SubscriptionEntity;
|
||||
import org.schabi.newpipe.extractor.NewPipe;
|
||||
import org.schabi.newpipe.extractor.ServiceList;
|
||||
import org.schabi.newpipe.extractor.StreamingService;
|
||||
import org.schabi.newpipe.fragments.subscription.SubscriptionService;
|
||||
import org.schabi.newpipe.report.ErrorActivity;
|
||||
import org.schabi.newpipe.report.UserAction;
|
||||
import org.schabi.newpipe.util.KioskTranslator;
|
||||
import org.schabi.newpipe.util.ServiceIconMapper;
|
||||
import org.schabi.newpipe.util.ServiceHelper;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Vector;
|
||||
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||
import io.reactivex.schedulers.Schedulers;
|
||||
|
||||
/**
|
||||
* Created by Christian Schabesberger on 09.10.17.
|
||||
* SelectKioskFragment.java is part of NewPipe.
|
||||
@@ -125,13 +121,15 @@ public class SelectKioskFragment extends DialogFragment {
|
||||
throws Exception {
|
||||
|
||||
for(StreamingService service : NewPipe.getServices()) {
|
||||
//TODO: Multi-service support
|
||||
if (service.getServiceId() != ServiceList.YouTube.getId()) continue;
|
||||
|
||||
for(String kioskId : service.getKioskList().getAvailableKiosks()) {
|
||||
String name = String.format(getString(R.string.service_kiosk_string),
|
||||
service.getServiceInfo().name,
|
||||
KioskTranslator.getTranslatedKioskName(kioskId, getContext()));
|
||||
kioskList.add(new Entry(
|
||||
//ServiceIconMapper.getIconResource(service.getServiceId()),
|
||||
ServiceIconMapper.getIconResource(-1),
|
||||
ServiceHelper.getIcon(service.getServiceId()),
|
||||
service.getServiceId(),
|
||||
kioskId,
|
||||
name));
|
||||
@@ -140,9 +138,7 @@ public class SelectKioskFragment extends DialogFragment {
|
||||
}
|
||||
|
||||
public int getItemCount() {
|
||||
//todo: uncommend this line on multyservice support
|
||||
//return kioskList.size();
|
||||
return 1;
|
||||
return kioskList.size();
|
||||
}
|
||||
|
||||
public SelectKioskItemHolder onCreateViewHolder(ViewGroup parent, int type) {
|
||||
|
@@ -43,7 +43,8 @@ public class SettingsActivity extends AppCompatActivity implements BasePreferenc
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceBundle) {
|
||||
ThemeHelper.setTheme(this);
|
||||
setTheme(ThemeHelper.getSettingsThemeStyle(this));
|
||||
|
||||
super.onCreate(savedInstanceBundle);
|
||||
setContentView(R.layout.settings_layout);
|
||||
|
||||
@@ -72,7 +73,9 @@ public class SettingsActivity extends AppCompatActivity implements BasePreferenc
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
int id = item.getItemId();
|
||||
if (id == android.R.id.home) {
|
||||
finish();
|
||||
if (getSupportFragmentManager().getBackStackEntryCount() == 0) {
|
||||
finish();
|
||||
} else getSupportFragmentManager().popBackStack();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -20,7 +20,6 @@ import org.schabi.newpipe.R;
|
||||
public class PermissionHelper {
|
||||
public static final int PERMISSION_WRITE_STORAGE = 778;
|
||||
public static final int PERMISSION_READ_STORAGE = 777;
|
||||
public static final int PERMISSION_SYSTEM_ALERT_WINDOW = 779;
|
||||
|
||||
|
||||
public static boolean checkStoragePermissions(Activity activity) {
|
||||
@@ -80,27 +79,25 @@ public class PermissionHelper {
|
||||
* In order to be able to draw over other apps, the permission android.permission.SYSTEM_ALERT_WINDOW have to be granted.
|
||||
* <p>
|
||||
* On < API 23 (MarshMallow) the permission was granted when the user installed the application (via AndroidManifest),
|
||||
* on > 23, however, it have to start a activity asking the user if he agree.
|
||||
* on > 23, however, it have to start a activity asking the user if he agrees.
|
||||
* <p>
|
||||
* This method just return if canDraw over other apps, if it doesn't, try to get the permission,
|
||||
* it does not get the result of the startActivityForResult, if the user accept, the next time that he tries to open
|
||||
* it will return true.
|
||||
* This method just return if the app has permission to draw over other apps, and if it doesn't, it will try to get the permission.
|
||||
*
|
||||
* @param activity context to startActivityForResult
|
||||
* @return returns {@link Settings#canDrawOverlays(Context)}
|
||||
**/
|
||||
@RequiresApi(api = Build.VERSION_CODES.M)
|
||||
public static boolean checkSystemAlertWindowPermission(Activity activity) {
|
||||
if (!Settings.canDrawOverlays(activity)) {
|
||||
Intent i = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, Uri.parse("package:" + activity.getPackageName()));
|
||||
activity.startActivityForResult(i, PERMISSION_SYSTEM_ALERT_WINDOW);
|
||||
public static boolean checkSystemAlertWindowPermission(Context context) {
|
||||
if (!Settings.canDrawOverlays(context)) {
|
||||
Intent i = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, Uri.parse("package:" + context.getPackageName()));
|
||||
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
context.startActivity(i);
|
||||
return false;
|
||||
}else return true;
|
||||
}
|
||||
|
||||
public static boolean isPopupEnabled(Activity activity) {
|
||||
public static boolean isPopupEnabled(Context context) {
|
||||
return Build.VERSION.SDK_INT < Build.VERSION_CODES.M ||
|
||||
PermissionHelper.checkSystemAlertWindowPermission(activity);
|
||||
PermissionHelper.checkSystemAlertWindowPermission(context);
|
||||
}
|
||||
|
||||
public static void showPopupEnablementToast(Context context) {
|
||||
|
@@ -0,0 +1,48 @@
|
||||
package org.schabi.newpipe.util;
|
||||
|
||||
import android.widget.PopupMenu;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
/**
|
||||
* Created by Christian Schabesberger on 20.01.18.
|
||||
* Copyright 2018 Christian Schabesberger <chris.schabesberger@mailbox.org>
|
||||
* PopupMenuIconHacker.java is part of NewPipe
|
||||
*
|
||||
* License: GPL-3.0+
|
||||
* This program 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.
|
||||
*
|
||||
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
public class PopupMenuIconHacker {
|
||||
public static void setShowPopupIcon(PopupMenu menu) throws Exception {
|
||||
try {
|
||||
Field[] fields = menu.getClass().getDeclaredFields();
|
||||
for (Field field : fields) {
|
||||
if ("mPopup".equals(field.getName())) {
|
||||
field.setAccessible(true);
|
||||
Object menuPopupHelper = field.get(menu);
|
||||
Class<?> classPopupHelper = Class.forName(menuPopupHelper
|
||||
.getClass().getName());
|
||||
Method setForceIcons = classPopupHelper.getMethod(
|
||||
"setForceShowIcon", boolean.class);
|
||||
setForceIcons.invoke(menuPopupHelper, true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new Exception("Could not make Popup menu show Icons", e);
|
||||
}
|
||||
}
|
||||
}
|
67
app/src/main/java/org/schabi/newpipe/util/ServiceHelper.java
Normal file
67
app/src/main/java/org/schabi/newpipe/util/ServiceHelper.java
Normal file
@@ -0,0 +1,67 @@
|
||||
package org.schabi.newpipe.util;
|
||||
|
||||
import android.content.Context;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.support.annotation.DrawableRes;
|
||||
|
||||
import org.schabi.newpipe.BuildConfig;
|
||||
import org.schabi.newpipe.R;
|
||||
import org.schabi.newpipe.extractor.NewPipe;
|
||||
import org.schabi.newpipe.extractor.ServiceList;
|
||||
import org.schabi.newpipe.extractor.StreamingService;
|
||||
import org.schabi.newpipe.extractor.exceptions.ExtractionException;
|
||||
|
||||
public class ServiceHelper {
|
||||
private static final StreamingService DEFAULT_FALLBACK_SERVICE = ServiceList.YouTube.getService();
|
||||
|
||||
@DrawableRes
|
||||
public static int getIcon(int serviceId) {
|
||||
switch (serviceId) {
|
||||
case 0:
|
||||
return R.drawable.place_holder_youtube;
|
||||
case 1:
|
||||
return R.drawable.place_holder_circle;
|
||||
default:
|
||||
return R.drawable.service;
|
||||
}
|
||||
}
|
||||
|
||||
public static int getSelectedServiceId(Context context) {
|
||||
if (BuildConfig.BUILD_TYPE.equals("release")) return DEFAULT_FALLBACK_SERVICE.getServiceId();
|
||||
|
||||
final String serviceName = PreferenceManager.getDefaultSharedPreferences(context)
|
||||
.getString(context.getString(R.string.current_service_key), context.getString(R.string.default_service_value));
|
||||
|
||||
int serviceId;
|
||||
try {
|
||||
serviceId = NewPipe.getService(serviceName).getServiceId();
|
||||
} catch (ExtractionException e) {
|
||||
serviceId = DEFAULT_FALLBACK_SERVICE.getServiceId();
|
||||
}
|
||||
|
||||
return serviceId;
|
||||
}
|
||||
|
||||
public static void setSelectedServiceId(Context context, int serviceId) {
|
||||
String serviceName;
|
||||
try {
|
||||
serviceName = NewPipe.getService(serviceId).getServiceInfo().name;
|
||||
} catch (ExtractionException e) {
|
||||
serviceName = DEFAULT_FALLBACK_SERVICE.getServiceInfo().name;
|
||||
}
|
||||
|
||||
setSelectedServicePreferences(context, serviceName);
|
||||
}
|
||||
|
||||
public static void setSelectedServiceId(Context context, String serviceName) {
|
||||
int serviceId = NewPipe.getIdOfService(serviceName);
|
||||
if (serviceId == -1) serviceName = DEFAULT_FALLBACK_SERVICE.getServiceInfo().name;
|
||||
|
||||
setSelectedServicePreferences(context, serviceName);
|
||||
}
|
||||
|
||||
private static void setSelectedServicePreferences(Context context, String serviceName) {
|
||||
PreferenceManager.getDefaultSharedPreferences(context).edit().
|
||||
putString(context.getString(R.string.current_service_key), serviceName).apply();
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user