Merge branch 'final-whitelabel-features' into 'master'

final whitelabel features

See merge request fdroid/fdroidclient!695
This commit is contained in:
Hans-Christoph Steiner 2018-06-27 20:25:32 +00:00
commit 56cbcd386c
13 changed files with 287 additions and 17 deletions

View File

@ -24,6 +24,16 @@
android:targetPackage="@string/applicationId"
android:targetClass="org.fdroid.fdroid.views.ManageReposActivity"/>
</android.support.v7.preference.PreferenceScreen>
<android.support.v7.preference.PreferenceScreen
android:key="installHistory"
android:visible="false"
android:title="@string/install_history"
android:summary="@string/install_history_summary">
<intent
android:action="android.intent.action.MAIN"
android:targetPackage="@string/applicationId"
android:targetClass="org.fdroid.fdroid.views.InstallHistoryActivity"/>
</android.support.v7.preference.PreferenceScreen>
</android.support.v7.preference.PreferenceCategory>
<android.support.v7.preference.PreferenceCategory android:title="@string/updates">
@ -110,13 +120,16 @@
<android.support.v7.preference.PreferenceCategory
android:key="pref_category_privacy"
android:title="@string/privacy">
<SwitchPreference
android:key="promptToSendCrashReports"
android:title="@string/prompt_to_send_crash_reports"
android:summary="@string/prompt_to_send_crash_reports_summary"
android:defaultValue="true"/>
<SwitchPreference
android:defaultValue="false"
android:key="preventScreenshots"
android:summary="@string/preventScreenshots_summary"
android:title="@string/preventScreenshots_title"/>
</android.support.v7.preference.PreferenceCategory>
<android.support.v7.preference.PreferenceCategory
@ -150,6 +163,12 @@
android:summary="@string/hide_all_notifications_summary"
android:defaultValue="false"
android:dependency="expert"/>
<CheckBoxPreference
android:key="sendVersionAndUUIDToServers"
android:title="@string/send_version_and_uuid"
android:summary="@string/send_version_and_uuid_summary"
android:defaultValue="false"
android:dependency="expert"/>
<CheckBoxPreference
android:key="forceOldIndex"
android:title="@string/force_old_index"

View File

@ -550,6 +550,12 @@
android:name="android.support.PARENT_ACTIVITY"
android:value=".views.main.MainActivity"/>
</activity>
<activity android:name=".views.InstallHistoryActivity"
android:parentActivityName=".views.main.MainActivity">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value=".views.main.MainActivity"/>
</activity>
<activity android:name=".AboutActivity" android:theme="@style/Theme.AppCompat.Light.Dialog"/>
<activity android:name=".installer.FileInstallerActivity" android:theme="@style/AppThemeTransparent"/>

View File

@ -1,5 +1,9 @@
/*
* Copyright (C) 2010-12 Ciaran Gultnieks, ciaran@ciarang.com
* Copyright (C) 2010-2012 Ciaran Gultnieks, ciaran@ciarang.com
* Copyright (C) 2013-2016 Peter Serwylo <peter@serwylo.com>
* Copyright (C) 2014-2018 Hans-Christoph Steiner <hans@eds.org>
* Copyright (C) 2015-2016 Daniel Martí <mvdan@mvdan.cc>
* Copyright (c) 2018 Senecto Limited
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -33,11 +37,13 @@ import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.res.Configuration;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Build;
import android.os.Environment;
import android.os.StrictMode;
import android.support.v4.util.LongSparseArray;
import android.text.TextUtils;
import android.util.Base64;
import android.util.Log;
import android.view.Display;
import android.view.WindowManager;
@ -66,14 +72,17 @@ import org.fdroid.fdroid.data.RepoProvider;
import org.fdroid.fdroid.installer.ApkFileProvider;
import org.fdroid.fdroid.installer.InstallHistoryService;
import org.fdroid.fdroid.net.ConnectivityMonitorService;
import org.fdroid.fdroid.net.HttpDownloader;
import org.fdroid.fdroid.net.ImageLoaderForUIL;
import org.fdroid.fdroid.net.WifiStateChangeService;
import org.fdroid.fdroid.views.hiding.HidingManager;
import javax.microedition.khronos.opengles.GL10;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.security.Security;
import java.util.List;
import java.util.UUID;
@ReportsCrashes(mailTo = "reports@f-droid.org",
mode = ReportingInteractionMode.DIALOG,
@ -341,9 +350,11 @@ public class FDroidApp extends Application {
Preferences.setup(this);
Languages.setLanguage(this);
ACRA.init(this);
if (isAcraProcess() || HidingManager.isHidden(this)) {
return;
if (Preferences.get().promptToSendCrashReports()) {
ACRA.init(this);
if (isAcraProcess() || HidingManager.isHidden(this)) {
return;
}
}
PRNGFixes.apply();
@ -480,6 +491,30 @@ public class FDroidApp extends Application {
UpdateService.forceUpdateRepo(this);
}
atStartTime.edit().putInt("build-version", Build.VERSION.SDK_INT).apply();
final String queryStringKey = "http-downloader-query-string";
if (Preferences.get().sendVersionAndUUIDToServers()) {
HttpDownloader.queryString = atStartTime.getString(queryStringKey, null);
if (HttpDownloader.queryString == null) {
UUID uuid = UUID.randomUUID();
ByteBuffer buffer = ByteBuffer.allocate(Long.SIZE / Byte.SIZE * 2);
buffer.putLong(uuid.getMostSignificantBits());
buffer.putLong(uuid.getLeastSignificantBits());
String id = Base64.encodeToString(buffer.array(),
Base64.URL_SAFE | Base64.NO_WRAP | Base64.NO_PADDING);
StringBuilder builder = new StringBuilder("id=").append(id);
String versionName = Uri.encode(Utils.getVersionName(this));
if (versionName != null) {
builder.append("&client_version=").append(versionName);
}
HttpDownloader.queryString = builder.toString();
}
if (!atStartTime.contains(queryStringKey)) {
atStartTime.edit().putString(queryStringKey, HttpDownloader.queryString).apply();
}
} else {
atStartTime.edit().remove(queryStringKey).apply();
}
}
/**

View File

@ -84,6 +84,7 @@ public final class Preferences implements SharedPreferences.OnSharedPreferenceCh
public static final String PREF_SHOW_ROOT_APPS = "rooted";
public static final String PREF_SHOW_ANTI_FEATURE_APPS = "showAntiFeatureApps";
public static final String PREF_FORCE_TOUCH_APPS = "ignoreTouchscreen";
public static final String PREF_PROMPT_TO_SEND_CRASH_REPORTS = "promptToSendCrashReports";
public static final String PREF_KEEP_CACHE_TIME = "keepCacheFor";
public static final String PREF_UNSTABLE_UPDATES = "unstableUpdates";
public static final String PREF_KEEP_INSTALL_HISTORY = "keepInstallHistory";
@ -106,6 +107,7 @@ public final class Preferences implements SharedPreferences.OnSharedPreferenceCh
public static final String PREF_PANIC_HIDE = "pref_panic_hide";
public static final String PREF_HIDE_ON_LONG_PRESS_SEARCH = "hideOnLongPressSearch";
public static final String PREF_HIDE_ALL_NOTIFICATIONS = "hideAllNotifications";
public static final String PREF_SEND_VERSION_AND_UUID_TO_SERVERS = "sendVersionAndUUIDToServers";
public static final int OVER_NETWORK_NEVER = 0;
public static final int OVER_NETWORK_ON_DEMAND = 1;
@ -172,6 +174,10 @@ public final class Preferences implements SharedPreferences.OnSharedPreferenceCh
initialized.put(key, false);
}
public boolean promptToSendCrashReports() {
return preferences.getBoolean(PREF_PROMPT_TO_SEND_CRASH_REPORTS, IGNORED_B);
}
public boolean isForceOldIndexEnabled() {
return preferences.getBoolean(PREF_FORCE_OLD_INDEX, IGNORED_B);
}
@ -498,6 +504,14 @@ public final class Preferences implements SharedPreferences.OnSharedPreferenceCh
return preferences.getBoolean(PREF_HIDE_ALL_NOTIFICATIONS, IGNORED_B);
}
/**
* Whether to include the version of this app and a randomly generated ID
* to the server when downloading from it.
*/
public boolean sendVersionAndUUIDToServers() {
return preferences.getBoolean(PREF_SEND_VERSION_AND_UUID_TO_SERVERS, IGNORED_B);
}
/**
* This is cached as it is called several times inside app list adapters.
* Providing it here means the shared preferences file only needs to be

View File

@ -111,12 +111,7 @@ public class RepoUpdater {
}
protected String getIndexUrl(@NonNull Repo repo) {
String url = repo.address + "/index.jar";
String versionName = Utils.getVersionName(context);
if (versionName != null) {
url += "?client_version=" + versionName;
}
return url;
return repo.address + "/index.jar";
}
public boolean hasChanged() {

View File

@ -28,7 +28,7 @@ import android.net.Uri;
import android.os.Process;
import android.support.v4.content.LocalBroadcastManager;
import android.text.TextUtils;
import org.fdroid.fdroid.BuildConfig;
import org.fdroid.fdroid.Utils;
import org.fdroid.fdroid.data.Apk;
@ -47,7 +47,8 @@ import java.util.List;
public class InstallHistoryService extends IntentService {
public static final String TAG = "InstallHistoryService";
public static final Uri LOG_URI = Uri.parse("content://org.fdroid.fdroid.installer/install_history/all");
public static final String AUTHORITY = BuildConfig.APPLICATION_ID + ".installer";
public static final Uri LOG_URI = Uri.parse("content://" + AUTHORITY + "/install_history/all");
private static BroadcastReceiver broadcastReceiver;

View File

@ -1,3 +1,24 @@
/*
* Copyright (C) 2014-2017 Peter Serwylo <peter@serwylo.com>
* Copyright (C) 2014-2018 Hans-Christoph Steiner <hans@eds.org>
* Copyright (C) 2015-2016 Daniel Martí <mvdan@mvdan.cc>
* Copyright (c) 2018 Senecto Limited
*
* 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, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package org.fdroid.fdroid.net;
import android.annotation.TargetApi;
@ -40,6 +61,11 @@ public class HttpDownloader extends Downloader {
private HttpURLConnection connection;
private boolean newFileAvailableOnServer;
/**
* String to append to all HTTP downloads, created in {@link FDroidApp#onCreate()}
*/
public static String queryString;
HttpDownloader(Uri uri, File destFile)
throws FileNotFoundException, MalformedURLException {
this(uri, destFile, null, null);
@ -142,7 +168,11 @@ public class HttpDownloader extends Downloader {
// swap never works with a proxy, its unrouted IP on the same subnet
connection = (HttpURLConnection) sourceUrl.openConnection();
} else {
connection = NetCipher.getHttpURLConnection(sourceUrl);
if (queryString != null) {
connection = NetCipher.getHttpURLConnection(new URL(urlString + "?" + queryString));
} else {
connection = NetCipher.getHttpURLConnection(sourceUrl);
}
}
connection.setRequestProperty("User-Agent", "F-Droid " + BuildConfig.VERSION_NAME);

View File

@ -0,0 +1,92 @@
/*
* Copyright (C) 2016 Blue Jay Wireless
* Copyright (C) 2018 Senecto Limited
*
* 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, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*/
package org.fdroid.fdroid.views;
import android.content.ContentResolver;
import android.database.Cursor;
import android.os.Bundle;
import android.os.ParcelFileDescriptor;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.TextView;
import org.apache.commons.io.IOUtils;
import org.fdroid.fdroid.R;
import org.fdroid.fdroid.installer.InstallHistoryService;
import java.io.FileDescriptor;
import java.io.FileInputStream;
import java.io.IOException;
import java.nio.charset.Charset;
public class InstallHistoryActivity extends AppCompatActivity {
public static final String TAG = "InstallHistoryActivity";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_install_history);
Toolbar toolbar = findViewById(R.id.toolbar);
toolbar.setTitle(getString(R.string.install_history));
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
String text = "";
try {
ContentResolver resolver = getContentResolver();
Cursor cursor = resolver.query(InstallHistoryService.LOG_URI, null, null, null, null);
if (cursor != null) {
cursor.moveToFirst();
cursor.close();
}
ParcelFileDescriptor pfd = resolver.openFileDescriptor(InstallHistoryService.LOG_URI, "r");
FileDescriptor fd = pfd.getFileDescriptor();
FileInputStream fileInputStream = new FileInputStream(fd);
text = IOUtils.toString(fileInputStream, Charset.defaultCharset());
} catch (IOException | SecurityException | IllegalStateException e) {
e.printStackTrace();
}
TextView textView = findViewById(R.id.text);
textView.setText(text);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.install_history, menu);
return super.onCreateOptionsMenu(menu);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.menu_delete:
getContentResolver().delete(InstallHistoryService.LOG_URI, null, null);
TextView textView = findViewById(R.id.text);
textView.setText("");
break;
}
return super.onOptionsItemSelected(item);
}
}

View File

@ -337,10 +337,13 @@ public class PreferencesFragment extends PreferenceFragment
case Preferences.PREF_KEEP_INSTALL_HISTORY:
CheckBoxPreference p = (CheckBoxPreference) findPreference(key);
Preference installHistory = findPreference("installHistory");
if (p.isChecked()) {
InstallHistoryService.register(getActivity());
installHistory.setVisible(true);
} else {
InstallHistoryService.unregister(getActivity());
installHistory.setVisible(false);
}
break;
}

View File

@ -0,0 +1,40 @@
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".views.InstallHistoryActivity">
<android.support.design.widget.AppBarLayout
android:id="@+id/app_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="@style/AppThemeLight.AppBarOverlay">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"/>
</android.support.design.widget.AppBarLayout>
<android.support.v4.widget.NestedScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
tools:context=".views.InstallHistoryActivity"
tools:showIn="@layout/activity_install_history">
<TextView
android:id="@+id/text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="16dp"/>
</android.support.v4.widget.NestedScrollView>
</android.support.design.widget.CoordinatorLayout>

View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/menu_delete"
android:icon="@android:drawable/ic_delete"
android:title="@string/delete"/>
</menu>

View File

@ -12,6 +12,10 @@
<string name="by_author_format">by %s</string>
<string name="delete">Delete</string>
<string name="enable_nfc_send">Enable NFC Send…</string>
<string name="prompt_to_send_crash_reports">Prompt to send crash reports</string>
<string name="prompt_to_send_crash_reports_summary">Gather data about crashes and ask to send them to the
developer
</string>
<string name="cache_downloaded">Keep cached apps</string>
<string name="updates">Updates</string>
<string name="unstable_updates">Unstable updates</string>
@ -20,8 +24,13 @@
<string name="hide_all_notifications_summary">Prevent all actions from showing in the status bar and notification
drawer.
</string>
<string name="install_history">Install history</string>
<string name="install_history_summary">View the private log of all installs and uninstalls</string>
<string name="keep_install_history">Keep install history</string>
<string name="keep_install_history_summary">Store a log of all installs and uninstalls in a private store</string>
<string name="send_version_and_uuid">Send version and UUID to servers</string>
<string name="send_version_and_uuid_summary">Include this app\'s version and a random, unique ID when
downloading, takes affect next app restart.</string>
<string name="force_old_index">Force old index format</string>
<string name="force_old_index_summary">In case there are bugs or compatibility issues, use the XML app index</string>
<string name="other">Other</string>

View File

@ -24,6 +24,16 @@
android:targetPackage="@string/applicationId"
android:targetClass="org.fdroid.fdroid.views.ManageReposActivity"/>
</android.support.v7.preference.PreferenceScreen>
<android.support.v7.preference.PreferenceScreen
android:key="installHistory"
android:visible="false"
android:title="@string/install_history"
android:summary="@string/install_history_summary">
<intent
android:action="android.intent.action.MAIN"
android:targetPackage="@string/applicationId"
android:targetClass="org.fdroid.fdroid.views.InstallHistoryActivity"/>
</android.support.v7.preference.PreferenceScreen>
</android.support.v7.preference.PreferenceCategory>
<android.support.v7.preference.PreferenceCategory android:title="@string/updates">
@ -116,7 +126,11 @@
<android.support.v7.preference.PreferenceCategory
android:key="pref_category_privacy"
android:title="@string/privacy">
<SwitchPreference
android:key="promptToSendCrashReports"
android:title="@string/prompt_to_send_crash_reports"
android:summary="@string/prompt_to_send_crash_reports_summary"
android:defaultValue="true"/>
<SwitchPreference
android:defaultValue="false"
android:key="preventScreenshots"
@ -137,7 +151,6 @@
android:targetClass="org.fdroid.fdroid.views.panic.PanicPreferencesActivity"
android:targetPackage="@string/applicationId"/>
</android.support.v7.preference.PreferenceScreen>
</android.support.v7.preference.PreferenceCategory>
<android.support.v7.preference.PreferenceCategory
@ -171,6 +184,12 @@
android:summary="@string/hide_all_notifications_summary"
android:defaultValue="false"
android:dependency="expert"/>
<CheckBoxPreference
android:key="sendVersionAndUUIDToServers"
android:title="@string/send_version_and_uuid"
android:summary="@string/send_version_and_uuid_summary"
android:defaultValue="false"
android:dependency="expert"/>
<CheckBoxPreference
android:key="forceOldIndex"
android:title="@string/force_old_index"