Merge branch 'eximport' into dev

This commit is contained in:
Christian Schabesberger 2018-02-04 13:40:03 +01:00
commit 87ba5a7eb6
7 changed files with 316 additions and 75 deletions

View File

@ -1,9 +1,12 @@
package org.schabi.newpipe; package org.schabi.newpipe;
import android.app.AlarmManager;
import android.app.Application; import android.app.Application;
import android.app.NotificationChannel; import android.app.NotificationChannel;
import android.app.NotificationManager; import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context; import android.content.Context;
import android.content.Intent;
import android.os.Build; import android.os.Build;
import android.util.Log; import android.util.Log;
@ -116,7 +119,6 @@ public class App extends Application {
}); });
} }
private void initACRA() { private void initACRA() {
try { try {
final ACRAConfiguration acraConfig = new ConfigurationBuilder(this) final ACRAConfiguration acraConfig = new ConfigurationBuilder(this)
@ -149,4 +151,5 @@ public class App extends Application {
NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
mNotificationManager.createNotificationChannel(mChannel); mNotificationManager.createNotificationChannel(mChannel);
} }
} }

View File

@ -1,9 +1,14 @@
package org.schabi.newpipe.settings; package org.schabi.newpipe.settings;
import android.app.Activity; import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle; import android.os.Bundle;
import android.support.v7.preference.ListPreference; import android.support.v7.preference.ListPreference;
import android.support.v7.preference.Preference; import android.support.v7.preference.Preference;
import android.util.Log;
import android.widget.Toast;
import org.schabi.newpipe.R; import org.schabi.newpipe.R;
import org.schabi.newpipe.extractor.NewPipe; import org.schabi.newpipe.extractor.NewPipe;
@ -12,19 +17,47 @@ import org.schabi.newpipe.extractor.exceptions.ExtractionException;
import org.schabi.newpipe.report.ErrorActivity; import org.schabi.newpipe.report.ErrorActivity;
import org.schabi.newpipe.report.UserAction; import org.schabi.newpipe.report.UserAction;
import org.schabi.newpipe.util.Constants; import org.schabi.newpipe.util.Constants;
import org.schabi.newpipe.util.FilePickerActivityHelper;
import org.schabi.newpipe.util.KioskTranslator; import org.schabi.newpipe.util.KioskTranslator;
import org.schabi.newpipe.util.ZipHelper;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import java.util.zip.ZipFile;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;
import javax.annotation.Nonnull;
public class ContentSettingsFragment extends BasePreferenceFragment { public class ContentSettingsFragment extends BasePreferenceFragment {
private static final int REQUEST_IMPORT_PATH = 8945;
private static final int REQUEST_EXPORT_PATH = 30945;
private String homeDir;
private File databasesDir;
private File newpipe_db;
private File newpipe_db_journal;
@Override @Override
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) { public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
homeDir = getActivity().getApplicationInfo().dataDir;
databasesDir = new File(homeDir + "/databases");
newpipe_db = new File(homeDir + "/databases/newpipe.db");
newpipe_db_journal = new File(homeDir + "/databases/newpipe.db-journal");
addPreferencesFromResource(R.xml.content_settings); addPreferencesFromResource(R.xml.content_settings);
final ListPreference mainPageContentPref = (ListPreference) findPreference(getString(R.string.main_page_content_key)); final ListPreference mainPageContentPref = (ListPreference) findPreference(getString(R.string.main_page_content_key));
mainPageContentPref.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() { mainPageContentPref.setOnPreferenceChangeListener((Preference preference, Object newValueO) -> {
@Override
public boolean onPreferenceChange(Preference preference, Object newValueO) {
final String newValue = newValueO.toString(); final String newValue = newValueO.toString();
final String mainPrefOldValue = final String mainPrefOldValue =
@ -33,9 +66,7 @@ public class ContentSettingsFragment extends BasePreferenceFragment {
if(newValue.equals(getString(R.string.kiosk_page_key))) { if(newValue.equals(getString(R.string.kiosk_page_key))) {
SelectKioskFragment selectKioskFragment = new SelectKioskFragment(); SelectKioskFragment selectKioskFragment = new SelectKioskFragment();
selectKioskFragment.setOnSelectedLisener(new SelectKioskFragment.OnSelectedLisener() { selectKioskFragment.setOnSelectedLisener((String kioskId, int service_id) -> {
@Override
public void onKioskSelected(String kioskId, int service_id) {
defaultPreferences.edit() defaultPreferences.edit()
.putInt(getString(R.string.main_page_selected_service), service_id).apply(); .putInt(getString(R.string.main_page_selected_service), service_id).apply();
defaultPreferences.edit() defaultPreferences.edit()
@ -55,21 +86,15 @@ public class ContentSettingsFragment extends BasePreferenceFragment {
kioskName); kioskName);
mainPageContentPref.setSummary(summary); mainPageContentPref.setSummary(summary);
}
}); });
selectKioskFragment.setOnCancelListener(new SelectKioskFragment.OnCancelListener() { selectKioskFragment.setOnCancelListener(() -> {
@Override
public void onCancel() {
mainPageContentPref.setSummary(mainPrefOldSummary); mainPageContentPref.setSummary(mainPrefOldSummary);
mainPageContentPref.setValue(mainPrefOldValue); mainPageContentPref.setValue(mainPrefOldValue);
}
}); });
selectKioskFragment.show(getFragmentManager(), "select_kiosk"); selectKioskFragment.show(getFragmentManager(), "select_kiosk");
} else if(newValue.equals(getString(R.string.channel_page_key))) { } else if(newValue.equals(getString(R.string.channel_page_key))) {
SelectChannelFragment selectChannelFragment = new SelectChannelFragment(); SelectChannelFragment selectChannelFragment = new SelectChannelFragment();
selectChannelFragment.setOnSelectedLisener(new SelectChannelFragment.OnSelectedLisener() { selectChannelFragment.setOnSelectedLisener((String url, String name, int service) -> {
@Override
public void onChannelSelected(String url, String name, int service) {
defaultPreferences.edit() defaultPreferences.edit()
.putInt(getString(R.string.main_page_selected_service), service).apply(); .putInt(getString(R.string.main_page_selected_service), service).apply();
defaultPreferences.edit() defaultPreferences.edit()
@ -78,14 +103,10 @@ public class ContentSettingsFragment extends BasePreferenceFragment {
.putString(getString(R.string.main_page_selected_channel_name), name).apply(); .putString(getString(R.string.main_page_selected_channel_name), name).apply();
mainPageContentPref.setSummary(name); mainPageContentPref.setSummary(name);
}
}); });
selectChannelFragment.setOnCancelListener(new SelectChannelFragment.OnCancelListener() { selectChannelFragment.setOnCancelListener(() -> {
@Override
public void onCancel() {
mainPageContentPref.setSummary(mainPrefOldSummary); mainPageContentPref.setSummary(mainPrefOldSummary);
mainPageContentPref.setValue(mainPrefOldValue); mainPageContentPref.setValue(mainPrefOldValue);
}
}); });
selectChannelFragment.show(getFragmentManager(), "select_channel"); selectChannelFragment.show(getFragmentManager(), "select_channel");
} else { } else {
@ -95,8 +116,109 @@ public class ContentSettingsFragment extends BasePreferenceFragment {
defaultPreferences.edit().putBoolean(Constants.KEY_MAIN_PAGE_CHANGE, true).apply(); defaultPreferences.edit().putBoolean(Constants.KEY_MAIN_PAGE_CHANGE, true).apply();
return true; return true;
}
}); });
Preference importDataPreference = findPreference(getString(R.string.import_data));
importDataPreference.setOnPreferenceClickListener((Preference p) -> {
Intent i = new Intent(getActivity(), FilePickerActivityHelper.class)
.putExtra(FilePickerActivityHelper.EXTRA_ALLOW_MULTIPLE, false)
.putExtra(FilePickerActivityHelper.EXTRA_ALLOW_CREATE_DIR, false)
.putExtra(FilePickerActivityHelper.EXTRA_MODE, FilePickerActivityHelper.MODE_FILE);
startActivityForResult(i, REQUEST_IMPORT_PATH);
return true;
});
Preference exportDataPreference = findPreference(getString(R.string.export_data));
exportDataPreference.setOnPreferenceClickListener((Preference p) -> {
Intent i = new Intent(getActivity(), FilePickerActivityHelper.class)
.putExtra(FilePickerActivityHelper.EXTRA_ALLOW_MULTIPLE, false)
.putExtra(FilePickerActivityHelper.EXTRA_ALLOW_CREATE_DIR, true)
.putExtra(FilePickerActivityHelper.EXTRA_MODE, FilePickerActivityHelper.MODE_DIR);
startActivityForResult(i, REQUEST_EXPORT_PATH);
return true;
});
}
@Override
public void onActivityResult(int requestCode, int resultCode, @Nonnull Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (DEBUG) {
Log.d(TAG, "onActivityResult() called with: requestCode = [" + requestCode + "], resultCode = [" + resultCode + "], data = [" + data + "]");
}
if ((requestCode == REQUEST_IMPORT_PATH || requestCode == REQUEST_EXPORT_PATH)
&& resultCode == Activity.RESULT_OK) {
String path = data.getData().getPath();
if (requestCode == REQUEST_EXPORT_PATH) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.US);
exportDatabase(path + "/NewPipeData-" + sdf.format(new Date()) + ".zip");
} else {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setMessage(R.string.override_current_data)
.setPositiveButton(android.R.string.ok,
(DialogInterface d, int id) -> importDatabase(path))
.setNegativeButton(android.R.string.cancel,
(DialogInterface d, int id) -> d.cancel());
builder.create().show();
}
}
}
private void exportDatabase(String path) {
try {
ZipOutputStream outZip = new ZipOutputStream(
new BufferedOutputStream(
new FileOutputStream(path)));
ZipHelper.addFileToZip(outZip, newpipe_db.getPath(), "newpipe.db");
ZipHelper.addFileToZip(outZip, newpipe_db_journal.getPath(), "newpipe.db-journal");
outZip.close();
Toast.makeText(getContext(), R.string.export_complete_toast, Toast.LENGTH_SHORT)
.show();
} catch (Exception e) {
onError(e);
}
}
private void importDatabase(String filePath) {
// check if file is supported
ZipFile zipFile = null;
try {
zipFile = new ZipFile(filePath);
} catch (IOException ioe) {
Toast.makeText(getContext(), R.string.no_valid_zip_file, Toast.LENGTH_SHORT)
.show();
return;
} finally {
try {
zipFile.close();
} catch (Exception e){}
}
try {
ZipInputStream zipIn = new ZipInputStream(
new BufferedInputStream(
new FileInputStream(filePath)));
if (!databasesDir.exists() && !databasesDir.mkdir()) {
throw new Exception("Could not create databases dir");
}
if(!(ZipHelper.extractFileFromZip(zipIn, newpipe_db.getPath(), "newpipe.db")
&& ZipHelper.extractFileFromZip(zipIn, newpipe_db_journal.getPath(), "newpipe.db-journal"))) {
Toast.makeText(getContext(), R.string.could_not_import_all_files, Toast.LENGTH_LONG)
.show();
}
zipIn.close();
// restart app to properly load db
//App.restart(getContext());
System.exit(0);
} catch (Exception e) {
onError(e);
}
} }
@Override @Override

View File

@ -46,7 +46,8 @@ public class DownloadSettingsFragment extends BasePreferenceFragment {
Log.d(TAG, "onPreferenceTreeClick() called with: preference = [" + preference + "]"); 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) Intent i = new Intent(getActivity(), FilePickerActivityHelper.class)
.putExtra(FilePickerActivityHelper.EXTRA_ALLOW_MULTIPLE, false) .putExtra(FilePickerActivityHelper.EXTRA_ALLOW_MULTIPLE, false)
.putExtra(FilePickerActivityHelper.EXTRA_ALLOW_CREATE_DIR, true) .putExtra(FilePickerActivityHelper.EXTRA_ALLOW_CREATE_DIR, true)

View File

@ -0,0 +1,94 @@
package org.schabi.newpipe.util;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;
/**
* Created by Christian Schabesberger on 28.01.18.
* Copyright 2018 Christian Schabesberger <chris.schabesberger@mailbox.org>
* ZipHelper.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 ZipHelper {
private static final int BUFFER_SIZE = 2048;
/**
* This function helps to create zip files.
* Caution this will override the original file.
* @param outZip The ZipOutputStream where the data should be stored in
* @param file The path of the file that should be added to zip.
* @param name The path of the file inside the zip.
* @throws Exception
*/
public static void addFileToZip(ZipOutputStream outZip, String file, String name) throws Exception {
byte data[] = new byte[BUFFER_SIZE];
FileInputStream fi = new FileInputStream(file);
BufferedInputStream inputStream = new BufferedInputStream(fi, BUFFER_SIZE);
ZipEntry entry = new ZipEntry(name);
outZip.putNextEntry(entry);
int count;
while((count = inputStream.read(data, 0, BUFFER_SIZE)) != -1) {
outZip.write(data, 0, count);
}
inputStream.close();
}
/**
* This will extract data from Zipfiles.
* Caution this will override the original file.
* @param inZip The ZipOutputStream where the data is stored in
* @param file The path of the file on the disk where the data should be extracted to.
* @param name The path of the file inside the zip.
* @return will return true if the file was found within the zip file
* @throws Exception
*/
public static boolean extractFileFromZip(ZipInputStream inZip, String file, String name) throws Exception {
byte data[] = new byte[BUFFER_SIZE];
boolean found = false;
ZipEntry ze;
while((ze = inZip.getNextEntry()) != null) {
if(ze.getName().equals(name)) {
found = true;
// delete old file first
File oldFile = new File(file);
if(oldFile.exists()) {
if(!oldFile.delete()) {
throw new Exception("Could not delete " + file);
}
}
FileOutputStream outFile = new FileOutputStream(file);
int count = 0;
while((count = inZip.read(data)) != -1) {
outFile.write(data, 0, count);
}
outFile.close();
inZip.closeEntry();
}
}
return true;
}
}

View File

@ -130,6 +130,8 @@
<string name="main_page_selected_channel_name" translatable="false">main_page_selected_channel_name</string> <string name="main_page_selected_channel_name" translatable="false">main_page_selected_channel_name</string>
<string name="main_page_selected_channel_url" translatable="false">main_page_selected_channel_url</string> <string name="main_page_selected_channel_url" translatable="false">main_page_selected_channel_url</string>
<string name="main_page_selectd_kiosk_id" translatable="false">main_page_selectd_kiosk_id</string> <string name="main_page_selectd_kiosk_id" translatable="false">main_page_selectd_kiosk_id</string>
<string name="import_data">import_data</string>
<string name="export_data">export_data</string>
<!-- FileName Downloads --> <!-- FileName Downloads -->
<string name="settings_file_charset_key" translatable="false">file_rename</string> <string name="settings_file_charset_key" translatable="false">file_rename</string>

View File

@ -134,6 +134,10 @@
<string name="switch_to_popup">Switch to Popup</string> <string name="switch_to_popup">Switch to Popup</string>
<string name="switch_to_main">Switch to Main</string> <string name="switch_to_main">Switch to Main</string>
<string name="import_data_title">Import database</string>
<string name="export_data_title">Export database</string>
<string name="import_data_summary">Will override your current history and subscriptions</string>
<string name="export_data_summary">Export history, subscriptions and playlists.</string>
<!-- error strings --> <!-- error strings -->
<string name="general_error">Error</string> <string name="general_error">Error</string>
<string name="network_error">Network error</string> <string name="network_error">Network error</string>
@ -317,6 +321,11 @@
<string name="select_a_channel">Select a channel</string> <string name="select_a_channel">Select a channel</string>
<string name="no_channel_subscribed_yet">No channel subscribed yet</string> <string name="no_channel_subscribed_yet">No channel subscribed yet</string>
<string name="select_a_kiosk">Select a kiosk</string> <string name="select_a_kiosk">Select a kiosk</string>
<string name="export_complete_toast">Export complete</string>
<string name="import_complete_toast">Import complete</string>
<string name="no_valid_zip_file">No valid Zip file</string>
<string name="could_not_import_all_files">WARNING: Could not import all files.</string>
<string name="override_current_data">This will override your current setup.</string>
<!-- Kiosk Names --> <!-- Kiosk Names -->
<string name="kiosk">Kiosk</string> <string name="kiosk">Kiosk</string>

View File

@ -37,4 +37,14 @@
android:key="@string/main_page_content_key" android:key="@string/main_page_content_key"
android:title="@string/main_page_content" android:title="@string/main_page_content"
android:summary="%s"/> android:summary="%s"/>
<Preference
android:summary="@string/import_data_summary"
android:key="@string/import_data"
android:title="@string/import_data_title"/>
<Preference
android:title="@string/export_data_title"
android:key="@string/export_data"
android:summary="@string/export_data_summary"/>
</PreferenceScreen> </PreferenceScreen>