merge unitTesting
This commit is contained in:
commit
ab0ce55411
66 changed files with 1971 additions and 1113 deletions
|
|
@ -99,8 +99,8 @@ class ActionBarHandler {
|
|||
defaultPreferences = PreferenceManager.getDefaultSharedPreferences(activity);
|
||||
String[] itemArray = new String[videoStreams.length];
|
||||
String defaultResolution = defaultPreferences
|
||||
.getString(activity.getString(R.string.defaultResolutionPreference),
|
||||
activity.getString(R.string.defaultResolutionListItem));
|
||||
.getString(activity.getString(R.string.default_resolution_key),
|
||||
activity.getString(R.string.default_resolution_value));
|
||||
int defaultResolutionPos = 0;
|
||||
|
||||
for(int i = 0; i < videoStreams.length; i++) {
|
||||
|
|
@ -124,7 +124,7 @@ class ActionBarHandler {
|
|||
// set audioStream
|
||||
audioStream = null;
|
||||
String preferedFormat = defaultPreferences
|
||||
.getString(activity.getString(R.string.defaultAudioFormatPreference), "webm");
|
||||
.getString(activity.getString(R.string.default_audio_format_key), "webm");
|
||||
if(preferedFormat.equals("webm")) {
|
||||
for(VideoInfo.AudioStream s : audioStreams) {
|
||||
if(s.format == MediaFormat.WEBMA.id) {
|
||||
|
|
@ -158,7 +158,7 @@ class ActionBarHandler {
|
|||
MenuItem castItem = menu.findItem(R.id.action_play_with_kodi);
|
||||
|
||||
castItem.setVisible(defaultPreferences
|
||||
.getBoolean(activity.getString(R.string.showPlayWithKodiPreference), false));
|
||||
.getBoolean(activity.getString(R.string.show_play_with_kodi_key), false));
|
||||
}
|
||||
|
||||
public boolean onItemSelected(MenuItem item) {
|
||||
|
|
@ -170,7 +170,7 @@ class ActionBarHandler {
|
|||
intent.setAction(Intent.ACTION_SEND);
|
||||
intent.putExtra(Intent.EXTRA_TEXT, websiteUrl);
|
||||
intent.setType("text/plain");
|
||||
activity.startActivity(Intent.createChooser(intent, activity.getString(R.string.shareDialogTitle)));
|
||||
activity.startActivity(Intent.createChooser(intent, activity.getString(R.string.share_dialog_title)));
|
||||
return true;
|
||||
}
|
||||
case R.id.menu_item_openInBrowser: {
|
||||
|
|
@ -210,7 +210,7 @@ class ActionBarHandler {
|
|||
// ----------- THE MAGIC MOMENT ---------------
|
||||
if(!videoTitle.isEmpty()) {
|
||||
if (PreferenceManager.getDefaultSharedPreferences(activity)
|
||||
.getBoolean(activity.getString(R.string.useExternalVideoPlayer), false)) {
|
||||
.getBoolean(activity.getString(R.string.use_external_video_player_key), false)) {
|
||||
|
||||
// External Player
|
||||
Intent intent = new Intent();
|
||||
|
|
@ -226,13 +226,13 @@ class ActionBarHandler {
|
|||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(activity);
|
||||
builder.setMessage(R.string.noPlayerFound)
|
||||
.setPositiveButton(R.string.installStreamPlayer, new DialogInterface.OnClickListener() {
|
||||
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.fdroidVLCurl)));
|
||||
intent.setData(Uri.parse(activity.getString(R.string.fdroid_vlc_url)));
|
||||
activity.startActivity(intent);
|
||||
}
|
||||
})
|
||||
|
|
@ -284,7 +284,7 @@ class ActionBarHandler {
|
|||
intent.setAction(Intent.ACTION_VIEW);
|
||||
intent.setData(Uri.parse(websiteUrl));
|
||||
|
||||
activity.startActivity(Intent.createChooser(intent, activity.getString(R.string.chooseBrowser)));
|
||||
activity.startActivity(Intent.createChooser(intent, activity.getString(R.string.choose_browser)));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -298,13 +298,13 @@ class ActionBarHandler {
|
|||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(activity);
|
||||
builder.setMessage(R.string.koreNotFound)
|
||||
.setPositiveButton(R.string.installeKore, new DialogInterface.OnClickListener() {
|
||||
builder.setMessage(R.string.kore_not_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.fdroidKoreUrl)));
|
||||
intent.setData(Uri.parse(activity.getString(R.string.fdroid_kore_url)));
|
||||
activity.startActivity(intent);
|
||||
}
|
||||
})
|
||||
|
|
@ -322,7 +322,7 @@ class ActionBarHandler {
|
|||
public void playAudio() {
|
||||
|
||||
boolean externalAudioPlayer = PreferenceManager.getDefaultSharedPreferences(activity)
|
||||
.getBoolean(activity.getString(R.string.useExternalAudioPlayer), false);
|
||||
.getBoolean(activity.getString(R.string.use_external_audio_player_key), false);
|
||||
Intent intent;
|
||||
|
||||
if (!externalAudioPlayer && android.os.Build.VERSION.SDK_INT >= 18) {
|
||||
|
|
@ -356,13 +356,13 @@ class ActionBarHandler {
|
|||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(activity);
|
||||
builder.setMessage(R.string.noPlayerFound)
|
||||
.setPositiveButton(R.string.installStreamPlayer, new DialogInterface.OnClickListener() {
|
||||
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.fdroidVLCurl)));
|
||||
intent.setData(Uri.parse(activity.getString(R.string.fdroid_vlc_url)));
|
||||
activity.startActivity(intent);
|
||||
}
|
||||
})
|
||||
|
|
|
|||
71
app/src/main/java/org/schabi/newpipe/App.java
Normal file
71
app/src/main/java/org/schabi/newpipe/App.java
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
package org.schabi.newpipe;
|
||||
|
||||
import android.app.Application;
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.preference.PreferenceManager;
|
||||
|
||||
import info.guardianproject.netcipher.NetCipher;
|
||||
import info.guardianproject.netcipher.proxy.OrbotHelper;
|
||||
|
||||
/**
|
||||
* Copyright (C) Hans-Christoph Steiner 2016 <hans@eds.org>
|
||||
* App.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/>.
|
||||
*/
|
||||
|
||||
public class App extends Application {
|
||||
|
||||
private static boolean useTor;
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
|
||||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
|
||||
if(prefs.getBoolean(getString(R.string.use_tor_key), false)) {
|
||||
OrbotHelper.requestStartTor(this);
|
||||
configureTor(true);
|
||||
} else {
|
||||
configureTor(false);
|
||||
}
|
||||
|
||||
// DO NOT REMOVE THIS FUNCTION!!!
|
||||
// Otherwise downloadPathPreference has invalid value.
|
||||
SettingsActivity.initSettings(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the proxy settings based on whether Tor should be enabled or not.
|
||||
*/
|
||||
static void configureTor(boolean enabled) {
|
||||
useTor = enabled;
|
||||
if (useTor) {
|
||||
NetCipher.useTor();
|
||||
} else {
|
||||
NetCipher.setProxy(null);
|
||||
}
|
||||
}
|
||||
|
||||
static void checkStartTor(Context context) {
|
||||
if (useTor) {
|
||||
OrbotHelper.requestStartTor(context);
|
||||
}
|
||||
}
|
||||
|
||||
static boolean isUsingTor() {
|
||||
return useTor;
|
||||
}
|
||||
}
|
||||
|
|
@ -17,6 +17,7 @@ import android.os.IBinder;
|
|||
import android.os.PowerManager;
|
||||
import android.support.v7.app.NotificationCompat;
|
||||
import android.util.Log;
|
||||
import android.widget.RemoteViews;
|
||||
import android.widget.Toast;
|
||||
|
||||
import java.io.IOException;
|
||||
|
|
@ -74,7 +75,7 @@ public class BackgroundPlayer extends Service /*implements MediaPlayer.OnPrepare
|
|||
}
|
||||
@Override
|
||||
public int onStartCommand(Intent intent, int flags, int startId) {
|
||||
Toast.makeText(this, R.string.backgroundPlayerStartPlayingToast,
|
||||
Toast.makeText(this, R.string.background_player_playing_toast,
|
||||
Toast.LENGTH_SHORT).show();
|
||||
|
||||
String source = intent.getDataString();
|
||||
|
|
@ -113,9 +114,9 @@ public class BackgroundPlayer extends Service /*implements MediaPlayer.OnPrepare
|
|||
private int noteID = TAG.hashCode();
|
||||
private BackgroundPlayer owner;
|
||||
private NotificationManager noteMgr;
|
||||
private NotificationCompat.Builder noteBuilder;
|
||||
private WifiManager.WifiLock wifiLock;
|
||||
private Bitmap videoThumbnail = null;
|
||||
private NotificationCompat.Builder noteBuilder;
|
||||
|
||||
public PlayerThread(String src, String title, BackgroundPlayer owner) {
|
||||
this.source = src;
|
||||
|
|
@ -124,10 +125,9 @@ public class BackgroundPlayer extends Service /*implements MediaPlayer.OnPrepare
|
|||
mediaPlayer = new MediaPlayer();
|
||||
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
Resources res = getApplicationContext().getResources();
|
||||
|
||||
mediaPlayer.setWakeMode(getApplicationContext(), PowerManager.PARTIAL_WAKE_LOCK);//cpu lock
|
||||
try {
|
||||
mediaPlayer.setDataSource(source);
|
||||
|
|
@ -135,9 +135,6 @@ public class BackgroundPlayer extends Service /*implements MediaPlayer.OnPrepare
|
|||
//so calling the blocking prepare() method should be ok
|
||||
mediaPlayer.prepare();
|
||||
|
||||
//alternatively:
|
||||
//mediaPlayer.setOnPreparedListener(this);
|
||||
//mediaPlayer.prepareAsync(); //prepare async to not block main thread
|
||||
} catch (IOException ioe) {
|
||||
ioe.printStackTrace();
|
||||
Log.e(TAG, "video source:" + source);
|
||||
|
|
@ -177,63 +174,7 @@ public class BackgroundPlayer extends Service /*implements MediaPlayer.OnPrepare
|
|||
filter.addAction(ACTION_STOP);
|
||||
registerReceiver(broadcastReceiver, filter);
|
||||
|
||||
PendingIntent playPI = PendingIntent.getBroadcast(owner, noteID,
|
||||
new Intent(ACTION_PLAYPAUSE), PendingIntent.FLAG_UPDATE_CURRENT);
|
||||
|
||||
NotificationCompat.Action playButton = new NotificationCompat.Action.Builder
|
||||
(R.drawable.ic_play_arrow_white_48dp, "Play", playPI).build();
|
||||
|
||||
/*
|
||||
NotificationCompat.Action pauseButton = new NotificationCompat.Action.Builder
|
||||
(R.drawable.ic_pause_white_24dp, "Pause", playPI).build();
|
||||
*/
|
||||
|
||||
PendingIntent stopPI = PendingIntent.getBroadcast(owner, noteID,
|
||||
new Intent(ACTION_STOP), PendingIntent.FLAG_UPDATE_CURRENT);
|
||||
|
||||
noteBuilder = new NotificationCompat.Builder(owner);
|
||||
noteBuilder
|
||||
.setContentTitle(title)
|
||||
//really? Id like to put something more helpful here.
|
||||
//.setContentText("NewPipe is playing in the background")
|
||||
.setContentText(channelName)
|
||||
//.setAutoCancel(!mediaPlayer.isPlaying())
|
||||
.setOngoing(true)
|
||||
.setDeleteIntent(stopPI)
|
||||
//doesn't fit with Notification.MediaStyle
|
||||
//.setProgress(vidLength, 0, false)
|
||||
.setSmallIcon(R.drawable.ic_play_circle_filled_white_24dp)
|
||||
.setLargeIcon(videoThumbnail)
|
||||
.setTicker(
|
||||
String.format(res.getString(
|
||||
R.string.backgroundPlayerTickerText), title))
|
||||
.addAction(playButton);
|
||||
//.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
|
||||
//.setLargeIcon(cover)
|
||||
if(android.os.Build.VERSION.SDK_INT >= 16)
|
||||
noteBuilder.setPriority(Notification.PRIORITY_LOW);
|
||||
if(android.os.Build.VERSION.SDK_INT >= 21)
|
||||
noteBuilder.setCategory(Notification.CATEGORY_TRANSPORT);
|
||||
|
||||
noteBuilder.setStyle(new NotificationCompat.MediaStyle()
|
||||
//.setMediaSession(mMediaSession.getSessionToken())
|
||||
.setShowActionsInCompactView(new int[]{0})
|
||||
.setShowCancelButton(true)
|
||||
.setCancelButtonIntent(stopPI));
|
||||
if(videoThumbnail != null) {
|
||||
noteBuilder.setLargeIcon(videoThumbnail);
|
||||
}
|
||||
|
||||
Notification note = noteBuilder.build();
|
||||
|
||||
Intent openDetailView = new Intent(getApplicationContext(),
|
||||
VideoItemDetailActivity.class);
|
||||
openDetailView.putExtra(VideoItemDetailFragment.STREAMING_SERVICE, serviceId);
|
||||
openDetailView.putExtra(VideoItemDetailFragment.VIDEO_URL, webUrl);
|
||||
openDetailView.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
note.contentIntent = PendingIntent.getActivity(getApplicationContext(),
|
||||
noteID, openDetailView,
|
||||
PendingIntent.FLAG_UPDATE_CURRENT);
|
||||
Notification note = buildNotification();
|
||||
|
||||
startForeground(noteID, note);
|
||||
|
||||
|
|
@ -252,9 +193,9 @@ public class BackgroundPlayer extends Service /*implements MediaPlayer.OnPrepare
|
|||
Log.d(TAG, "sleep failure");
|
||||
}
|
||||
}*/
|
||||
|
||||
}
|
||||
|
||||
/**Handles button presses from the notification. */
|
||||
private final BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
|
|
@ -265,7 +206,7 @@ public class BackgroundPlayer extends Service /*implements MediaPlayer.OnPrepare
|
|||
mediaPlayer.pause();
|
||||
}
|
||||
else {
|
||||
//reacquire CPU lock after releasing it on pause
|
||||
//reacquire CPU lock after auto-releasing it on pause
|
||||
mediaPlayer.setWakeMode(getApplicationContext(), PowerManager.PARTIAL_WAKE_LOCK);
|
||||
mediaPlayer.start();
|
||||
}
|
||||
|
|
@ -279,8 +220,9 @@ public class BackgroundPlayer extends Service /*implements MediaPlayer.OnPrepare
|
|||
};
|
||||
|
||||
private void afterPlayCleanup() {
|
||||
//noteBuilder.setProgress(0, 0, false);
|
||||
//remove progress bar
|
||||
//noteBuilder.setProgress(0, 0, false);
|
||||
|
||||
//remove notification
|
||||
noteMgr.cancel(noteID);
|
||||
unregisterReceiver(broadcastReceiver);
|
||||
|
|
@ -289,7 +231,7 @@ public class BackgroundPlayer extends Service /*implements MediaPlayer.OnPrepare
|
|||
|
||||
//release wifilock
|
||||
wifiLock.release();
|
||||
//remove foreground status of service; make us killable
|
||||
//remove foreground status of service; make BackgroundPlayer killable
|
||||
stopForeground(true);
|
||||
|
||||
stopSelf();
|
||||
|
|
@ -306,5 +248,110 @@ public class BackgroundPlayer extends Service /*implements MediaPlayer.OnPrepare
|
|||
afterPlayCleanup();
|
||||
}
|
||||
}
|
||||
|
||||
private Notification buildNotification() {
|
||||
Notification note;
|
||||
Resources res = getApplicationContext().getResources();
|
||||
noteBuilder = new NotificationCompat.Builder(owner);
|
||||
|
||||
PendingIntent playPI = PendingIntent.getBroadcast(owner, noteID,
|
||||
new Intent(ACTION_PLAYPAUSE), PendingIntent.FLAG_UPDATE_CURRENT);
|
||||
PendingIntent stopPI = PendingIntent.getBroadcast(owner, noteID,
|
||||
new Intent(ACTION_STOP), PendingIntent.FLAG_UPDATE_CURRENT);
|
||||
/*
|
||||
NotificationCompat.Action pauseButton = new NotificationCompat.Action.Builder
|
||||
(R.drawable.ic_pause_white_24dp, "Pause", playPI).build();
|
||||
*/
|
||||
|
||||
//build intent to return to video, on tapping notification
|
||||
Intent openDetailView = new Intent(getApplicationContext(),
|
||||
VideoItemDetailActivity.class);
|
||||
openDetailView.putExtra(VideoItemDetailFragment.STREAMING_SERVICE, serviceId);
|
||||
openDetailView.putExtra(VideoItemDetailFragment.VIDEO_URL, webUrl);
|
||||
openDetailView.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
|
||||
noteBuilder
|
||||
.setOngoing(true)
|
||||
.setDeleteIntent(stopPI)
|
||||
//doesn't fit with Notification.MediaStyle
|
||||
//.setProgress(vidLength, 0, false)
|
||||
.setSmallIcon(R.drawable.ic_play_circle_filled_white_24dp)
|
||||
.setTicker(
|
||||
String.format(res.getString(
|
||||
R.string.background_player_time_text), title))
|
||||
.setContentIntent(PendingIntent.getActivity(getApplicationContext(),
|
||||
noteID, openDetailView,
|
||||
PendingIntent.FLAG_UPDATE_CURRENT));
|
||||
|
||||
|
||||
if (android.os.Build.VERSION.SDK_INT < 21) {
|
||||
|
||||
NotificationCompat.Action playButton = new NotificationCompat.Action.Builder
|
||||
(R.drawable.ic_play_arrow_white_48dp,
|
||||
res.getString(R.string.play_btn_text), playPI).build();
|
||||
|
||||
noteBuilder
|
||||
.setContentTitle(title)
|
||||
//really? Id like to put something more helpful here.
|
||||
//was more of a placeholder than anything else. -medavox
|
||||
//.setContentText("NewPipe is playing in the background")
|
||||
.setContentText(channelName)
|
||||
//.setAutoCancel(!mediaPlayer.isPlaying())
|
||||
.setDeleteIntent(stopPI)
|
||||
//doesn't fit with Notification.MediaStyle
|
||||
//.setProgress(vidLength, 0, false)
|
||||
.setLargeIcon(videoThumbnail)
|
||||
.addAction(playButton);
|
||||
//.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
|
||||
//.setLargeIcon(cover)
|
||||
|
||||
//is wrapping this in an SDK version check really necessary,
|
||||
// if we're using NotificationCompat?
|
||||
// the compat libraries should handle this, right? -medavox
|
||||
if (android.os.Build.VERSION.SDK_INT >= 16)
|
||||
noteBuilder.setPriority(Notification.PRIORITY_LOW);
|
||||
|
||||
noteBuilder.setStyle(new NotificationCompat.MediaStyle()
|
||||
//.setMediaSession(mMediaSession.getSessionToken())
|
||||
.setShowActionsInCompactView(new int[]{0})
|
||||
.setShowCancelButton(true)
|
||||
.setCancelButtonIntent(stopPI));
|
||||
if (videoThumbnail != null) {
|
||||
noteBuilder.setLargeIcon(videoThumbnail);
|
||||
}
|
||||
note = noteBuilder.build();
|
||||
} else {
|
||||
RemoteViews view =
|
||||
new RemoteViews(BuildConfig.APPLICATION_ID, R.layout.player_notification);
|
||||
view.setImageViewBitmap(R.id.backgroundCover, videoThumbnail);
|
||||
view.setTextViewText(R.id.backgroundSongName, title);
|
||||
view.setTextViewText(R.id.backgroundArtist, channelName);
|
||||
view.setOnClickPendingIntent(R.id.backgroundStop, stopPI);
|
||||
view.setOnClickPendingIntent(R.id.backgroundPlayPause, playPI);
|
||||
|
||||
//possibly found the expandedView problem,
|
||||
//but can't test it as I don't have a 5.0 device. -medavox
|
||||
RemoteViews expandedView =
|
||||
new RemoteViews(BuildConfig.APPLICATION_ID, R.layout.player_notification_expanded);
|
||||
expandedView.setImageViewBitmap(R.id.backgroundCover, videoThumbnail);
|
||||
expandedView.setTextViewText(R.id.backgroundSongName, title);
|
||||
expandedView.setTextViewText(R.id.backgroundArtist, channelName);
|
||||
expandedView.setOnClickPendingIntent(R.id.backgroundStop, stopPI);
|
||||
expandedView.setOnClickPendingIntent(R.id.backgroundPlayPause, playPI);
|
||||
|
||||
noteBuilder.setCategory(Notification.CATEGORY_TRANSPORT);
|
||||
|
||||
//Make notification appear on lockscreen
|
||||
noteBuilder.setVisibility(Notification.VISIBILITY_PUBLIC);
|
||||
|
||||
note = noteBuilder.build();
|
||||
note.contentView = view;
|
||||
|
||||
//todo: This never shows up. I was not able to figure out why:
|
||||
note.bigContentView = expandedView;
|
||||
}
|
||||
|
||||
return note;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -52,49 +52,58 @@ public class DownloadDialog extends DialogFragment {
|
|||
arguments = getArguments();
|
||||
super.onCreateDialog(savedInstanceState);
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
|
||||
builder.setTitle(R.string.downloadDialogTitle)
|
||||
.setItems(R.array.downloadOptions, new DialogInterface.OnClickListener() {
|
||||
builder.setTitle(R.string.download_dialog_title)
|
||||
.setItems(R.array.download_options, new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
Context context = getActivity();
|
||||
SharedPreferences defaultPreferences = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
String suffix = "";
|
||||
String title = arguments.getString(TITLE);
|
||||
String url = "";
|
||||
String downloadFolder = Environment.DIRECTORY_DOWNLOADS;
|
||||
switch(which) {
|
||||
case 0: // Video
|
||||
suffix = arguments.getString(FILE_SUFFIX_VIDEO);
|
||||
url = arguments.getString(VIDEO_URL);
|
||||
downloadFolder = Environment.DIRECTORY_MOVIES;
|
||||
break;
|
||||
case 1:
|
||||
suffix = arguments.getString(FILE_SUFFIX_AUDIO);
|
||||
url = arguments.getString(AUDIO_URL);
|
||||
downloadFolder = Environment.DIRECTORY_MUSIC;
|
||||
break;
|
||||
default:
|
||||
Log.d(TAG, "lolz");
|
||||
}
|
||||
//to avoid hard-coded string like "/storage/emulated/0/NewPipe"
|
||||
final File dir = new File(defaultPreferences.getString(
|
||||
"download_path_preference",
|
||||
Environment.getExternalStorageDirectory().getAbsolutePath() + "/NewPipe"));
|
||||
//to avoid hard-coded string like "/storage/emulated/0/Movies"
|
||||
String downloadPath = prefs.getString(getString(R.string.download_path_key),
|
||||
Environment.getExternalStorageDirectory().getAbsolutePath() + "/" + downloadFolder);
|
||||
final File dir = new File(downloadPath);
|
||||
if(!dir.exists()) {
|
||||
boolean mkdir = dir.mkdir(); //attempt to create directory
|
||||
//attempt to create directory
|
||||
boolean mkdir = dir.mkdir();
|
||||
if(!mkdir && !dir.isDirectory()) {
|
||||
Log.e(TAG, "Cant' create directory named " + dir.toString());
|
||||
//TODO notify user "download directory should be changed" ?
|
||||
}
|
||||
}
|
||||
DownloadManager dm = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE);
|
||||
DownloadManager.Request request = new DownloadManager.Request(
|
||||
Uri.parse(url));
|
||||
request.setDestinationUri(Uri.fromFile(new File(
|
||||
defaultPreferences.getString("download_path_preference", "/storage/emulated/0/NewPipe")
|
||||
+ "/" + title + suffix)));
|
||||
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
|
||||
try {
|
||||
dm.enqueue(request);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
|
||||
String saveFilePath = dir + "/" + title + suffix;
|
||||
if (App.isUsingTor()) {
|
||||
// if using Tor, do not use DownloadManager because the proxy cannot be set
|
||||
Downloader.downloadFile(getContext(), url, saveFilePath);
|
||||
} else {
|
||||
DownloadManager dm = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE);
|
||||
DownloadManager.Request request = new DownloadManager.Request(
|
||||
Uri.parse(url));
|
||||
request.setDestinationUri(Uri.fromFile(new File(saveFilePath)));
|
||||
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
|
||||
try {
|
||||
dm.enqueue(request);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,12 +1,30 @@
|
|||
package org.schabi.newpipe;
|
||||
|
||||
|
||||
import android.app.NotificationManager;
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.graphics.drawable.BitmapDrawable;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.AsyncTask;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.support.v4.app.NotificationCompat;
|
||||
import android.util.Log;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
import java.net.UnknownHostException;
|
||||
|
||||
import javax.net.ssl.HttpsURLConnection;
|
||||
|
||||
import info.guardianproject.netcipher.NetCipher;
|
||||
|
||||
/**
|
||||
* Created by Christian Schabesberger on 14.08.15.
|
||||
*
|
||||
|
|
@ -28,7 +46,7 @@ import java.net.UnknownHostException;
|
|||
*/
|
||||
|
||||
public class Downloader {
|
||||
|
||||
public static final String TAG = "Downloader";
|
||||
private static final String USER_AGENT = "Mozilla/5.0";
|
||||
|
||||
/**Download the text file at the supplied URL as in download(String),
|
||||
|
|
@ -40,7 +58,7 @@ public class Downloader {
|
|||
String ret = "";
|
||||
try {
|
||||
URL url = new URL(siteUrl);
|
||||
HttpURLConnection con = (HttpURLConnection) url.openConnection();
|
||||
HttpsURLConnection con = (HttpsURLConnection) url.openConnection();
|
||||
con.setRequestProperty("Accept-Language", language);
|
||||
ret = dl(con);
|
||||
}
|
||||
|
|
@ -49,8 +67,9 @@ public class Downloader {
|
|||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**Common functionality between download(String url) and download(String url, String language)*/
|
||||
private static String dl(HttpURLConnection con) throws IOException {
|
||||
private static String dl(HttpsURLConnection con) throws IOException {
|
||||
StringBuilder response = new StringBuilder();
|
||||
|
||||
try {
|
||||
|
|
@ -84,7 +103,7 @@ public class Downloader {
|
|||
|
||||
try {
|
||||
URL url = new URL(siteUrl);
|
||||
HttpURLConnection con = (HttpURLConnection) url.openConnection();
|
||||
HttpsURLConnection con = NetCipher.getHttpsURLConnection(url);
|
||||
ret = dl(con);
|
||||
}
|
||||
catch(Exception e) {
|
||||
|
|
@ -93,4 +112,92 @@ public class Downloader {
|
|||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Downloads a file from a URL in the background using an {@link AsyncTask}.
|
||||
*
|
||||
* @param fileURL HTTP URL of the file to be downloaded
|
||||
* @param saveFilePath path of the directory to save the file
|
||||
* @throws IOException
|
||||
*/
|
||||
public static void downloadFile(final Context context, final String fileURL, final String saveFilePath) {
|
||||
new AsyncTask<Void, Integer, Void>() {
|
||||
|
||||
private NotificationManager nm;
|
||||
private NotificationCompat.Builder builder;
|
||||
private int notifyId = 0x1234;
|
||||
private int fileSize = 0xffffffff;
|
||||
|
||||
@Override
|
||||
protected void onPreExecute() {
|
||||
super.onPreExecute();
|
||||
nm = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
|
||||
Drawable icon = context.getResources().getDrawable(R.mipmap.ic_launcher);
|
||||
builder = new NotificationCompat.Builder(context)
|
||||
.setSmallIcon(android.R.drawable.stat_sys_download)
|
||||
.setLargeIcon(((BitmapDrawable) icon).getBitmap())
|
||||
.setContentTitle(saveFilePath.substring(saveFilePath.lastIndexOf('/') + 1))
|
||||
.setContentText(saveFilePath)
|
||||
.setProgress(fileSize, 0, false);
|
||||
nm.notify(notifyId, builder.build());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Void doInBackground(Void... voids) {
|
||||
HttpsURLConnection con = null;
|
||||
try {
|
||||
con = NetCipher.getHttpsURLConnection(fileURL);
|
||||
int responseCode = con.getResponseCode();
|
||||
|
||||
// always check HTTP response code first
|
||||
if (responseCode == HttpURLConnection.HTTP_OK) {
|
||||
fileSize = con.getContentLength();
|
||||
InputStream inputStream = new BufferedInputStream(con.getInputStream());
|
||||
FileOutputStream outputStream = new FileOutputStream(saveFilePath);
|
||||
|
||||
int bufferSize = 8192;
|
||||
int downloaded = 0;
|
||||
|
||||
int bytesRead = -1;
|
||||
byte[] buffer = new byte[bufferSize];
|
||||
while ((bytesRead = inputStream.read(buffer)) != -1) {
|
||||
outputStream.write(buffer, 0, bytesRead);
|
||||
downloaded += bytesRead;
|
||||
if (downloaded % 50000 < bufferSize) {
|
||||
publishProgress(downloaded);
|
||||
}
|
||||
}
|
||||
|
||||
outputStream.close();
|
||||
inputStream.close();
|
||||
publishProgress(bufferSize);
|
||||
|
||||
} else {
|
||||
Log.i(TAG, "No file to download. Server replied HTTP code: " + responseCode);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
if (con != null) {
|
||||
con.disconnect();
|
||||
con = null;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onProgressUpdate(Integer... progress) {
|
||||
builder.setProgress(fileSize, progress[0], false);
|
||||
nm.notify(notifyId, builder.build());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(Void aVoid) {
|
||||
super.onPostExecute(aVoid);
|
||||
nm.cancel(notifyId);
|
||||
}
|
||||
}.execute();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
54
app/src/main/java/org/schabi/newpipe/ExitActivity.java
Normal file
54
app/src/main/java/org/schabi/newpipe/ExitActivity.java
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
|
||||
package org.schabi.newpipe;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
|
||||
/**
|
||||
* Copyright (C) Hans-Christoph Steiner 2016 <hans@eds.org>
|
||||
* ExitActivity.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/>.
|
||||
*/
|
||||
|
||||
public class ExitActivity extends Activity {
|
||||
|
||||
@SuppressLint("NewApi")
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
if (Build.VERSION.SDK_INT >= 21) {
|
||||
finishAndRemoveTask();
|
||||
} else {
|
||||
finish();
|
||||
}
|
||||
|
||||
System.exit(0);
|
||||
}
|
||||
|
||||
public static void exitAndRemoveFromRecentApps(Activity activity) {
|
||||
Intent intent = new Intent(activity, ExitActivity.class);
|
||||
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
|
||||
| Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
|
||||
| Intent.FLAG_ACTIVITY_CLEAR_TASK
|
||||
| Intent.FLAG_ACTIVITY_NO_ANIMATION);
|
||||
|
||||
activity.startActivity(intent);
|
||||
}
|
||||
}
|
||||
93
app/src/main/java/org/schabi/newpipe/Localization.java
Normal file
93
app/src/main/java/org/schabi/newpipe/Localization.java
Normal file
|
|
@ -0,0 +1,93 @@
|
|||
package org.schabi.newpipe;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.res.Resources;
|
||||
import android.preference.PreferenceManager;
|
||||
|
||||
import java.text.DateFormat;
|
||||
import java.text.NumberFormat;
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.Locale;
|
||||
|
||||
/**
|
||||
* Created by chschtsch on 12/29/15.
|
||||
*
|
||||
* Copyright (C) Gregory Arkhipov 2015
|
||||
* Localization.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/>.
|
||||
*/
|
||||
|
||||
public class Localization {
|
||||
|
||||
public static Locale getPreferredLocale(Context context) {
|
||||
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
|
||||
String languageCode = sp.getString(String.valueOf(R.string.search_language_key),
|
||||
context.getString(R.string.default_language_value));
|
||||
|
||||
if(languageCode.length() == 2) {
|
||||
return new Locale(languageCode);
|
||||
}
|
||||
else if(languageCode.contains("_")) {
|
||||
String country = languageCode
|
||||
.substring(languageCode.indexOf("_"), languageCode.length());
|
||||
return new Locale(languageCode.substring(0, 2), country);
|
||||
}
|
||||
return Locale.getDefault();
|
||||
}
|
||||
|
||||
public static String localizeViewCount(long viewCount, Context context) {
|
||||
Locale locale = getPreferredLocale(context);
|
||||
|
||||
Resources res = context.getResources();
|
||||
String viewsString = res.getString(R.string.view_count_text);
|
||||
|
||||
NumberFormat nf = NumberFormat.getInstance(locale);
|
||||
String formattedViewCount = nf.format(viewCount);
|
||||
return String.format(viewsString, formattedViewCount);
|
||||
}
|
||||
|
||||
public static String localizeNumber(long number, Context context) {
|
||||
Locale locale = getPreferredLocale(context);
|
||||
NumberFormat nf = NumberFormat.getInstance(locale);
|
||||
return nf.format(number);
|
||||
}
|
||||
|
||||
private static String formatDate(String date, Context context) {
|
||||
Locale locale = getPreferredLocale(context);
|
||||
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
|
||||
Date datum = null;
|
||||
try {
|
||||
datum = formatter.parse(date);
|
||||
} catch (ParseException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
DateFormat df = DateFormat.getDateInstance(DateFormat.MEDIUM, locale);
|
||||
|
||||
return df.format(datum);
|
||||
}
|
||||
|
||||
public static String localizeDate(String date, Context context) {
|
||||
Resources res = context.getResources();
|
||||
String dateString = res.getString(R.string.upload_date_text);
|
||||
|
||||
String formattedDate = formatDate(date, context);
|
||||
return String.format(dateString, formattedDate);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
|
||||
package org.schabi.newpipe;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
|
||||
/**
|
||||
* Copyright (C) Hans-Christoph Steiner 2016 <hans@eds.org>
|
||||
* PanicResponderActivity.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/>.
|
||||
*/
|
||||
|
||||
public class PanicResponderActivity extends Activity {
|
||||
|
||||
public static final String PANIC_TRIGGER_ACTION = "info.guardianproject.panic.action.TRIGGER";
|
||||
|
||||
@SuppressLint("NewApi")
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
Intent intent = getIntent();
|
||||
if (intent != null && PANIC_TRIGGER_ACTION.equals(intent.getAction())) {
|
||||
// TODO explicitly clear the search results once they are restored when the app restarts
|
||||
// or if the app reloads the current video after being killed, that should be cleared also
|
||||
ExitActivity.exitAndRemoveFromRecentApps(this);
|
||||
}
|
||||
|
||||
if (Build.VERSION.SDK_INT >= 21) {
|
||||
finishAndRemoveTask();
|
||||
} else {
|
||||
finish();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -187,6 +187,18 @@ public class PlayVideoActivity extends AppCompatActivity {
|
|||
videoView.pause();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
App.checkStartTor(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
prefs = getPreferences(Context.MODE_PRIVATE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
int id = item.getItemId();
|
||||
|
|
@ -199,7 +211,7 @@ public class PlayVideoActivity extends AppCompatActivity {
|
|||
intent.setAction(Intent.ACTION_SEND);
|
||||
intent.putExtra(Intent.EXTRA_TEXT, videoUrl);
|
||||
intent.setType("text/plain");
|
||||
startActivity(Intent.createChooser(intent, getString(R.string.shareDialogTitle)));
|
||||
startActivity(Intent.createChooser(intent, getString(R.string.share_dialog_title)));
|
||||
break;
|
||||
case R.id.menu_item_screen_rotation:
|
||||
toggleOrientation();
|
||||
|
|
|
|||
|
|
@ -1,10 +1,15 @@
|
|||
package org.schabi.newpipe;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.res.Configuration;
|
||||
import android.os.Bundle;
|
||||
import android.os.Environment;
|
||||
import android.preference.CheckBoxPreference;
|
||||
import android.preference.EditTextPreference;
|
||||
import android.preference.ListPreference;
|
||||
import android.preference.PreferenceActivity;
|
||||
import android.preference.PreferenceFragment;
|
||||
import android.preference.PreferenceManager;
|
||||
|
|
@ -17,6 +22,8 @@ import android.view.MenuItem;
|
|||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import info.guardianproject.netcipher.proxy.OrbotHelper;
|
||||
|
||||
/**
|
||||
* Created by Christian Schabesberger on 31.08.15.
|
||||
*
|
||||
|
|
@ -37,8 +44,9 @@ import android.view.ViewGroup;
|
|||
* along with NewPipe. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
public class SettingsActivity extends PreferenceActivity {
|
||||
public class SettingsActivity extends PreferenceActivity {
|
||||
|
||||
private static final int REQUEST_INSTALL_ORBOT = 0x1234;
|
||||
private AppCompatDelegate mDelegate = null;
|
||||
|
||||
@Override
|
||||
|
|
@ -55,12 +63,100 @@ public class SettingsActivity extends PreferenceActivity {
|
|||
|
||||
}
|
||||
|
||||
public static class SettingsFragment extends PreferenceFragment {
|
||||
public static class SettingsFragment extends PreferenceFragment{
|
||||
SharedPreferences.OnSharedPreferenceChangeListener prefListener;
|
||||
|
||||
// get keys
|
||||
String DEFAULT_RESOLUTION_PREFERENCE;
|
||||
String DEFAULT_AUDIO_FORMAT_PREFERENCE;
|
||||
String SEARCH_LANGUAGE_PREFERENCE;
|
||||
String DOWNLOAD_PATH_PREFERENCE;
|
||||
String USE_TOR_KEY;
|
||||
|
||||
private ListPreference defaultResolutionPreference;
|
||||
private ListPreference defaultAudioFormatPreference;
|
||||
private ListPreference searchLanguagePreference;
|
||||
private EditTextPreference downloadPathPreference;
|
||||
private CheckBoxPreference useTorCheckBox;
|
||||
private SharedPreferences defaultPreferences;
|
||||
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
addPreferencesFromResource(R.xml.settings_screen);
|
||||
addPreferencesFromResource(R.xml.settings);
|
||||
|
||||
final Activity activity = getActivity();
|
||||
|
||||
defaultPreferences = PreferenceManager.getDefaultSharedPreferences(activity);
|
||||
|
||||
// get keys
|
||||
DEFAULT_RESOLUTION_PREFERENCE =getString(R.string.default_resolution_key);
|
||||
DEFAULT_AUDIO_FORMAT_PREFERENCE =getString(R.string.default_audio_format_key);
|
||||
SEARCH_LANGUAGE_PREFERENCE =getString(R.string.search_language_key);
|
||||
DOWNLOAD_PATH_PREFERENCE = getString(R.string.download_path_key);
|
||||
USE_TOR_KEY = getString(R.string.use_tor_key);
|
||||
|
||||
// get pref objects
|
||||
defaultResolutionPreference =
|
||||
(ListPreference) findPreference(DEFAULT_RESOLUTION_PREFERENCE);
|
||||
defaultAudioFormatPreference =
|
||||
(ListPreference) findPreference(DEFAULT_AUDIO_FORMAT_PREFERENCE);
|
||||
searchLanguagePreference =
|
||||
(ListPreference) findPreference(SEARCH_LANGUAGE_PREFERENCE);
|
||||
downloadPathPreference =
|
||||
(EditTextPreference) findPreference(DOWNLOAD_PATH_PREFERENCE);
|
||||
useTorCheckBox = (CheckBoxPreference) findPreference(USE_TOR_KEY);
|
||||
|
||||
prefListener = new SharedPreferences.OnSharedPreferenceChangeListener() {
|
||||
@Override
|
||||
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences,
|
||||
String key) {
|
||||
Activity a = getActivity();
|
||||
updateSummary();
|
||||
|
||||
if (defaultPreferences.getBoolean(USE_TOR_KEY, false)) {
|
||||
if (OrbotHelper.isOrbotInstalled(a)) {
|
||||
App.configureTor(true);
|
||||
OrbotHelper.requestStartTor(a);
|
||||
} else {
|
||||
Intent intent = OrbotHelper.getOrbotInstallIntent(a);
|
||||
a.startActivityForResult(intent, REQUEST_INSTALL_ORBOT);
|
||||
}
|
||||
} else {
|
||||
App.configureTor(false);
|
||||
}
|
||||
}
|
||||
};
|
||||
defaultPreferences.registerOnSharedPreferenceChangeListener(prefListener);
|
||||
|
||||
updateSummary();
|
||||
}
|
||||
|
||||
// This is used to show the status of some preference in the description
|
||||
private void updateSummary() {
|
||||
defaultResolutionPreference.setSummary(
|
||||
defaultPreferences.getString(DEFAULT_RESOLUTION_PREFERENCE,
|
||||
getString(R.string.default_resolution_value)));
|
||||
defaultAudioFormatPreference.setSummary(
|
||||
defaultPreferences.getString(DEFAULT_AUDIO_FORMAT_PREFERENCE,
|
||||
getString(R.string.default_audio_format_value)));
|
||||
searchLanguagePreference.setSummary(
|
||||
defaultPreferences.getString(SEARCH_LANGUAGE_PREFERENCE,
|
||||
getString(R.string.default_language_value)));
|
||||
downloadPathPreference.setSummary(
|
||||
defaultPreferences.getString(DOWNLOAD_PATH_PREFERENCE,
|
||||
getString(R.string.download_path_summary)));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
// try to start tor regardless of resultCode since clicking back after
|
||||
// installing the app does not necessarily return RESULT_OK
|
||||
App.configureTor(requestCode == REQUEST_INSTALL_ORBOT
|
||||
&& OrbotHelper.requestStartTor(this));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -150,13 +246,13 @@ public class SettingsActivity extends PreferenceActivity {
|
|||
}
|
||||
|
||||
public static void initSettings(Context context) {
|
||||
PreferenceManager.setDefaultValues(context, R.xml.settings_screen, false);
|
||||
PreferenceManager.setDefaultValues(context, R.xml.settings, false);
|
||||
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
if(sp.getString(context.getString(R.string.downloadPathPreference), "").isEmpty()){
|
||||
if(sp.getString(context.getString(R.string.download_path_key), "").isEmpty()){
|
||||
SharedPreferences.Editor spEditor = sp.edit();
|
||||
String newPipeDownloadStorage =
|
||||
Environment.getExternalStorageDirectory().getAbsolutePath() + "/NewPipe";
|
||||
spEditor.putString(context.getString(R.string.downloadPathPreference)
|
||||
spEditor.putString(context.getString(R.string.download_path_key)
|
||||
, newPipeDownloadStorage);
|
||||
spEditor.apply();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
package org.schabi.newpipe;
|
||||
|
||||
import android.content.Context;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
|
@ -33,7 +34,7 @@ class VideoInfoItemViewCreator {
|
|||
this.inflater = inflater;
|
||||
}
|
||||
|
||||
public View getViewFromVideoInfoItem(View convertView, ViewGroup parent, VideoPreviewInfo info) {
|
||||
public View getViewFromVideoInfoItem(View convertView, ViewGroup parent, VideoPreviewInfo info, Context context) {
|
||||
ViewHolder holder;
|
||||
if(convertView == null) {
|
||||
convertView = inflater.inflate(R.layout.video_item, parent, false);
|
||||
|
|
@ -59,8 +60,7 @@ class VideoInfoItemViewCreator {
|
|||
if(!info.upload_date.isEmpty()) {
|
||||
holder.itemUploadDateView.setText(info.upload_date);
|
||||
} else {
|
||||
//tweak if necessary: This is a hack to prevent having white space in the layout :P
|
||||
holder.itemUploadDateView.setText(String.format("%d", info.view_count));
|
||||
holder.itemUploadDateView.setText(Localization.localizeViewCount(info.view_count, context));
|
||||
}
|
||||
|
||||
return convertView;
|
||||
|
|
|
|||
|
|
@ -80,7 +80,7 @@ public class VideoItemDetailActivity extends AppCompatActivity {
|
|||
}
|
||||
}
|
||||
if(currentStreamingService == -1) {
|
||||
Toast.makeText(this, R.string.urlNotSupportedText, Toast.LENGTH_LONG)
|
||||
Toast.makeText(this, R.string.url_not_supported_toast, Toast.LENGTH_LONG)
|
||||
.show();
|
||||
}
|
||||
//arguments.putString(VideoItemDetailFragment.VIDEO_URL,
|
||||
|
|
@ -89,7 +89,7 @@ public class VideoItemDetailActivity extends AppCompatActivity {
|
|||
|
||||
arguments.putBoolean(VideoItemDetailFragment.AUTO_PLAY,
|
||||
PreferenceManager.getDefaultSharedPreferences(this)
|
||||
.getBoolean(getString(R.string.autoPlayThroughIntent), false));
|
||||
.getBoolean(getString(R.string.autoplay_through_intent_key), false));
|
||||
} else {
|
||||
videoUrl = getIntent().getStringExtra(VideoItemDetailFragment.VIDEO_URL);
|
||||
currentStreamingService = getIntent().getIntExtra(VideoItemDetailFragment.STREAMING_SERVICE, -1);
|
||||
|
|
@ -113,6 +113,12 @@ public class VideoItemDetailActivity extends AppCompatActivity {
|
|||
.commit();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
App.checkStartTor(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSaveInstanceState(Bundle outState) {
|
||||
outState.putString(VideoItemDetailFragment.VIDEO_URL, videoUrl);
|
||||
|
|
|
|||
|
|
@ -1,9 +1,7 @@
|
|||
package org.schabi.newpipe;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
|
|
@ -35,13 +33,7 @@ import android.view.MenuItem;
|
|||
import android.widget.Toast;
|
||||
|
||||
import java.net.URL;
|
||||
import java.text.DateFormat;
|
||||
import java.text.NumberFormat;
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.Locale;
|
||||
import java.util.Vector;
|
||||
|
||||
import org.schabi.newpipe.services.VideoExtractor;
|
||||
|
|
@ -235,7 +227,7 @@ public class VideoItemDetailFragment extends Fragment {
|
|||
switch (info.errorCode) {
|
||||
case VideoInfo.NO_ERROR: {
|
||||
View nextVideoView = videoItemViewCreator
|
||||
.getViewFromVideoInfoItem(null, nextVideoFrame, info.nextVideo);
|
||||
.getViewFromVideoInfoItem(null, nextVideoFrame, info.nextVideo, getContext());
|
||||
nextVideoFrame.addView(nextVideoView);
|
||||
|
||||
|
||||
|
|
@ -253,31 +245,20 @@ public class VideoItemDetailFragment extends Fragment {
|
|||
uploaderView.setText(info.uploader);
|
||||
actionBarHandler.setChannelName(info.uploader);
|
||||
|
||||
Locale locale = getPreferredLocale();
|
||||
NumberFormat nf = NumberFormat.getInstance(locale);
|
||||
String localisedViewCount = nf.format(info.view_count);
|
||||
viewCountView.setText(
|
||||
String.format(
|
||||
res.getString(R.string.viewCountText), localisedViewCount));
|
||||
String localizedViewCount = Localization.localizeViewCount(info.view_count, getContext());
|
||||
viewCountView.setText(localizedViewCount);
|
||||
|
||||
thumbsUpView.setText(nf.format(info.like_count));
|
||||
thumbsDownView.setText(nf.format(info.dislike_count));
|
||||
String localizedLikeCount = Localization.localizeNumber(info.like_count, getContext());
|
||||
thumbsUpView.setText(localizedLikeCount);
|
||||
|
||||
@SuppressLint("SimpleDateFormat")
|
||||
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
|
||||
Date datum = null;
|
||||
try {
|
||||
datum = formatter.parse(info.upload_date);
|
||||
} catch (ParseException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
String localizedDislikeCount = Localization.localizeNumber(info.dislike_count, getContext());
|
||||
thumbsDownView.setText(localizedDislikeCount);
|
||||
|
||||
DateFormat df = DateFormat.getDateInstance(DateFormat.MEDIUM, locale);
|
||||
String localizedDate = Localization.localizeDate(info.upload_date, getContext());
|
||||
uploadDateView.setText(localizedDate);
|
||||
|
||||
String localisedDate = df.format(datum);
|
||||
uploadDateView.setText(
|
||||
String.format(res.getString(R.string.uploadDateText), localisedDate));
|
||||
descriptionView.setText(Html.fromHtml(info.description));
|
||||
|
||||
descriptionView.setMovementMethod(LinkMovementMethod.getInstance());
|
||||
|
||||
actionBarHandler.setServiceId(streamingServiceId);
|
||||
|
|
@ -306,7 +287,7 @@ public class VideoItemDetailFragment extends Fragment {
|
|||
VideoItemDetailFragment.ARG_ITEM_ID, currentVideoInfo.nextVideo.id); */
|
||||
detailIntent.putExtra(
|
||||
VideoItemDetailFragment.VIDEO_URL, currentVideoInfo.nextVideo.webpage_url);
|
||||
//todo: make id dynamic the following line is crap
|
||||
|
||||
detailIntent.putExtra(VideoItemDetailFragment.STREAMING_SERVICE, streamingServiceId);
|
||||
startActivity(detailIntent);
|
||||
}
|
||||
|
|
@ -315,13 +296,13 @@ public class VideoItemDetailFragment extends Fragment {
|
|||
break;
|
||||
case VideoInfo.ERROR_BLOCKED_BY_GEMA:
|
||||
thumbnailView.setImageBitmap(BitmapFactory.decodeResource(
|
||||
getResources(), R.drawable.gruese_die_gema_unangebracht));
|
||||
getResources(), R.drawable.gruese_die_gema));
|
||||
backgroundButton.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
Intent intent = new Intent();
|
||||
intent.setAction(Intent.ACTION_VIEW);
|
||||
intent.setData(Uri.parse(activity.getString(R.string.c3sUrl)));
|
||||
intent.setData(Uri.parse(activity.getString(R.string.c3s_url)));
|
||||
activity.startActivity(intent);
|
||||
}
|
||||
});
|
||||
|
|
@ -364,7 +345,7 @@ public class VideoItemDetailFragment extends Fragment {
|
|||
super.onCreate(savedInstanceState);
|
||||
activity = (AppCompatActivity) getActivity();
|
||||
showNextVideoItem = PreferenceManager.getDefaultSharedPreferences(getActivity())
|
||||
.getBoolean(activity.getString(R.string.showNextVideo), true);
|
||||
.getBoolean(activity.getString(R.string.show_next_video_key), true);
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -458,30 +439,6 @@ public class VideoItemDetailFragment extends Fragment {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**Returns the java.util.Locale object which corresponds to the locale set in NewPipe's preferences.
|
||||
* Currently not affected by the device's locale.*/
|
||||
private Locale getPreferredLocale() {
|
||||
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getContext());
|
||||
String languageKey = getContext().getString(R.string.searchLanguage);
|
||||
//i know the following line defaults languageCode to "en", but java is picky about uninitialised values
|
||||
// Schabi: well lint tels me the value is redundant. I'll suppress it for now.
|
||||
@SuppressWarnings("UnusedAssignment")
|
||||
String languageCode = "en";
|
||||
languageCode = sp.getString(languageKey, "en");
|
||||
|
||||
if(languageCode.length() == 2) {
|
||||
return new Locale(languageCode);
|
||||
}
|
||||
else if(languageCode.contains("_")) {
|
||||
String country = languageCode
|
||||
.substring(languageCode.indexOf("_"), languageCode.length());
|
||||
return new Locale(languageCode.substring(0, 2), country);
|
||||
}
|
||||
return Locale.getDefault();
|
||||
}
|
||||
|
||||
private boolean checkIfLandscape() {
|
||||
DisplayMetrics displayMetrics = new DisplayMetrics();
|
||||
getActivity().getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ package org.schabi.newpipe;
|
|||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.support.v4.app.NavUtils;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.support.v7.widget.SearchView;
|
||||
|
|
@ -171,7 +172,13 @@ public class VideoItemListActivity extends AppCompatActivity
|
|||
}
|
||||
}
|
||||
|
||||
SettingsActivity.initSettings(this);
|
||||
PreferenceManager.setDefaultValues(this, R.xml.settings, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
App.checkStartTor(this);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -66,6 +66,9 @@ public class VideoItemListFragment extends ListFragment {
|
|||
|
||||
private View footer;
|
||||
|
||||
// used to suppress request for loading a new page while another page is already loading.
|
||||
private boolean loadingNextPage = true;
|
||||
|
||||
private class ResultRunnable implements Runnable {
|
||||
private final SearchEngine.Result result;
|
||||
private final int requestId;
|
||||
|
|
@ -76,6 +79,9 @@ public class VideoItemListFragment extends ListFragment {
|
|||
@Override
|
||||
public void run() {
|
||||
updateListOnResult(result, requestId);
|
||||
if (android.os.Build.VERSION.SDK_INT >= 19) {
|
||||
getListView().removeFooterView(footer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -84,7 +90,7 @@ public class VideoItemListFragment extends ListFragment {
|
|||
private final String query;
|
||||
private final int page;
|
||||
final Handler h = new Handler();
|
||||
private volatile boolean run = true;
|
||||
private volatile boolean runs = true;
|
||||
private final int requestId;
|
||||
public SearchRunnable(SearchEngine engine, String query, int page, int requestId) {
|
||||
this.engine = engine;
|
||||
|
|
@ -93,17 +99,18 @@ public class VideoItemListFragment extends ListFragment {
|
|||
this.requestId = requestId;
|
||||
}
|
||||
void terminate() {
|
||||
run = false;
|
||||
runs = false;
|
||||
}
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getContext());
|
||||
String searchLanguageKey = getContext().getString(R.string.searchLanguage);
|
||||
String searchLanguage = sp.getString(searchLanguageKey, "en");
|
||||
String searchLanguageKey = getContext().getString(R.string.search_language_key);
|
||||
String searchLanguage = sp.getString(searchLanguageKey,
|
||||
getString(R.string.default_language_value));
|
||||
SearchEngine.Result result = engine.search(query, page, searchLanguage);
|
||||
Log.i(TAG, "language code passed:\""+searchLanguage+"\"");
|
||||
if(run) {
|
||||
if(runs) {
|
||||
h.post(new ResultRunnable(result, requestId));
|
||||
}
|
||||
} catch(Exception e) {
|
||||
|
|
@ -111,19 +118,11 @@ public class VideoItemListFragment extends ListFragment {
|
|||
h.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Toast.makeText(getActivity(), "Network Error", Toast.LENGTH_SHORT).show();
|
||||
Toast.makeText(getActivity(), getString(R.string.network_error),
|
||||
Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
});
|
||||
}
|
||||
getActivity().runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (android.os.Build.VERSION.SDK_INT >= 19) {
|
||||
getListView().removeFooterView(footer);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -203,8 +202,9 @@ public class VideoItemListFragment extends ListFragment {
|
|||
}
|
||||
|
||||
private void nextPage() {
|
||||
loadingNextPage = true;
|
||||
lastPage++;
|
||||
Log.d(TAG, getString(R.string.searchPage) + Integer.toString(lastPage));
|
||||
Log.d(TAG, getString(R.string.search_page) + Integer.toString(lastPage));
|
||||
startSearch(query, lastPage);
|
||||
}
|
||||
|
||||
|
|
@ -228,7 +228,7 @@ public class VideoItemListFragment extends ListFragment {
|
|||
Toast.makeText(getActivity(), result.errorMessage, Toast.LENGTH_LONG).show();
|
||||
} else {
|
||||
if (!result.suggestion.isEmpty()) {
|
||||
Toast.makeText(getActivity(), getString(R.string.didYouMean) + result.suggestion + " ?",
|
||||
Toast.makeText(getActivity(), getString(R.string.did_you_mean) + result.suggestion + " ?",
|
||||
Toast.LENGTH_LONG).show();
|
||||
}
|
||||
updateList(result.resultList);
|
||||
|
|
@ -248,6 +248,8 @@ public class VideoItemListFragment extends ListFragment {
|
|||
Log.w(TAG, "Trying to set value while activity doesn't exist anymore.");
|
||||
} catch(Exception e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
loadingNextPage = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -297,7 +299,8 @@ public class VideoItemListFragment extends ListFragment {
|
|||
super.onViewCreated(view, savedInstanceState);
|
||||
list = getListView();
|
||||
videoListAdapter = new VideoListAdapter(getActivity(), this);
|
||||
footer = ((LayoutInflater) getActivity().getSystemService(Context.LAYOUT_INFLATER_SERVICE)).inflate(R.layout.paginate_footer, null, false);
|
||||
footer = ((LayoutInflater) getActivity().getSystemService(Context.LAYOUT_INFLATER_SERVICE))
|
||||
.inflate(R.layout.paginate_footer, null, false);
|
||||
|
||||
|
||||
setListAdapter(videoListAdapter);
|
||||
|
|
@ -318,13 +321,15 @@ public class VideoItemListFragment extends ListFragment {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
|
||||
public void onScroll(AbsListView view, int firstVisibleItem,
|
||||
int visibleItemCount, int totalItemCount) {
|
||||
if (mode != PRESENT_VIDEOS_MODE
|
||||
&& list.getChildAt(0) != null
|
||||
&& list.getLastVisiblePosition() == list.getAdapter().getCount() - 1
|
||||
&& list.getChildAt(list.getChildCount() - 1).getBottom() <= list.getHeight()) {
|
||||
long time = System.currentTimeMillis();
|
||||
if ((time - lastScrollDate) > 200) {
|
||||
if ((time - lastScrollDate) > 200
|
||||
&& !loadingNextPage) {
|
||||
lastScrollDate = time;
|
||||
getListView().addFooterView(footer);
|
||||
nextPage();
|
||||
|
|
|
|||
|
|
@ -96,10 +96,10 @@ class VideoListAdapter extends BaseAdapter {
|
|||
|
||||
@Override
|
||||
public View getView(int position, View convertView, ViewGroup parent) {
|
||||
convertView = viewCreator.getViewFromVideoInfoItem(convertView, parent, videoList.get(position));
|
||||
convertView = viewCreator.getViewFromVideoInfoItem(convertView, parent, videoList.get(position), context);
|
||||
|
||||
if(listView.isItemChecked(position)) {
|
||||
convertView.setBackgroundColor(ContextCompat.getColor(context,R.color.primaryColorYoutube));
|
||||
convertView.setBackgroundColor(ContextCompat.getColor(context,R.color.light_youtube_primary_color));
|
||||
} else {
|
||||
convertView.setBackgroundColor(0);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -106,7 +106,7 @@ public abstract class VideoExtractor {
|
|||
return videoInfo;
|
||||
}
|
||||
|
||||
|
||||
//todo: add licence field
|
||||
public abstract int getErrorCode();
|
||||
public abstract String getErrorMessage();
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue