Compare commits
1 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
36902eac49 |
24
CHANGELOG.md
@ -1,27 +1,3 @@
|
||||
### 1.13-alpha1 (2021-06-02)
|
||||
|
||||
* Stop repeated updates of Trichrome Library
|
||||
|
||||
* More changes to follow Material Design (@proletarius101)
|
||||
|
||||
* Improve OpenCollective badge (@ConnyDuck)
|
||||
|
||||
### 1.13-alpha0 (2021-04-22)
|
||||
|
||||
* Theme support tied to built-in Android themes (@proletarius101)
|
||||
|
||||
* New top banner notifications: "No Internet" and "No Data or WiFi enabled"
|
||||
|
||||
* Improved handling of USB-OTG and SD Card repos and mirrors
|
||||
|
||||
### 1.12.1 (2021-04-12)
|
||||
|
||||
* Fix trove4j verification error
|
||||
|
||||
### 1.12 (2021-04-06)
|
||||
|
||||
* Sync translations
|
||||
|
||||
### 1.12-alpha3 (2021-03-10)
|
||||
|
||||
* Opt-in F-Droid Metrics
|
||||
|
@ -1,6 +1,6 @@
|
||||
# F-Droid Client
|
||||
|
||||
[](https://gitlab.com/fdroid/fdroidclient/-/jobs)
|
||||
[](https://gitlab.com/fdroid/fdroidclient/builds)
|
||||
[](https://hosted.weblate.org/engage/f-droid/)
|
||||
|
||||
Client for [F-Droid](https://f-droid.org), the Free Software repository system
|
||||
|
@ -21,16 +21,16 @@ def basicApplicationId = "org.fdroid.basic"
|
||||
def privilegedExtensionApplicationId = '"org.fdroid.fdroid.privileged"'
|
||||
|
||||
android {
|
||||
compileSdkVersion 30
|
||||
compileSdkVersion 29
|
||||
|
||||
defaultConfig {
|
||||
versionCode 1013001
|
||||
versionCode 1012050
|
||||
versionName getVersionName()
|
||||
|
||||
testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner'
|
||||
minSdkVersion 24
|
||||
minSdkVersion 14
|
||||
//noinspection ExpiredTargetSdkVersion
|
||||
targetSdkVersion 28
|
||||
targetSdkVersion 25
|
||||
/*
|
||||
The Android Testing Support Library collects analytics to continuously improve the testing
|
||||
experience. More specifically, it uploads a hash of the package name of the application
|
||||
@ -38,7 +38,6 @@ android {
|
||||
passing the following argument to the test runner: disableAnalytics "true".
|
||||
*/
|
||||
testInstrumentationRunnerArguments disableAnalytics: 'true'
|
||||
vectorDrawables.useSupportLibrary = true
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
@ -142,9 +141,10 @@ android {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation 'androidx.appcompat:appcompat:1.3.0'
|
||||
implementation 'androidx.appcompat:appcompat:1.1.0'
|
||||
implementation 'androidx.preference:preference:1.1.1'
|
||||
implementation 'androidx.gridlayout:gridlayout:1.0.0'
|
||||
implementation 'androidx.annotation:annotation:1.1.0'
|
||||
implementation 'androidx.recyclerview:recyclerview:1.1.0'
|
||||
implementation 'androidx.cardview:cardview:1.0.0'
|
||||
implementation 'androidx.vectordrawable:vectordrawable:1.1.0'
|
||||
@ -152,19 +152,18 @@ dependencies {
|
||||
implementation 'androidx.palette:palette:1.0.0'
|
||||
implementation 'androidx.work:work-runtime:2.4.0'
|
||||
|
||||
implementation 'com.google.android.material:material:1.3.0'
|
||||
implementation 'com.google.android.material:material:1.1.0'
|
||||
|
||||
implementation 'com.nostra13.universalimageloader:universal-image-loader:1.9.5'
|
||||
implementation 'com.google.zxing:core:3.3.3'
|
||||
implementation 'info.guardianproject.netcipher:netcipher:2.2.0-alpha'
|
||||
implementation 'info.guardianproject.netcipher:netcipher:2.0.0-beta1'
|
||||
implementation 'info.guardianproject.panic:panic:1.0'
|
||||
implementation 'commons-io:commons-io:2.6'
|
||||
implementation 'commons-net:commons-net:3.6'
|
||||
implementation 'ch.acra:acra:4.9.1'
|
||||
implementation 'io.reactivex:rxjava:1.1.0'
|
||||
implementation 'com.hannesdorfmann:adapterdelegates3:3.0.1'
|
||||
|
||||
implementation 'io.reactivex.rxjava3:rxandroid:3.0.0'
|
||||
implementation 'io.reactivex.rxjava3:rxjava:3.0.9'
|
||||
implementation 'com.ashokvarma.android:bottom-navigation-bar:2.0.5'
|
||||
|
||||
implementation 'com.fasterxml.jackson.core:jackson-core:2.11.1'
|
||||
implementation 'com.fasterxml.jackson.core:jackson-annotations:2.11.1'
|
||||
|
7
app/proguard-rules.pro
vendored
@ -31,6 +31,13 @@
|
||||
public *;
|
||||
}
|
||||
|
||||
# The rxjava library depends on sun.misc.Unsafe, which is unavailable on Android
|
||||
# The rxjava team is aware of this, and mention in the docs that they only use
|
||||
# the unsafe functionality if the platform supports it.
|
||||
# - https://github.com/ReactiveX/RxJava/issues/1415#issuecomment-48390883
|
||||
# - https://github.com/ReactiveX/RxJava/blob/1.x/src/main/java/rx/internal/util/unsafe/UnsafeAccess.java#L23
|
||||
-dontwarn rx.internal.util.**
|
||||
|
||||
-keepattributes *Annotation*,EnclosingMethod,Signature
|
||||
-keepnames class com.fasterxml.jackson.** { *; }
|
||||
-dontwarn com.fasterxml.jackson.databind.ext.**
|
||||
|
@ -1,24 +1,18 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<!-- package name must be unique so suffix with "tests" so package loader doesn't ignore us -->
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
package="org.fdroid.fdroid.tests"
|
||||
android:versionCode="1"
|
||||
android:versionName="1.0">
|
||||
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
package="org.fdroid.fdroid.tests"
|
||||
android:versionCode="1"
|
||||
android:versionName="1.0">
|
||||
<uses-sdk tools:overrideLibrary="android_libs.ub_uiautomator" />
|
||||
|
||||
<!-- We add an application tag here just so that we can indicate that
|
||||
this package needs to link against the android.test library,
|
||||
which is needed when building test cases. -->
|
||||
<application>
|
||||
<uses-library
|
||||
android:name="android.test.runner"
|
||||
<uses-library android:name="android.test.runner"
|
||||
android:required="false" />
|
||||
</application>
|
||||
|
||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||
|
||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
|
||||
</manifest>
|
||||
|
@ -21,7 +21,7 @@ import androidx.test.uiautomator.UiObjectNotFoundException;
|
||||
import androidx.test.uiautomator.UiSelector;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import org.fdroid.fdroid.views.StatusBanner;
|
||||
import org.fdroid.fdroid.views.BannerUpdatingRepos;
|
||||
import org.fdroid.fdroid.views.main.MainActivity;
|
||||
import org.hamcrest.Matchers;
|
||||
import org.junit.After;
|
||||
@ -267,7 +267,7 @@ public class MainActivityEspressoTest {
|
||||
if (!BuildConfig.FLAVOR.startsWith("full")) {
|
||||
return;
|
||||
}
|
||||
onView(Matchers.<View>instanceOf(StatusBanner.class)).check(matches(not(isDisplayed())));
|
||||
onView(Matchers.<View>instanceOf(BannerUpdatingRepos.class)).check(matches(not(isDisplayed())));
|
||||
onView(allOf(withText(R.string.menu_settings), isDisplayed())).perform(click());
|
||||
onView(allOf(withText(R.string.main_menu__latest_apps), isDisplayed())).perform(click());
|
||||
onView(allOf(withId(R.id.swipe_to_refresh), isDisplayed()))
|
||||
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 2.5 KiB |
BIN
app/src/basic/res/drawable-ldpi/ic_launcher.png
Normal file
After Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 5.5 KiB After Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 3.5 KiB |
Before Width: | Height: | Size: 40 KiB After Width: | Height: | Size: 5.8 KiB |
Before Width: | Height: | Size: 65 KiB After Width: | Height: | Size: 5.3 KiB |
@ -1,8 +1,13 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<PreferenceScreen
|
||||
xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<PreferenceScreen android:title="@string/about_title"
|
||||
android:key="pref_about" />
|
||||
<PreferenceScreen android:title="@string/about_title">
|
||||
<intent
|
||||
android:action="android.intent.action.MAIN"
|
||||
android:targetPackage="@string/applicationId"
|
||||
android:targetClass="org.fdroid.fdroid.AboutActivity"/>
|
||||
</PreferenceScreen>
|
||||
|
||||
<PreferenceCategory android:title="@string/preference_category__my_apps">
|
||||
<PreferenceScreen android:title="@string/preference_manage_installed_apps">
|
||||
@ -42,7 +47,7 @@
|
||||
android:title="@string/over_data"
|
||||
android:defaultValue="@integer/defaultOverData"
|
||||
android:layout="@layout/preference_seekbar"/>
|
||||
<SwitchPreferenceCompat
|
||||
<SwitchPreference
|
||||
android:title="@string/update_auto_download"
|
||||
android:summary="@string/update_auto_download_summary"
|
||||
android:key="updateAutoDownload"/>
|
||||
@ -51,7 +56,7 @@
|
||||
android:title="@string/update_interval"
|
||||
android:defaultValue="@integer/defaultUpdateInterval"
|
||||
android:layout="@layout/preference_seekbar"/>
|
||||
<SwitchPreferenceCompat
|
||||
<SwitchPreference
|
||||
android:title="@string/notify"
|
||||
android:defaultValue="true"
|
||||
android:key="updateNotify"/>
|
||||
@ -72,26 +77,26 @@
|
||||
|
||||
<PreferenceCategory android:title="@string/appcompatibility"
|
||||
android:key="pref_category_appcompatibility">
|
||||
<SwitchPreferenceCompat
|
||||
<SwitchPreference
|
||||
android:title="@string/show_incompat_versions"
|
||||
android:defaultValue="false"
|
||||
android:key="incompatibleVersions"/>
|
||||
<SwitchPreferenceCompat
|
||||
<SwitchPreference
|
||||
android:title="@string/show_anti_feature_apps"
|
||||
android:defaultValue="false"
|
||||
android:key="showAntiFeatureApps"/>
|
||||
<SwitchPreferenceCompat
|
||||
<SwitchPreference
|
||||
android:title="@string/force_touch_apps"
|
||||
android:defaultValue="false"
|
||||
android:key="ignoreTouchscreen"/>
|
||||
</PreferenceCategory>
|
||||
|
||||
<PreferenceCategory android:title="@string/proxy">
|
||||
<SwitchPreferenceCompat
|
||||
<SwitchPreference
|
||||
android:key="useTor"
|
||||
android:summary="@string/useTorSummary"
|
||||
android:title="@string/useTor"/>
|
||||
<SwitchPreferenceCompat
|
||||
<SwitchPreference
|
||||
android:defaultValue="false"
|
||||
android:key="enableProxy"
|
||||
android:title="@string/enable_proxy_title"
|
||||
@ -111,12 +116,12 @@
|
||||
<PreferenceCategory
|
||||
android:key="pref_category_privacy"
|
||||
android:title="@string/privacy">
|
||||
<SwitchPreferenceCompat
|
||||
<SwitchPreference
|
||||
android:key="promptToSendCrashReports"
|
||||
android:title="@string/prompt_to_send_crash_reports"
|
||||
android:summary="@string/prompt_to_send_crash_reports_summary"
|
||||
android:defaultValue="true"/>
|
||||
<SwitchPreferenceCompat
|
||||
<SwitchPreference
|
||||
android:defaultValue="false"
|
||||
android:key="preventScreenshots"
|
||||
android:summary="@string/preventScreenshots_summary"
|
||||
@ -132,7 +137,7 @@
|
||||
android:defaultValue="86400000"
|
||||
android:entries="@array/keepCacheNames"
|
||||
android:entryValues="@array/keepCacheValues"/>
|
||||
<SwitchPreferenceCompat
|
||||
<SwitchPreference
|
||||
android:title="@string/expert"
|
||||
android:defaultValue="false"
|
||||
android:key="expert"/>
|
||||
|
@ -1,8 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<!-- This file should be outside of release manifest (in this case app/src/mock/Manifest.xml -->
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<!--required to enable/disable system animations from the app itself during Espresso test runs-->
|
||||
<uses-permission android:name="android.permission.SET_ANIMATION_SCALE" />
|
||||
<uses-permission android:name="android.permission.SET_ANIMATION_SCALE"/>
|
||||
</manifest>
|
||||
|
@ -1,5 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<!--
|
||||
* Copyright (C) 2010-2012 Ciaran Gultnieks
|
||||
* Copyright (C) 2013-2017 Peter Serwylo
|
||||
@ -24,128 +23,91 @@
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
-->
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="org.fdroid.fdroid"
|
||||
android:installLocation="auto">
|
||||
package="org.fdroid.fdroid"
|
||||
android:installLocation="auto">
|
||||
|
||||
<uses-feature
|
||||
android:name="android.hardware.nfc"
|
||||
android:required="false" />
|
||||
<uses-feature
|
||||
android:name="android.hardware.bluetooth"
|
||||
android:required="false" />
|
||||
<uses-feature android:name="android.hardware.nfc" android:required="false"/>
|
||||
<uses-feature android:name="android.hardware.bluetooth" android:required="false"/>
|
||||
<uses-feature android:name="android.hardware.usb.host" android:required="false"/>
|
||||
|
||||
<uses-feature
|
||||
android:name="android.hardware.usb.host"
|
||||
android:required="false" />
|
||||
<uses-permission android:name="android.permission.INTERNET"/>
|
||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
|
||||
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
|
||||
<uses-permission android:name="android.permission.CHANGE_WIFI_MULTICAST_STATE"/>
|
||||
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE"/>
|
||||
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/>
|
||||
<uses-permission android:name="android.permission.BLUETOOTH"/>
|
||||
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
|
||||
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
|
||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
|
||||
<uses-permission android:name="android.permission.WRITE_SETTINGS"/>
|
||||
<uses-permission android:name="android.permission.NFC"/>
|
||||
<uses-permission android:name="android.permission.USB_PERMISSION"
|
||||
android:maxSdkVersion="22"/> <!-- maybe unnecessary -->
|
||||
<uses-permission android:name="android.permission.WAKE_LOCK"/>
|
||||
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
|
||||
<uses-permission android:name="android.permission.CHANGE_WIFI_MULTICAST_STATE" />
|
||||
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
|
||||
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
|
||||
<uses-permission android:name="android.permission.BLUETOOTH" />
|
||||
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
|
||||
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
|
||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||
<uses-permission android:name="android.permission.WRITE_SETTINGS" />
|
||||
<uses-permission android:name="android.permission.NFC" />
|
||||
<uses-permission
|
||||
android:name="android.permission.USB_PERMISSION"
|
||||
android:maxSdkVersion="22" /><!-- maybe unnecessary -->
|
||||
|
||||
<uses-permission android:name="android.permission.WAKE_LOCK" />
|
||||
|
||||
<uses-permission-sdk-23 android:name="android.permission.ACCESS_COARSE_LOCATION" />
|
||||
<uses-permission-sdk-23 android:name="android.permission.ACCESS_COARSE_LOCATION"/>
|
||||
|
||||
<application>
|
||||
|
||||
<activity
|
||||
android:name=".nearby.SwapWorkflowActivity"
|
||||
android:configChanges="orientation|keyboardHidden"
|
||||
android:label="@string/swap"
|
||||
android:launchMode="singleTask"
|
||||
android:parentActivityName=".views.main.MainActivity"
|
||||
android:screenOrientation="portrait">
|
||||
android:label="@string/swap"
|
||||
android:name=".nearby.SwapWorkflowActivity"
|
||||
android:parentActivityName=".views.main.MainActivity"
|
||||
android:launchMode="singleTask"
|
||||
android:theme="@style/SwapTheme.Wizard"
|
||||
android:screenOrientation="portrait"
|
||||
android:configChanges="orientation|keyboardHidden">
|
||||
<meta-data
|
||||
android:name="android.support.PARENT_ACTIVITY"
|
||||
android:value=".views.main.MainActivity" />
|
||||
android:name="android.support.PARENT_ACTIVITY"
|
||||
android:value=".views.main.MainActivity"/>
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:name=".panic.PanicPreferencesActivity"
|
||||
android:label="@string/panic_settings"
|
||||
android:parentActivityName=".views.main.MainActivity">
|
||||
<intent-filter>
|
||||
<action android:name="info.guardianproject.panic.action.CONNECT" />
|
||||
<action android:name="info.guardianproject.panic.action.DISCONNECT" />
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
</intent-filter>
|
||||
|
||||
<meta-data
|
||||
android:name="android.support.PARENT_ACTIVITY"
|
||||
android:value=".views.main.MainActivity" />
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:name=".panic.SelectInstalledAppsActivity"
|
||||
android:parentActivityName=".panic.PanicPreferencesActivity" />
|
||||
|
||||
<activity
|
||||
android:name=".panic.PanicResponderActivity"
|
||||
android:noHistory="true"
|
||||
android:theme="@android:style/Theme.NoDisplay">
|
||||
|
||||
<!-- this can never have launchMode singleTask or singleInstance! -->
|
||||
<intent-filter>
|
||||
<action android:name="info.guardianproject.panic.action.TRIGGER" />
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<activity
|
||||
android:name=".panic.ExitActivity"
|
||||
android:theme="@android:style/Theme.NoDisplay" />
|
||||
|
||||
<activity
|
||||
android:name=".panic.CalculatorActivity"
|
||||
android:enabled="false"
|
||||
android:icon="@mipmap/ic_calculator_launcher"
|
||||
android:label="@string/hiding_calculator">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<receiver android:name=".nearby.WifiStateChangeReceiver">
|
||||
<intent-filter>
|
||||
<action android:name="android.net.wifi.STATE_CHANGE" />
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
<receiver android:name=".receiver.DeviceStorageReceiver">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.DEVICE_STORAGE_LOW" />
|
||||
<action android:name="android.net.wifi.STATE_CHANGE"/>
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
|
||||
<receiver android:name=".nearby.UsbDeviceAttachedReceiver">
|
||||
<receiver android:name=".receiver.DeviceStorageReceiver">
|
||||
<intent-filter>
|
||||
<action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" />
|
||||
<action android:name="android.intent.action.DEVICE_STORAGE_LOW"/>
|
||||
</intent-filter>
|
||||
<meta-data
|
||||
android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED"
|
||||
android:resource="@xml/device_filter" />
|
||||
</receiver>
|
||||
<receiver android:name=".nearby.UsbDeviceDetachedReceiver">
|
||||
|
||||
<service
|
||||
android:name=".nearby.WifiStateChangeService"
|
||||
android:exported="false"/>
|
||||
<service android:name=".nearby.SwapService"/>
|
||||
|
||||
<service
|
||||
android:name=".nearby.LocalRepoService"
|
||||
android:exported="false"/>
|
||||
<service
|
||||
android:name=".nearby.TreeUriScannerIntentService"
|
||||
android:exported="false"/>
|
||||
<service
|
||||
android:name=".nearby.SDCardScannerService"
|
||||
android:exported="false"/>
|
||||
|
||||
<receiver
|
||||
android:name=".nearby.UsbDeviceAttachedReceiver">
|
||||
<intent-filter>
|
||||
<action android:name="android.hardware.usb.action.USB_DEVICE_DETACHED" />
|
||||
<action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED"/>
|
||||
</intent-filter>
|
||||
<meta-data
|
||||
android:name="android.hardware.usb.action.USB_DEVICE_DETACHED"
|
||||
android:resource="@xml/device_filter" />
|
||||
android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED"
|
||||
android:resource="@xml/device_filter"/>
|
||||
</receiver>
|
||||
<receiver
|
||||
android:name=".nearby.UsbDeviceDetachedReceiver">
|
||||
<intent-filter>
|
||||
<action android:name="android.hardware.usb.action.USB_DEVICE_DETACHED"/>
|
||||
</intent-filter>
|
||||
<meta-data
|
||||
android:name="android.hardware.usb.action.USB_DEVICE_DETACHED"
|
||||
android:resource="@xml/device_filter"/>
|
||||
</receiver>
|
||||
<receiver android:name=".nearby.UsbDeviceMediaMountedReceiver">
|
||||
<intent-filter>
|
||||
@ -159,20 +121,52 @@
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
|
||||
<service
|
||||
android:name=".nearby.WifiStateChangeService"
|
||||
android:exported="false" />
|
||||
<service android:name=".nearby.SwapService" />
|
||||
<activity
|
||||
android:name=".panic.PanicPreferencesActivity"
|
||||
android:label="@string/panic_settings"
|
||||
android:parentActivityName=".views.main.MainActivity">
|
||||
<meta-data
|
||||
android:name="android.support.PARENT_ACTIVITY"
|
||||
android:value=".views.main.MainActivity"/>
|
||||
|
||||
<service
|
||||
android:name=".nearby.LocalRepoService"
|
||||
android:exported="false" />
|
||||
<service
|
||||
android:name=".nearby.TreeUriScannerIntentService"
|
||||
android:exported="false" />
|
||||
<service
|
||||
android:name=".nearby.SDCardScannerService"
|
||||
android:exported="false" />
|
||||
<intent-filter>
|
||||
<action android:name="info.guardianproject.panic.action.CONNECT"/>
|
||||
<action android:name="info.guardianproject.panic.action.DISCONNECT"/>
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT"/>
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<activity
|
||||
android:name=".panic.SelectInstalledAppsActivity"
|
||||
android:parentActivityName=".panic.PanicPreferencesActivity"/>
|
||||
|
||||
<activity
|
||||
android:name=".panic.PanicResponderActivity"
|
||||
android:noHistory="true"
|
||||
android:theme="@android:style/Theme.NoDisplay">
|
||||
|
||||
<!-- this can never have launchMode singleTask or singleInstance! -->
|
||||
<intent-filter>
|
||||
<action android:name="info.guardianproject.panic.action.TRIGGER"/>
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT"/>
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<activity
|
||||
android:name=".panic.ExitActivity"
|
||||
android:theme="@android:style/Theme.NoDisplay"/>
|
||||
<activity
|
||||
android:name=".panic.CalculatorActivity"
|
||||
android:enabled="false"
|
||||
android:icon="@mipmap/ic_calculator_launcher"
|
||||
android:label="@string/hiding_calculator"
|
||||
android:theme="@style/AppThemeLight">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN"/>
|
||||
|
||||
<category android:name="android.intent.category.LAUNCHER"/>
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
</application>
|
||||
|
||||
|
@ -4,13 +4,12 @@ import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import javax.jmdns.ServiceInfo;
|
||||
import javax.jmdns.impl.util.ByteWrangler;
|
||||
import java.net.Inet4Address;
|
||||
import java.net.Inet6Address;
|
||||
import java.net.UnknownHostException;
|
||||
|
||||
import javax.jmdns.ServiceInfo;
|
||||
import javax.jmdns.impl.util.ByteWrangler;
|
||||
|
||||
/**
|
||||
* The ServiceInfo class needs to be serialized in order to be sent as an Android broadcast.
|
||||
* In order to make it Parcelable (or Serializable for that matter), there are some package-scope
|
||||
|
@ -10,17 +10,15 @@ import android.os.Handler;
|
||||
import android.os.HandlerThread;
|
||||
import android.os.Message;
|
||||
import android.os.Process;
|
||||
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
|
||||
import org.fdroid.fdroid.R;
|
||||
import org.fdroid.fdroid.Utils;
|
||||
import org.fdroid.fdroid.nearby.peers.BluetoothPeer;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
|
||||
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
|
||||
|
||||
/**
|
||||
* Manage the {@link android.bluetooth.BluetoothAdapter}in a {@link HandlerThread}.
|
||||
* The start process is in {@link HandlerThread#onLooperPrepared()} so that it is
|
||||
|
@ -5,7 +5,7 @@ import android.bluetooth.BluetoothServerSocket;
|
||||
import android.bluetooth.BluetoothSocket;
|
||||
import android.util.Log;
|
||||
import android.webkit.MimeTypeMap;
|
||||
|
||||
import fi.iki.elonen.NanoHTTPD;
|
||||
import org.fdroid.fdroid.Utils;
|
||||
import org.fdroid.fdroid.nearby.httpish.Request;
|
||||
import org.fdroid.fdroid.nearby.httpish.Response;
|
||||
@ -20,8 +20,6 @@ import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import fi.iki.elonen.NanoHTTPD;
|
||||
|
||||
/**
|
||||
* Act as a layer on top of LocalHTTPD server, by forwarding requests served
|
||||
* over bluetooth to that server.
|
||||
|
@ -10,6 +10,9 @@ import android.os.Process;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
|
||||
|
||||
import org.fdroid.fdroid.FDroidApp;
|
||||
import org.fdroid.fdroid.Preferences;
|
||||
import org.fdroid.fdroid.Utils;
|
||||
@ -25,9 +28,6 @@ import javax.jmdns.ServiceEvent;
|
||||
import javax.jmdns.ServiceInfo;
|
||||
import javax.jmdns.ServiceListener;
|
||||
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
|
||||
|
||||
/**
|
||||
* Manage {@link JmDNS} in a {@link HandlerThread}. The start process is in
|
||||
* {@link HandlerThread#onLooperPrepared()} so that it is always started before
|
||||
|
@ -35,9 +35,11 @@ package org.fdroid.fdroid.nearby;
|
||||
|
||||
import android.content.Context;
|
||||
import android.net.Uri;
|
||||
|
||||
import fi.iki.elonen.NanoHTTPD;
|
||||
import fi.iki.elonen.NanoHTTPD.Response.IStatus;
|
||||
import org.fdroid.fdroid.BuildConfig;
|
||||
|
||||
import javax.net.ssl.SSLServerSocketFactory;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
@ -60,11 +62,6 @@ import java.util.Map;
|
||||
import java.util.StringTokenizer;
|
||||
import java.util.TimeZone;
|
||||
|
||||
import javax.net.ssl.SSLServerSocketFactory;
|
||||
|
||||
import fi.iki.elonen.NanoHTTPD;
|
||||
import fi.iki.elonen.NanoHTTPD.Response.IStatus;
|
||||
|
||||
/**
|
||||
* A HTTP server for serving the files that are being swapped via WiFi, etc.
|
||||
* The only changes were to remove unneeded extras like {@code main()}, the
|
||||
|
@ -6,8 +6,8 @@ import android.os.Handler;
|
||||
import android.os.HandlerThread;
|
||||
import android.os.Message;
|
||||
import android.os.Process;
|
||||
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
|
||||
import android.util.Log;
|
||||
|
||||
import org.fdroid.fdroid.FDroidApp;
|
||||
import org.fdroid.fdroid.Preferences;
|
||||
|
||||
@ -15,8 +15,6 @@ import java.io.IOException;
|
||||
import java.net.BindException;
|
||||
import java.util.Random;
|
||||
|
||||
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
|
||||
|
||||
/**
|
||||
* Manage {@link LocalHTTPD} in a {@link HandlerThread};
|
||||
*/
|
||||
|
@ -2,7 +2,7 @@ package org.fdroid.fdroid.nearby;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.Log;
|
||||
|
||||
import kellinwood.security.zipsigner.ZipSigner;
|
||||
import org.bouncycastle.asn1.ASN1Sequence;
|
||||
import org.bouncycastle.asn1.x500.X500Name;
|
||||
import org.bouncycastle.asn1.x509.GeneralName;
|
||||
@ -19,6 +19,9 @@ import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
|
||||
import org.fdroid.fdroid.FDroidApp;
|
||||
import org.fdroid.fdroid.Utils;
|
||||
|
||||
import javax.net.ssl.KeyManager;
|
||||
import javax.net.ssl.KeyManagerFactory;
|
||||
import javax.net.ssl.X509KeyManager;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
@ -46,12 +49,6 @@ import java.util.Date;
|
||||
import java.util.GregorianCalendar;
|
||||
import java.util.Locale;
|
||||
|
||||
import javax.net.ssl.KeyManager;
|
||||
import javax.net.ssl.KeyManagerFactory;
|
||||
import javax.net.ssl.X509KeyManager;
|
||||
|
||||
import kellinwood.security.zipsigner.ZipSigner;
|
||||
|
||||
// TODO Address exception handling in a uniform way throughout
|
||||
|
||||
@SuppressWarnings("LineLength")
|
||||
|
@ -12,7 +12,8 @@ import android.graphics.drawable.BitmapDrawable;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import org.fdroid.fdroid.FDroidApp;
|
||||
import org.fdroid.fdroid.Hasher;
|
||||
import org.fdroid.fdroid.IndexUpdater;
|
||||
@ -49,9 +50,6 @@ import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.jar.JarEntry;
|
||||
import java.util.jar.JarOutputStream;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* The {@link SwapService} deals with managing the entire workflow from selecting apps to
|
||||
* swap, to invoking this class to prepare the webroot, to enabling various communication protocols.
|
||||
|
@ -4,7 +4,7 @@ import android.app.IntentService;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Process;
|
||||
|
||||
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
|
||||
import org.fdroid.fdroid.FDroidApp;
|
||||
import org.fdroid.fdroid.R;
|
||||
import org.fdroid.fdroid.Utils;
|
||||
@ -15,8 +15,6 @@ import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
|
||||
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
|
||||
|
||||
/**
|
||||
* Handles setting up and generating the local repo used to swap apps, including
|
||||
* the {@code index.jar}, the symlinks to the shared APKs, etc.
|
||||
|
@ -29,7 +29,7 @@ import android.os.Build;
|
||||
import android.os.Environment;
|
||||
import android.os.Process;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.core.content.ContextCompat;
|
||||
import org.fdroid.fdroid.IndexUpdater;
|
||||
import org.fdroid.fdroid.IndexV1Updater;
|
||||
import org.fdroid.fdroid.Utils;
|
||||
@ -44,8 +44,6 @@ import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
|
||||
import androidx.core.content.ContextCompat;
|
||||
|
||||
/**
|
||||
* An {@link IntentService} subclass for scanning removable "external storage"
|
||||
* for F-Droid package repos, e.g. SD Cards. This is intended to support
|
||||
|
@ -4,6 +4,7 @@ import android.annotation.TargetApi;
|
||||
import android.content.Context;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.database.Cursor;
|
||||
import android.graphics.PorterDuff;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
@ -20,10 +21,6 @@ import android.widget.ImageView;
|
||||
import android.widget.ListView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import org.fdroid.fdroid.R;
|
||||
import org.fdroid.fdroid.data.InstalledAppProvider;
|
||||
import org.fdroid.fdroid.data.Schema.InstalledAppTable;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.core.content.ContextCompat;
|
||||
@ -32,6 +29,10 @@ import androidx.loader.app.LoaderManager;
|
||||
import androidx.loader.content.CursorLoader;
|
||||
import androidx.loader.content.Loader;
|
||||
|
||||
import org.fdroid.fdroid.R;
|
||||
import org.fdroid.fdroid.data.InstalledAppProvider;
|
||||
import org.fdroid.fdroid.data.Schema.InstalledAppTable;
|
||||
|
||||
public class SelectAppsView extends SwapView implements LoaderManager.LoaderCallbacks<Cursor> {
|
||||
|
||||
public SelectAppsView(Context context) {
|
||||
@ -199,6 +200,8 @@ public class SelectAppsView extends SwapView implements LoaderManager.LoaderCall
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
updateCheckedIndicatorView(view, listView.isItemChecked(listPosition));
|
||||
}
|
||||
|
||||
public void updateCheckedIndicatorView(int position, boolean checked) {
|
||||
@ -207,6 +210,24 @@ public class SelectAppsView extends SwapView implements LoaderManager.LoaderCall
|
||||
|
||||
if (position >= firstListItemPosition && position <= lastListItemPosition) {
|
||||
final int childIndex = position - firstListItemPosition;
|
||||
updateCheckedIndicatorView(listView.getChildAt(childIndex), checked);
|
||||
}
|
||||
}
|
||||
|
||||
private void updateCheckedIndicatorView(View view, boolean checked) {
|
||||
ImageView imageView = (ImageView) view.findViewById(R.id.checked);
|
||||
if (imageView != null) {
|
||||
int resource;
|
||||
int colour;
|
||||
if (checked) {
|
||||
resource = R.drawable.ic_check_circle;
|
||||
colour = ContextCompat.getColor(getContext(), R.color.swap_bright_blue);
|
||||
} else {
|
||||
resource = R.drawable.ic_add_circle_outline;
|
||||
colour = 0xFFD0D0D4;
|
||||
}
|
||||
imageView.setImageDrawable(ContextCompat.getDrawable(getContext(), resource));
|
||||
imageView.setColorFilter(colour, PorterDuff.Mode.MULTIPLY);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -20,6 +20,11 @@ import android.widget.ListView;
|
||||
import android.widget.ProgressBar;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.widget.SwitchCompat;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
|
||||
|
||||
import org.fdroid.fdroid.FDroidApp;
|
||||
import org.fdroid.fdroid.R;
|
||||
import org.fdroid.fdroid.Utils;
|
||||
@ -27,10 +32,6 @@ import org.fdroid.fdroid.nearby.peers.Peer;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import com.google.android.material.switchmaterial.SwitchMaterial;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
|
||||
import cc.mvdan.accesspoint.WifiApControl;
|
||||
|
||||
@SuppressWarnings("LineLength")
|
||||
@ -79,7 +80,7 @@ public class StartSwapView extends SwapView {
|
||||
@Nullable /* Emulators typically don't have bluetooth adapters */
|
||||
private final BluetoothAdapter bluetooth = BluetoothAdapter.getDefaultAdapter();
|
||||
|
||||
private SwitchMaterial bluetoothSwitch;
|
||||
private SwitchCompat bluetoothSwitch;
|
||||
private TextView viewBluetoothId;
|
||||
private TextView textBluetoothVisible;
|
||||
private TextView viewWifiId;
|
||||
@ -175,7 +176,7 @@ public class StartSwapView extends SwapView {
|
||||
|
||||
textBluetoothVisible = findViewById(R.id.bluetooth_visible);
|
||||
|
||||
bluetoothSwitch = (SwitchMaterial) findViewById(R.id.switch_bluetooth);
|
||||
bluetoothSwitch = (SwitchCompat) findViewById(R.id.switch_bluetooth);
|
||||
bluetoothSwitch.setOnCheckedChangeListener(onBluetoothSwitchToggled);
|
||||
bluetoothSwitch.setChecked(SwapService.getBluetoothVisibleUserPreference());
|
||||
bluetoothSwitch.setEnabled(true);
|
||||
|
@ -1,5 +1,6 @@
|
||||
package org.fdroid.fdroid.nearby;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.Notification;
|
||||
import android.app.PendingIntent;
|
||||
import android.app.Service;
|
||||
@ -12,17 +13,17 @@ import android.content.IntentFilter;
|
||||
import android.content.SharedPreferences;
|
||||
import android.net.Uri;
|
||||
import android.net.wifi.WifiManager;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.IBinder;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.core.app.NotificationCompat;
|
||||
import androidx.core.app.ServiceCompat;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
|
||||
|
||||
import cc.mvdan.accesspoint.WifiApControl;
|
||||
import org.fdroid.fdroid.FDroidApp;
|
||||
import org.fdroid.fdroid.NotificationHelper;
|
||||
import org.fdroid.fdroid.Preferences;
|
||||
@ -35,6 +36,7 @@ import org.fdroid.fdroid.data.Schema;
|
||||
import org.fdroid.fdroid.nearby.peers.Peer;
|
||||
import org.fdroid.fdroid.net.Downloader;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.net.HttpURLConnection;
|
||||
@ -45,12 +47,6 @@ import java.util.Set;
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
|
||||
import cc.mvdan.accesspoint.WifiApControl;
|
||||
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
|
||||
import io.reactivex.rxjava3.core.Completable;
|
||||
import io.reactivex.rxjava3.disposables.CompositeDisposable;
|
||||
import io.reactivex.rxjava3.schedulers.Schedulers;
|
||||
|
||||
/**
|
||||
* Central service which manages all of the different moving parts of swap which are required
|
||||
* to enable p2p swapping of apps.
|
||||
@ -111,6 +107,46 @@ public class SwapService extends Service {
|
||||
UpdateService.updateRepoNow(this, peer.getRepoAddress());
|
||||
}
|
||||
|
||||
@SuppressLint("StaticFieldLeak")
|
||||
private void askServerToSwapWithUs(final Repo repo) {
|
||||
new AsyncTask<Void, Void, Void>() {
|
||||
@Override
|
||||
protected Void doInBackground(Void... args) {
|
||||
String swapBackUri = Utils.getLocalRepoUri(FDroidApp.repo).toString();
|
||||
HttpURLConnection conn = null;
|
||||
try {
|
||||
URL url = new URL(repo.address.replace("/fdroid/repo", "/request-swap"));
|
||||
conn = (HttpURLConnection) url.openConnection();
|
||||
conn.setRequestMethod("POST");
|
||||
conn.setDoInput(true);
|
||||
conn.setDoOutput(true);
|
||||
|
||||
OutputStream outputStream = conn.getOutputStream();
|
||||
OutputStreamWriter writer = new OutputStreamWriter(outputStream);
|
||||
writer.write("repo=" + swapBackUri);
|
||||
writer.flush();
|
||||
writer.close();
|
||||
outputStream.close();
|
||||
|
||||
int responseCode = conn.getResponseCode();
|
||||
Utils.debugLog(TAG, "Asking server at " + repo.address + " to swap with us in return (by " +
|
||||
"POSTing to \"/request-swap\" with repo \"" + swapBackUri + "\"): " + responseCode);
|
||||
} catch (IOException e) {
|
||||
Log.e(TAG, "Error while asking server to swap with us", e);
|
||||
Intent intent = new Intent(Downloader.ACTION_INTERRUPTED);
|
||||
intent.setData(Uri.parse(repo.address));
|
||||
intent.putExtra(Downloader.EXTRA_ERROR_MESSAGE, e.getLocalizedMessage());
|
||||
LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(intent);
|
||||
} finally {
|
||||
if (conn != null) {
|
||||
conn.disconnect();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}.execute();
|
||||
}
|
||||
|
||||
private Repo ensureRepoExists(@NonNull Peer peer) {
|
||||
// TODO: newRepoConfig.getParsedUri() will include a fingerprint, which may not match with
|
||||
// the repos address in the database. Not sure on best behaviour in this situation.
|
||||
@ -304,15 +340,12 @@ public class SwapService extends Service {
|
||||
@Nullable
|
||||
private Timer timer;
|
||||
|
||||
private final CompositeDisposable compositeDisposable = new CompositeDisposable();
|
||||
|
||||
public class Binder extends android.os.Binder {
|
||||
public SwapService getService() {
|
||||
return SwapService.this;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
startForeground(NOTIFICATION, createNotification());
|
||||
@ -362,45 +395,6 @@ public class SwapService extends Service {
|
||||
BonjourManager.setVisible(this, getWifiVisibleUserPreference() || getHotspotActivatedUserPreference());
|
||||
}
|
||||
|
||||
private void askServerToSwapWithUs(final Repo repo) {
|
||||
compositeDisposable.add(
|
||||
Completable.fromAction(() -> {
|
||||
String swapBackUri = Utils.getLocalRepoUri(FDroidApp.repo).toString();
|
||||
HttpURLConnection conn = null;
|
||||
try {
|
||||
URL url = new URL(repo.address.replace("/fdroid/repo", "/request-swap"));
|
||||
conn = (HttpURLConnection) url.openConnection();
|
||||
conn.setRequestMethod("POST");
|
||||
conn.setDoInput(true);
|
||||
conn.setDoOutput(true);
|
||||
|
||||
try (OutputStream outputStream = conn.getOutputStream();
|
||||
OutputStreamWriter writer = new OutputStreamWriter(outputStream)) {
|
||||
writer.write("repo=" + swapBackUri);
|
||||
writer.flush();
|
||||
}
|
||||
|
||||
int responseCode = conn.getResponseCode();
|
||||
Utils.debugLog(TAG, "Asking server at " + repo.address + " to swap with us in return (by " +
|
||||
"POSTing to \"/request-swap\" with repo \"" + swapBackUri + "\"): " + responseCode);
|
||||
} finally {
|
||||
if (conn != null) {
|
||||
conn.disconnect();
|
||||
}
|
||||
}
|
||||
})
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.doOnError(e -> {
|
||||
Intent intent = new Intent(Downloader.ACTION_INTERRUPTED);
|
||||
intent.setData(Uri.parse(repo.address));
|
||||
intent.putExtra(Downloader.EXTRA_ERROR_MESSAGE, e.getLocalizedMessage());
|
||||
LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(intent);
|
||||
})
|
||||
.subscribe()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* This is for setting things up for when the {@code SwapService} was
|
||||
* started by the user clicking on the initial start button. The things
|
||||
@ -424,8 +418,6 @@ public class SwapService extends Service {
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
compositeDisposable.dispose();
|
||||
|
||||
Utils.debugLog(TAG, "Destroying service, will disable swapping if required, and unregister listeners.");
|
||||
Preferences.get().unregisterLocalRepoHttpsListeners(httpsEnabledListener);
|
||||
localBroadcastManager.unregisterReceiver(onWifiChange);
|
||||
|
@ -1,6 +1,7 @@
|
||||
package org.fdroid.fdroid.nearby;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import android.app.PendingIntent;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
@ -11,6 +12,14 @@ import android.database.Cursor;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.loader.app.LoaderManager;
|
||||
import androidx.loader.content.CursorLoader;
|
||||
import androidx.loader.content.Loader;
|
||||
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
|
||||
import androidx.cursoradapter.widget.CursorAdapter;
|
||||
import android.text.TextUtils;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Log;
|
||||
@ -23,9 +32,7 @@ import android.widget.ListView;
|
||||
import android.widget.ProgressBar;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.nostra13.universalimageloader.core.ImageLoader;
|
||||
|
||||
import org.fdroid.fdroid.R;
|
||||
import org.fdroid.fdroid.UpdateService;
|
||||
import org.fdroid.fdroid.Utils;
|
||||
@ -42,16 +49,6 @@ import org.fdroid.fdroid.net.DownloaderService;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.cursoradapter.widget.CursorAdapter;
|
||||
import androidx.loader.app.LoaderManager;
|
||||
import androidx.loader.content.CursorLoader;
|
||||
import androidx.loader.content.Loader;
|
||||
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
|
||||
|
||||
/**
|
||||
* This is a view that shows a listing of all apps in the swap repo that this
|
||||
* just connected to. The app listing and search should be replaced by
|
||||
|
@ -6,12 +6,12 @@ import android.content.res.TypedArray;
|
||||
import android.util.AttributeSet;
|
||||
import android.widget.RelativeLayout;
|
||||
|
||||
import org.fdroid.fdroid.R;
|
||||
|
||||
import androidx.annotation.ColorInt;
|
||||
import androidx.annotation.LayoutRes;
|
||||
import androidx.core.content.ContextCompat;
|
||||
|
||||
import org.fdroid.fdroid.R;
|
||||
|
||||
/**
|
||||
* A {@link android.view.View} that registers to handle the swap events from
|
||||
* {@link SwapService}.
|
||||
|
@ -1,6 +1,7 @@
|
||||
package org.fdroid.fdroid.nearby;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import android.bluetooth.BluetoothAdapter;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.ComponentName;
|
||||
@ -41,11 +42,11 @@ import androidx.annotation.StringRes;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.appcompat.widget.SearchView;
|
||||
import androidx.appcompat.widget.SwitchCompat;
|
||||
import androidx.appcompat.widget.Toolbar;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
|
||||
|
||||
import com.google.android.material.appbar.MaterialToolbar;
|
||||
import com.google.android.material.switchmaterial.SwitchMaterial;
|
||||
import com.google.zxing.integration.android.IntentIntegrator;
|
||||
import com.google.zxing.integration.android.IntentResult;
|
||||
|
||||
@ -65,6 +66,7 @@ import org.fdroid.fdroid.net.BluetoothDownloader;
|
||||
import org.fdroid.fdroid.net.Downloader;
|
||||
import org.fdroid.fdroid.net.HttpDownloader;
|
||||
import org.fdroid.fdroid.qr.CameraCharacteristicsChecker;
|
||||
import org.fdroid.fdroid.qr.QrGenAsyncTask;
|
||||
import org.fdroid.fdroid.views.main.MainActivity;
|
||||
|
||||
import java.util.Date;
|
||||
@ -76,7 +78,6 @@ import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
|
||||
import cc.mvdan.accesspoint.WifiApControl;
|
||||
import io.reactivex.rxjava3.disposables.CompositeDisposable;
|
||||
|
||||
import static org.fdroid.fdroid.views.main.MainActivity.ACTION_REQUEST_SWAP;
|
||||
|
||||
@ -106,7 +107,7 @@ public class SwapWorkflowActivity extends AppCompatActivity {
|
||||
private static final int REQUEST_WRITE_SETTINGS_PERMISSION = 5;
|
||||
private static final int STEP_INTRO = 1; // TODO remove this special case, only use layoutResIds
|
||||
|
||||
private MaterialToolbar toolbar;
|
||||
private Toolbar toolbar;
|
||||
private SwapView currentView;
|
||||
private boolean hasPreparedLocalRepo;
|
||||
private boolean newIntent;
|
||||
@ -119,8 +120,6 @@ public class SwapWorkflowActivity extends AppCompatActivity {
|
||||
@LayoutRes
|
||||
private int currentSwapViewLayoutRes = STEP_INTRO;
|
||||
|
||||
private final CompositeDisposable compositeDisposable = new CompositeDisposable();
|
||||
|
||||
public static void requestSwap(Context context, String repo) {
|
||||
requestSwap(context, Uri.parse(repo));
|
||||
}
|
||||
@ -202,11 +201,7 @@ public class SwapWorkflowActivity extends AppCompatActivity {
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
FDroidApp fdroidApp = (FDroidApp) getApplication();
|
||||
fdroidApp.setSecureWindow(this);
|
||||
|
||||
fdroidApp.applyPureBlackBackgroundInDarkTheme(this);
|
||||
|
||||
((FDroidApp) getApplication()).setSecureWindow(this);
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
currentView = new SwapView(this); // dummy placeholder to avoid NullPointerExceptions;
|
||||
@ -219,8 +214,10 @@ public class SwapWorkflowActivity extends AppCompatActivity {
|
||||
|
||||
setContentView(R.layout.swap_activity);
|
||||
|
||||
toolbar = findViewById(R.id.toolbar);
|
||||
toolbar = (Toolbar) findViewById(R.id.toolbar);
|
||||
toolbar.setTitleTextAppearance(getApplicationContext(), R.style.SwapTheme_Wizard_Text_Toolbar);
|
||||
setSupportActionBar(toolbar);
|
||||
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
|
||||
|
||||
container = (ViewGroup) findViewById(R.id.container);
|
||||
|
||||
@ -238,7 +235,6 @@ public class SwapWorkflowActivity extends AppCompatActivity {
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
compositeDisposable.dispose();
|
||||
localBroadcastManager.unregisterReceiver(downloaderInterruptedReceiver);
|
||||
unbindService(serviceConnection);
|
||||
super.onDestroy();
|
||||
@ -499,6 +495,7 @@ public class SwapWorkflowActivity extends AppCompatActivity {
|
||||
currentView.setLayoutResId(viewRes);
|
||||
currentSwapViewLayoutRes = viewRes;
|
||||
|
||||
toolbar.setBackgroundColor(currentView.getToolbarColour());
|
||||
toolbar.setTitle(currentView.getToolbarTitle());
|
||||
toolbar.setNavigationOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
@ -779,7 +776,7 @@ public class SwapWorkflowActivity extends AppCompatActivity {
|
||||
private final BroadcastReceiver bluetoothScanModeChanged = new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
SwitchMaterial bluetoothSwitch = container.findViewById(R.id.switch_bluetooth);
|
||||
SwitchCompat bluetoothSwitch = container.findViewById(R.id.switch_bluetooth);
|
||||
TextView textBluetoothVisible = container.findViewById(R.id.bluetooth_visible);
|
||||
if (bluetoothSwitch == null || textBluetoothVisible == null
|
||||
|| !BluetoothManager.ACTION_STATUS.equals(intent.getAction())) {
|
||||
@ -933,23 +930,18 @@ public class SwapWorkflowActivity extends AppCompatActivity {
|
||||
ImageView qrImage = container.findViewById(R.id.wifi_qr_code);
|
||||
if (qrUriString != null && qrImage != null) {
|
||||
Utils.debugLog(TAG, "Encoded swap URI in QR Code: " + qrUriString);
|
||||
new QrGenAsyncTask(SwapWorkflowActivity.this, R.id.wifi_qr_code).execute(qrUriString);
|
||||
|
||||
compositeDisposable.add(Utils.generateQrBitmap(this, qrUriString)
|
||||
.subscribe(qrBitmap -> {
|
||||
qrImage.setImageBitmap(qrBitmap);
|
||||
// Replace all blacks with the background blue.
|
||||
qrImage.setColorFilter(new LightingColorFilter(0xffffffff, ContextCompat.getColor(this,
|
||||
R.color.swap_blue)));
|
||||
|
||||
// Replace all blacks with the background blue.
|
||||
qrImage.setColorFilter(new LightingColorFilter(0xffffffff,
|
||||
ContextCompat.getColor(this, R.color.swap_blue)));
|
||||
|
||||
final View qrWarningMessage = container.findViewById(R.id.warning_qr_scanner);
|
||||
if (CameraCharacteristicsChecker.getInstance(this).hasAutofocus()) {
|
||||
qrWarningMessage.setVisibility(View.GONE);
|
||||
} else {
|
||||
qrWarningMessage.setVisibility(View.VISIBLE);
|
||||
}
|
||||
})
|
||||
);
|
||||
final View qrWarningMessage = container.findViewById(R.id.warning_qr_scanner);
|
||||
if (CameraCharacteristicsChecker.getInstance(this).hasAutofocus()) {
|
||||
qrWarningMessage.setVisibility(View.GONE);
|
||||
} else {
|
||||
qrWarningMessage.setVisibility(View.VISIBLE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -996,7 +988,7 @@ public class SwapWorkflowActivity extends AppCompatActivity {
|
||||
}
|
||||
});
|
||||
|
||||
SwitchMaterial wifiSwitch = findViewById(R.id.switch_wifi);
|
||||
SwitchCompat wifiSwitch = findViewById(R.id.switch_wifi);
|
||||
wifiSwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
|
||||
@Override
|
||||
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
|
||||
@ -1120,7 +1112,7 @@ public class SwapWorkflowActivity extends AppCompatActivity {
|
||||
private final BroadcastReceiver bluetoothStatus = new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
SwitchMaterial bluetoothSwitch = container.findViewById(R.id.switch_bluetooth);
|
||||
SwitchCompat bluetoothSwitch = container.findViewById(R.id.switch_bluetooth);
|
||||
TextView textBluetoothVisible = container.findViewById(R.id.bluetooth_visible);
|
||||
TextView textDeviceIdBluetooth = container.findViewById(R.id.device_id_bluetooth);
|
||||
TextView peopleNearbyText = container.findViewById(R.id.text_people_nearby);
|
||||
|
@ -29,7 +29,7 @@ import android.os.Build;
|
||||
import android.os.Process;
|
||||
import android.util.Log;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.documentfile.provider.DocumentFile;
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.fdroid.fdroid.AddRepoIntentService;
|
||||
@ -49,8 +49,6 @@ import java.util.jar.JarEntry;
|
||||
import java.util.jar.JarFile;
|
||||
import java.util.jar.JarInputStream;
|
||||
|
||||
import androidx.documentfile.provider.DocumentFile;
|
||||
|
||||
/**
|
||||
* An {@link IntentService} subclass for handling asynchronous scanning of a
|
||||
* removable storage device like an SD Card or USB OTG thumb drive using the
|
||||
|
@ -8,13 +8,13 @@ import android.os.Build;
|
||||
import android.os.storage.StorageManager;
|
||||
import android.provider.DocumentsContract;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.core.content.ContextCompat;
|
||||
|
||||
import java.io.File;
|
||||
import java.lang.reflect.Array;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.core.content.ContextCompat;
|
||||
|
||||
|
||||
/**
|
||||
* @see <a href="https://stackoverflow.com/a/36162691">Android 5.0 DocumentFile from tree URI</a>
|
||||
|
@ -31,10 +31,8 @@ import android.os.Build;
|
||||
import android.os.Handler;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
|
||||
import org.fdroid.fdroid.views.main.NearbyViewBinder;
|
||||
|
||||
import androidx.annotation.RequiresApi;
|
||||
import org.fdroid.fdroid.views.main.NearbyViewBinder;
|
||||
|
||||
|
||||
/**
|
||||
|
@ -29,13 +29,11 @@ import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.annotation.RequiresApi;
|
||||
import org.fdroid.fdroid.views.main.NearbyViewBinder;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
import androidx.annotation.RequiresApi;
|
||||
|
||||
/**
|
||||
* This is just a shim to receive {@link UsbManager#ACTION_USB_DEVICE_DETACHED}
|
||||
* events.
|
||||
|
@ -4,7 +4,6 @@ import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Environment;
|
||||
|
||||
import org.fdroid.fdroid.views.main.NearbyViewBinder;
|
||||
|
||||
public class UsbDeviceMediaMountedReceiver extends BroadcastReceiver {
|
||||
|
@ -4,7 +4,6 @@ import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.net.wifi.WifiManager;
|
||||
|
||||
import org.fdroid.fdroid.Utils;
|
||||
|
||||
public class WifiStateChangeReceiver extends BroadcastReceiver {
|
||||
|
@ -10,13 +10,12 @@ import android.net.wifi.WifiConfiguration;
|
||||
import android.net.wifi.WifiInfo;
|
||||
import android.net.wifi.WifiManager;
|
||||
import android.os.Build;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
|
||||
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
import cc.mvdan.accesspoint.WifiApControl;
|
||||
import org.apache.commons.net.util.SubnetUtils;
|
||||
import org.fdroid.fdroid.BuildConfig;
|
||||
import org.fdroid.fdroid.FDroidApp;
|
||||
@ -35,9 +34,6 @@ import java.security.cert.Certificate;
|
||||
import java.util.Enumeration;
|
||||
import java.util.Locale;
|
||||
|
||||
import cc.mvdan.accesspoint.WifiApControl;
|
||||
import io.reactivex.rxjava3.disposables.CompositeDisposable;
|
||||
|
||||
/**
|
||||
* Handle state changes to the device's wifi, storing the required bits.
|
||||
* The {@link Intent} that starts it either has no extras included,
|
||||
@ -72,8 +68,6 @@ public class WifiStateChangeService extends IntentService {
|
||||
private static int previousWifiState = Integer.MIN_VALUE;
|
||||
private static int wifiState;
|
||||
|
||||
private final CompositeDisposable compositeDisposable = new CompositeDisposable();
|
||||
|
||||
public WifiStateChangeService() {
|
||||
super("WifiStateChangeService");
|
||||
}
|
||||
@ -86,12 +80,6 @@ public class WifiStateChangeService extends IntentService {
|
||||
context.startService(intent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
compositeDisposable.dispose();
|
||||
super.onDestroy();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onHandleIntent(Intent intent) {
|
||||
android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_LOWEST);
|
||||
@ -119,7 +107,7 @@ public class WifiStateChangeService extends IntentService {
|
||||
}
|
||||
|
||||
if (Build.VERSION.SDK_INT < 21 && wifiState == WifiManager.WIFI_STATE_ENABLED) {
|
||||
compositeDisposable.add(UpdateService.scheduleIfStillOnWifi(this).subscribe());
|
||||
UpdateService.scheduleIfStillOnWifi(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -5,10 +5,10 @@ import android.bluetooth.BluetoothDevice;
|
||||
import android.os.Parcel;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import org.fdroid.fdroid.R;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import org.fdroid.fdroid.R;
|
||||
|
||||
public class BluetoothPeer implements Peer {
|
||||
|
||||
private static final String BLUETOOTH_NAME_TAG = "FDroid:";
|
||||
|
@ -2,15 +2,13 @@ package org.fdroid.fdroid.nearby.peers;
|
||||
|
||||
import android.net.Uri;
|
||||
import android.os.Parcel;
|
||||
import androidx.annotation.Nullable;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import org.fdroid.fdroid.FDroidApp;
|
||||
|
||||
import javax.jmdns.ServiceInfo;
|
||||
import javax.jmdns.impl.FDroidServiceInfo;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
public class BonjourPeer extends WifiPeer {
|
||||
private static final String TAG = "BonjourPeer";
|
||||
|
||||
|
@ -1,7 +1,6 @@
|
||||
package org.fdroid.fdroid.nearby.peers;
|
||||
|
||||
import android.os.Parcelable;
|
||||
|
||||
import androidx.annotation.DrawableRes;
|
||||
|
||||
/**
|
||||
|
@ -1,21 +1,17 @@
|
||||
package org.fdroid.fdroid.panic;
|
||||
|
||||
import android.os.Bundle;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.appcompat.widget.Toolbar;
|
||||
import android.view.View;
|
||||
import android.widget.Button;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.google.android.material.appbar.MaterialToolbar;
|
||||
|
||||
import org.fdroid.fdroid.FDroidApp;
|
||||
import org.fdroid.fdroid.R;
|
||||
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
|
||||
/**
|
||||
* A very hacky calculator which is barely functional.
|
||||
* It is just meant to pass a very casual inspection.
|
||||
@ -39,13 +35,10 @@ public class CalculatorActivity extends AppCompatActivity {
|
||||
|
||||
@Override
|
||||
protected void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
FDroidApp fdroidApp = (FDroidApp) getApplication();
|
||||
fdroidApp.applyPureBlackBackgroundInDarkTheme(this);
|
||||
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_calculator);
|
||||
|
||||
MaterialToolbar toolbar = findViewById(R.id.toolbar);
|
||||
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
|
||||
setSupportActionBar(toolbar);
|
||||
|
||||
textView = (TextView) findViewById(R.id.textView);
|
||||
|
@ -3,13 +3,13 @@ package org.fdroid.fdroid.panic;
|
||||
import android.content.Context;
|
||||
import android.util.AttributeSet;
|
||||
|
||||
import org.fdroid.fdroid.FDroidApp;
|
||||
import org.fdroid.fdroid.R;
|
||||
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.preference.CheckBoxPreference;
|
||||
import androidx.preference.PreferenceViewHolder;
|
||||
|
||||
import org.fdroid.fdroid.FDroidApp;
|
||||
import org.fdroid.fdroid.R;
|
||||
|
||||
public class DestructiveCheckBoxPreference extends CheckBoxPreference {
|
||||
public DestructiveCheckBoxPreference(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
|
@ -3,13 +3,13 @@ package org.fdroid.fdroid.panic;
|
||||
import android.content.Context;
|
||||
import android.util.AttributeSet;
|
||||
|
||||
import org.fdroid.fdroid.FDroidApp;
|
||||
import org.fdroid.fdroid.R;
|
||||
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.preference.Preference;
|
||||
import androidx.preference.PreferenceViewHolder;
|
||||
|
||||
import org.fdroid.fdroid.FDroidApp;
|
||||
import org.fdroid.fdroid.R;
|
||||
|
||||
public class DestructivePreference extends Preference {
|
||||
public DestructivePreference(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
|
@ -3,7 +3,6 @@ package org.fdroid.fdroid.panic;
|
||||
import android.content.Intent;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
|
||||
public class ExitActivity extends AppCompatActivity {
|
||||
|
@ -7,14 +7,12 @@ import android.content.Intent;
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.ServiceInfo;
|
||||
|
||||
import androidx.core.app.NotificationManagerCompat;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import org.fdroid.fdroid.BuildConfig;
|
||||
import org.fdroid.fdroid.R;
|
||||
import org.fdroid.fdroid.views.main.MainActivity;
|
||||
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.core.app.NotificationManagerCompat;
|
||||
|
||||
/**
|
||||
* This class is encapsulating all methods related to hiding the app from the launcher
|
||||
* and restoring it.
|
||||
|
@ -1,32 +1,37 @@
|
||||
package org.fdroid.fdroid.panic;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.view.View;
|
||||
|
||||
import com.google.android.material.appbar.MaterialToolbar;
|
||||
|
||||
import androidx.appcompat.app.ActionBar;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.appcompat.widget.Toolbar;
|
||||
import android.view.MenuItem;
|
||||
import org.fdroid.fdroid.FDroidApp;
|
||||
import org.fdroid.fdroid.R;
|
||||
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
|
||||
public class PanicPreferencesActivity extends AppCompatActivity {
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle bundle) {
|
||||
FDroidApp fdroidApp = (FDroidApp) getApplication();
|
||||
fdroidApp.applyPureBlackBackgroundInDarkTheme(this);
|
||||
|
||||
((FDroidApp) getApplication()).applyTheme(this);
|
||||
super.onCreate(bundle);
|
||||
setContentView(R.layout.activity_panic_settings);
|
||||
|
||||
MaterialToolbar toolbar = findViewById(R.id.toolbar);
|
||||
toolbar.setNavigationOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
// Handle navigation icon press
|
||||
onBackPressed();
|
||||
}
|
||||
});
|
||||
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
|
||||
setSupportActionBar(toolbar);
|
||||
ActionBar ab = getSupportActionBar();
|
||||
if (ab != null) {
|
||||
ab.setDisplayShowHomeEnabled(true);
|
||||
ab.setDisplayHomeAsUpEnabled(true);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
if (item.getItemId() == android.R.id.home) {
|
||||
onBackPressed();
|
||||
return true;
|
||||
}
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
package org.fdroid.fdroid.panic;
|
||||
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import android.content.ComponentName;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
@ -15,6 +16,16 @@ import android.os.Bundle;
|
||||
import android.text.TextUtils;
|
||||
import android.util.TypedValue;
|
||||
|
||||
import androidx.annotation.ColorInt;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.preference.CheckBoxPreference;
|
||||
import androidx.preference.ListPreference;
|
||||
import androidx.preference.Preference;
|
||||
import androidx.preference.PreferenceCategory;
|
||||
import androidx.preference.PreferenceFragmentCompat;
|
||||
|
||||
import org.fdroid.fdroid.Preferences;
|
||||
import org.fdroid.fdroid.R;
|
||||
import org.fdroid.fdroid.installer.PrivilegedInstaller;
|
||||
@ -22,16 +33,6 @@ import org.fdroid.fdroid.installer.PrivilegedInstaller;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Set;
|
||||
|
||||
import androidx.annotation.ColorInt;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.preference.CheckBoxPreference;
|
||||
import androidx.preference.ListPreference;
|
||||
import androidx.preference.Preference;
|
||||
import androidx.preference.PreferenceCategory;
|
||||
import androidx.preference.PreferenceFragmentCompat;
|
||||
import info.guardianproject.panic.Panic;
|
||||
import info.guardianproject.panic.PanicResponder;
|
||||
|
||||
|
@ -1,13 +1,17 @@
|
||||
package org.fdroid.fdroid.panic;
|
||||
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.ContentValues;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import android.util.Log;
|
||||
|
||||
import info.guardianproject.panic.Panic;
|
||||
import info.guardianproject.panic.PanicResponder;
|
||||
import org.fdroid.fdroid.Preferences;
|
||||
import org.fdroid.fdroid.data.Apk;
|
||||
import org.fdroid.fdroid.data.DBHelper;
|
||||
@ -27,11 +31,6 @@ import java.util.List;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
|
||||
import info.guardianproject.panic.Panic;
|
||||
import info.guardianproject.panic.PanicResponder;
|
||||
|
||||
/**
|
||||
* This {@link AppCompatActivity} is purely to run events in response to a panic trigger.
|
||||
* It needs to be an {@code AppCompatActivity} rather than a {@link android.app.Service}
|
||||
|
@ -1,8 +1,9 @@
|
||||
package org.fdroid.fdroid.panic;
|
||||
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.annotation.NonNull;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import org.fdroid.fdroid.Preferences;
|
||||
import org.fdroid.fdroid.R;
|
||||
import org.fdroid.fdroid.views.installed.InstalledAppListAdapter;
|
||||
@ -10,9 +11,6 @@ import org.fdroid.fdroid.views.installed.InstalledAppListItemController;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
|
||||
public class SelectInstalledAppListAdapter extends InstalledAppListAdapter {
|
||||
private final Set<String> selectedApps;
|
||||
|
||||
|
@ -1,7 +1,9 @@
|
||||
package org.fdroid.fdroid.panic;
|
||||
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import android.view.View;
|
||||
|
||||
import org.fdroid.fdroid.AppUpdateStatusManager;
|
||||
import org.fdroid.fdroid.data.App;
|
||||
import org.fdroid.fdroid.views.apps.AppListItemState;
|
||||
@ -9,10 +11,6 @@ import org.fdroid.fdroid.views.installed.InstalledAppListItemController;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
|
||||
/**
|
||||
* Shows the currently installed apps as a selectable list.
|
||||
*/
|
||||
|
@ -27,7 +27,15 @@ import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.google.android.material.appbar.MaterialToolbar;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.appcompat.widget.Toolbar;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.loader.app.LoaderManager;
|
||||
import androidx.loader.content.CursorLoader;
|
||||
import androidx.loader.content.Loader;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import org.fdroid.fdroid.FDroidApp;
|
||||
import org.fdroid.fdroid.Preferences;
|
||||
@ -35,14 +43,6 @@ import org.fdroid.fdroid.R;
|
||||
import org.fdroid.fdroid.data.InstalledAppProvider;
|
||||
import org.fdroid.fdroid.views.installed.InstalledAppListAdapter;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.loader.app.LoaderManager;
|
||||
import androidx.loader.content.CursorLoader;
|
||||
import androidx.loader.content.Loader;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
public class SelectInstalledAppsActivity extends AppCompatActivity implements LoaderManager.LoaderCallbacks<Cursor> {
|
||||
|
||||
private InstalledAppListAdapter adapter;
|
||||
@ -54,14 +54,13 @@ public class SelectInstalledAppsActivity extends AppCompatActivity implements Lo
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
FDroidApp fdroidApp = (FDroidApp) getApplication();
|
||||
fdroidApp.applyPureBlackBackgroundInDarkTheme(this);
|
||||
|
||||
((FDroidApp) getApplication()).applyTheme(this);
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
setContentView(R.layout.installed_apps_layout);
|
||||
|
||||
MaterialToolbar toolbar = findViewById(R.id.toolbar);
|
||||
Toolbar toolbar = findViewById(R.id.toolbar);
|
||||
toolbar.setTitle(getString(R.string.panic_add_apps_to_uninstall));
|
||||
setSupportActionBar(toolbar);
|
||||
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
|
||||
|
@ -6,9 +6,15 @@ import android.os.Bundle;
|
||||
import android.view.View;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.loader.app.LoaderManager;
|
||||
import androidx.loader.content.CursorLoader;
|
||||
import androidx.loader.content.Loader;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
|
||||
import com.google.android.material.floatingactionbutton.FloatingActionButton;
|
||||
|
||||
import org.fdroid.fdroid.Preferences;
|
||||
import org.fdroid.fdroid.R;
|
||||
import org.fdroid.fdroid.UpdateService;
|
||||
@ -25,15 +31,6 @@ import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.loader.app.LoaderManager;
|
||||
import androidx.loader.content.CursorLoader;
|
||||
import androidx.loader.content.Loader;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
|
||||
|
||||
/**
|
||||
* Responsible for ensuring that the categories view is inflated and then populated correctly.
|
||||
* Will start a loader to get the list of categories from the database and populate a recycler
|
||||
|
@ -2,15 +2,15 @@ package org.fdroid.fdroid.views.main;
|
||||
|
||||
import android.widget.FrameLayout;
|
||||
|
||||
import org.fdroid.fdroid.R;
|
||||
import org.fdroid.fdroid.views.PreferencesFragment;
|
||||
import org.fdroid.fdroid.views.updates.UpdatesViewBinder;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import org.fdroid.fdroid.R;
|
||||
import org.fdroid.fdroid.views.PreferencesFragment;
|
||||
import org.fdroid.fdroid.views.updates.UpdatesViewBinder;
|
||||
|
||||
/**
|
||||
* Decides which view on the main screen to attach to a given {@link FrameLayout}. This class
|
||||
* doesn't know which view it will be rendering at the time it is constructed. Rather, at some
|
||||
|
@ -1,6 +1,7 @@
|
||||
package org.fdroid.fdroid.views.main;
|
||||
|
||||
import android.Manifest;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.UriPermission;
|
||||
@ -21,7 +22,9 @@ import android.widget.FrameLayout;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.annotation.RequiresApi;
|
||||
import androidx.core.app.ActivityCompat;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import org.fdroid.fdroid.R;
|
||||
import org.fdroid.fdroid.Utils;
|
||||
import org.fdroid.fdroid.nearby.SDCardScannerService;
|
||||
@ -31,11 +34,6 @@ import org.fdroid.fdroid.nearby.TreeUriScannerIntentService;
|
||||
import java.io.File;
|
||||
import java.util.List;
|
||||
|
||||
import androidx.annotation.RequiresApi;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.core.app.ActivityCompat;
|
||||
import androidx.core.content.ContextCompat;
|
||||
|
||||
/**
|
||||
* A splash screen encouraging people to start the swap process. The swap
|
||||
* process is quite heavy duty in that it fires up Bluetooth and/or WiFi
|
||||
|
12
app/src/full/res/drawable/ic_check_circle.xml
Normal file
@ -0,0 +1,12 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24"
|
||||
android:tint="?attr/colorControlNormal"
|
||||
tools:ignore="VectorRaster">
|
||||
<path
|
||||
android:fillColor="#FFFFFF"
|
||||
android:pathData="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM9.29,16.29L5.7,12.7c-0.39,-0.39 -0.39,-1.02 0,-1.41 0.39,-0.39 1.02,-0.39 1.41,0L10,14.17l6.88,-6.88c0.39,-0.39 1.02,-0.39 1.41,0 0.39,0.39 0.39,1.02 0,1.41l-7.59,7.59c-0.38,0.39 -1.02,0.39 -1.41,0z"/>
|
||||
</vector>
|
@ -1,8 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<RelativeLayout
|
||||
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"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/header"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="130dp"
|
||||
@ -13,7 +12,7 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:scaleType="centerCrop"
|
||||
app:srcCompat="@drawable/swap_start_header"/>
|
||||
android:src="@drawable/swap_start_header"/>
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
|
78
app/src/full/res/layout-v11/select_local_apps_list_item.xml
Normal file
@ -0,0 +1,78 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright (C) 2010 The Android Open Source Project
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:minHeight="?android:attr/listPreferredItemHeight"
|
||||
android:paddingBottom="2dip"
|
||||
android:paddingTop="2dip">
|
||||
|
||||
<ImageView
|
||||
android:id="@android:id/icon"
|
||||
android:layout_width="48dip"
|
||||
android:layout_height="48dip"
|
||||
android:layout_marginLeft="?attr/listPreferredItemPaddingLeft"
|
||||
android:layout_marginStart="?android:attr/listPreferredItemPaddingStart"
|
||||
android:layout_marginTop="6dip"
|
||||
android:layout_alignParentStart="true"
|
||||
android:layout_alignParentLeft="true"
|
||||
tools:src="@drawable/ic_launcher"
|
||||
tools:ignore="ContentDescription" />
|
||||
|
||||
<!-- Suppress InconsistentLayout because the lower API levels use a checkbox rather than this -->
|
||||
<ImageView
|
||||
android:id="@+id/checked"
|
||||
android:layout_width="32dip"
|
||||
android:layout_height="32dip"
|
||||
android:layout_marginRight="?attr/listPreferredItemPaddingLeft"
|
||||
android:layout_marginEnd="?android:attr/listPreferredItemPaddingStart"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_centerVertical="true"
|
||||
tools:suppress="InconsistentLayout"
|
||||
android:src="@drawable/ic_add_circle_outline" />
|
||||
|
||||
<TwoLineListItem
|
||||
android:layout_toRightOf="@android:id/icon"
|
||||
android:layout_toEndOf="@android:id/icon"
|
||||
android:layout_toLeftOf="@id/checked"
|
||||
android:layout_toStartOf="@id/checked"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:mode="twoLine" >
|
||||
|
||||
<TextView
|
||||
android:id="@+id/application_label"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="?attr/listPreferredItemPaddingLeft"
|
||||
android:layout_marginStart="?android:attr/listPreferredItemPaddingStart"
|
||||
android:layout_marginTop="6dip"
|
||||
android:textAppearance="?android:attr/textAppearanceMedium"
|
||||
tools:text="F-Droid" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/package_name"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignStart="@+id/application_label"
|
||||
android:layout_alignLeft="@+id/application_label"
|
||||
android:layout_below="@+id/application_label"
|
||||
android:textAppearance="?android:attr/textAppearanceSmall"
|
||||
tools:text="Application Manager" />
|
||||
</TwoLineListItem>
|
||||
|
||||
</RelativeLayout>
|
70
app/src/full/res/layout-v17/select_local_apps_list_item.xml
Normal file
@ -0,0 +1,70 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright (C) 2010 The Android Open Source Project
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:minHeight="?android:attr/listPreferredItemHeight"
|
||||
android:paddingBottom="2dip"
|
||||
android:paddingTop="2dip">
|
||||
|
||||
<ImageView
|
||||
android:id="@android:id/icon"
|
||||
android:layout_width="48dip"
|
||||
android:layout_height="48dip"
|
||||
android:layout_marginStart="?android:attr/listPreferredItemPaddingStart"
|
||||
android:layout_marginTop="6dip"
|
||||
android:layout_alignParentStart="true"
|
||||
tools:src="@drawable/ic_launcher"
|
||||
tools:ignore="ContentDescription" />
|
||||
|
||||
<!-- Suppress InconsistentLayout because the lower API levels use a checkbox rather than this -->
|
||||
<ImageView
|
||||
android:id="@+id/checked"
|
||||
android:layout_width="32dip"
|
||||
android:layout_height="32dip"
|
||||
android:layout_marginEnd="?android:attr/listPreferredItemPaddingStart"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_centerVertical="true"
|
||||
tools:suppress="InconsistentLayout"
|
||||
android:src="@drawable/ic_add_circle_outline" />
|
||||
|
||||
<TwoLineListItem
|
||||
android:layout_toEndOf="@android:id/icon"
|
||||
android:layout_toStartOf="@id/checked"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:mode="twoLine" >
|
||||
|
||||
<TextView
|
||||
android:id="@+id/application_label"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="?android:attr/listPreferredItemPaddingStart"
|
||||
android:layout_marginTop="6dip"
|
||||
android:textAppearance="?android:attr/textAppearanceMedium"
|
||||
tools:text="F-Droid" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/package_name"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignStart="@+id/application_label"
|
||||
android:layout_below="@+id/application_label"
|
||||
android:textAppearance="?android:attr/textAppearanceSmall"
|
||||
tools:text="Application Manager" />
|
||||
</TwoLineListItem>
|
||||
|
||||
</RelativeLayout>
|
@ -1,302 +1,291 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
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"
|
||||
<androidx.constraintlayout.widget.ConstraintLayout 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"
|
||||
tools:context=".panic.CalculatorActivity">
|
||||
|
||||
<androidx.appcompat.widget.Toolbar
|
||||
android:id="@+id/toolbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:context=".panic.CalculatorActivity"
|
||||
android:fitsSystemWindows="true">
|
||||
|
||||
<com.google.android.material.appbar.AppBarLayout
|
||||
android:id="@+id/topAppBarLayout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:fitsSystemWindows="true"
|
||||
app:liftOnScroll="true"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
<com.google.android.material.appbar.MaterialToolbar
|
||||
android:id="@+id/toolbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="?attr/actionBarSize"
|
||||
app:navigationIcon="@drawable/ic_back"
|
||||
style="@style/Widget.MaterialComponents.Toolbar.PrimarySurface" />
|
||||
|
||||
</com.google.android.material.appbar.AppBarLayout>
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?attr/colorPrimary"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:theme="?attr/actionBarTheme" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textView"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:layout_marginStart="8dp"
|
||||
android:layout_marginTop="8dp"
|
||||
android:gravity="bottom|end"
|
||||
android:padding="5dp"
|
||||
android:textAlignment="textEnd"
|
||||
android:textSize="22sp"
|
||||
android:typeface="monospace"
|
||||
app:layout_constraintBottom_toTopOf="@+id/ce"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/topAppBarLayout"
|
||||
tools:text="1337+42" />
|
||||
android:id="@+id/textView"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:layout_marginStart="8dp"
|
||||
android:layout_marginTop="8dp"
|
||||
android:gravity="bottom|end"
|
||||
android:padding="5dp"
|
||||
android:textAlignment="textEnd"
|
||||
android:textSize="22sp"
|
||||
android:typeface="monospace"
|
||||
app:layout_constraintBottom_toTopOf="@+id/ce"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/toolbar"
|
||||
tools:text="1337+42" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/times"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:layout_marginLeft="8dp"
|
||||
android:layout_marginStart="8dp"
|
||||
android:onClick="op"
|
||||
android:text="×"
|
||||
app:layout_constraintBottom_toTopOf="@+id/seven"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
tools:ignore="HardcodedText" />
|
||||
android:id="@+id/times"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:layout_marginLeft="8dp"
|
||||
android:layout_marginStart="8dp"
|
||||
android:onClick="op"
|
||||
android:text="×"
|
||||
app:layout_constraintBottom_toTopOf="@+id/seven"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
tools:ignore="HardcodedText" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/divided"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:layout_marginLeft="8dp"
|
||||
android:layout_marginStart="8dp"
|
||||
android:onClick="op"
|
||||
android:text="÷"
|
||||
app:layout_constraintBottom_toTopOf="@+id/eight"
|
||||
app:layout_constraintStart_toEndOf="@+id/times"
|
||||
tools:ignore="HardcodedText" />
|
||||
android:id="@+id/divided"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:layout_marginLeft="8dp"
|
||||
android:layout_marginStart="8dp"
|
||||
android:onClick="op"
|
||||
android:text="÷"
|
||||
app:layout_constraintBottom_toTopOf="@+id/eight"
|
||||
app:layout_constraintStart_toEndOf="@+id/times"
|
||||
tools:ignore="HardcodedText" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/c"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:layout_marginLeft="8dp"
|
||||
android:layout_marginStart="8dp"
|
||||
android:onClick="c"
|
||||
android:text="C"
|
||||
app:layout_constraintBottom_toTopOf="@+id/nine"
|
||||
app:layout_constraintStart_toEndOf="@+id/divided"
|
||||
tools:ignore="HardcodedText" />
|
||||
android:id="@+id/c"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:layout_marginLeft="8dp"
|
||||
android:layout_marginStart="8dp"
|
||||
android:onClick="c"
|
||||
android:text="C"
|
||||
app:layout_constraintBottom_toTopOf="@+id/nine"
|
||||
app:layout_constraintStart_toEndOf="@+id/divided"
|
||||
tools:ignore="HardcodedText" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/seven"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:layout_marginLeft="8dp"
|
||||
android:layout_marginStart="8dp"
|
||||
android:onClick="number"
|
||||
android:text="7"
|
||||
app:layout_constraintBottom_toTopOf="@+id/four"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
tools:ignore="HardcodedText" />
|
||||
android:id="@+id/seven"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:layout_marginLeft="8dp"
|
||||
android:layout_marginStart="8dp"
|
||||
android:onClick="number"
|
||||
android:text="7"
|
||||
app:layout_constraintBottom_toTopOf="@+id/four"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
tools:ignore="HardcodedText" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/eight"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:layout_marginLeft="8dp"
|
||||
android:layout_marginStart="8dp"
|
||||
android:onClick="number"
|
||||
android:text="8"
|
||||
app:layout_constraintBottom_toTopOf="@+id/five"
|
||||
app:layout_constraintStart_toEndOf="@+id/seven"
|
||||
tools:ignore="HardcodedText" />
|
||||
android:id="@+id/eight"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:layout_marginLeft="8dp"
|
||||
android:layout_marginStart="8dp"
|
||||
android:onClick="number"
|
||||
android:text="8"
|
||||
app:layout_constraintBottom_toTopOf="@+id/five"
|
||||
app:layout_constraintStart_toEndOf="@+id/seven"
|
||||
tools:ignore="HardcodedText" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/nine"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:layout_marginLeft="8dp"
|
||||
android:layout_marginStart="8dp"
|
||||
android:onClick="number"
|
||||
android:text="9"
|
||||
app:layout_constraintBottom_toTopOf="@+id/six"
|
||||
app:layout_constraintStart_toEndOf="@+id/eight"
|
||||
tools:ignore="HardcodedText" />
|
||||
android:id="@+id/nine"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:layout_marginLeft="8dp"
|
||||
android:layout_marginStart="8dp"
|
||||
android:onClick="number"
|
||||
android:text="9"
|
||||
app:layout_constraintBottom_toTopOf="@+id/six"
|
||||
app:layout_constraintStart_toEndOf="@+id/eight"
|
||||
tools:ignore="HardcodedText" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/ce"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:layout_marginStart="8dp"
|
||||
android:onClick="ce"
|
||||
android:text="CE"
|
||||
app:layout_constraintBottom_toTopOf="@+id/plus"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@+id/nine"
|
||||
tools:ignore="HardcodedText" />
|
||||
android:id="@+id/ce"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:layout_marginStart="8dp"
|
||||
android:onClick="ce"
|
||||
android:text="CE"
|
||||
app:layout_constraintBottom_toTopOf="@+id/plus"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@+id/nine"
|
||||
tools:ignore="HardcodedText" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/four"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:layout_marginLeft="8dp"
|
||||
android:layout_marginStart="8dp"
|
||||
android:onClick="number"
|
||||
android:text="4"
|
||||
app:layout_constraintBottom_toTopOf="@+id/one"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
tools:ignore="HardcodedText" />
|
||||
android:id="@+id/four"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:layout_marginLeft="8dp"
|
||||
android:layout_marginStart="8dp"
|
||||
android:onClick="number"
|
||||
android:text="4"
|
||||
app:layout_constraintBottom_toTopOf="@+id/one"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
tools:ignore="HardcodedText" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/five"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:layout_marginLeft="8dp"
|
||||
android:layout_marginStart="8dp"
|
||||
android:onClick="number"
|
||||
android:text="5"
|
||||
app:layout_constraintBottom_toTopOf="@+id/two"
|
||||
app:layout_constraintStart_toEndOf="@+id/four"
|
||||
tools:ignore="HardcodedText" />
|
||||
android:id="@+id/five"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:layout_marginLeft="8dp"
|
||||
android:layout_marginStart="8dp"
|
||||
android:onClick="number"
|
||||
android:text="5"
|
||||
app:layout_constraintBottom_toTopOf="@+id/two"
|
||||
app:layout_constraintStart_toEndOf="@+id/four"
|
||||
tools:ignore="HardcodedText" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/six"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:layout_marginLeft="8dp"
|
||||
android:layout_marginStart="8dp"
|
||||
android:onClick="number"
|
||||
android:text="6"
|
||||
app:layout_constraintBottom_toTopOf="@+id/three"
|
||||
app:layout_constraintStart_toEndOf="@+id/five"
|
||||
tools:ignore="HardcodedText" />
|
||||
android:id="@+id/six"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:layout_marginLeft="8dp"
|
||||
android:layout_marginStart="8dp"
|
||||
android:onClick="number"
|
||||
android:text="6"
|
||||
app:layout_constraintBottom_toTopOf="@+id/three"
|
||||
app:layout_constraintStart_toEndOf="@+id/five"
|
||||
tools:ignore="HardcodedText" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/plus"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:layout_marginStart="8dp"
|
||||
android:onClick="op"
|
||||
android:text="+"
|
||||
app:layout_constraintBottom_toTopOf="@+id/minus"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@+id/six"
|
||||
tools:ignore="HardcodedText" />
|
||||
android:id="@+id/plus"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:layout_marginStart="8dp"
|
||||
android:onClick="op"
|
||||
android:text="+"
|
||||
app:layout_constraintBottom_toTopOf="@+id/minus"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@+id/six"
|
||||
tools:ignore="HardcodedText" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/minus"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:layout_marginStart="8dp"
|
||||
android:onClick="op"
|
||||
android:text="-"
|
||||
app:layout_constraintBottom_toTopOf="@+id/equals"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@+id/three"
|
||||
tools:ignore="HardcodedText" />
|
||||
android:id="@+id/minus"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:layout_marginStart="8dp"
|
||||
android:onClick="op"
|
||||
android:text="-"
|
||||
app:layout_constraintBottom_toTopOf="@+id/equals"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@+id/three"
|
||||
tools:ignore="HardcodedText" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/one"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:layout_marginLeft="8dp"
|
||||
android:layout_marginStart="8dp"
|
||||
android:onClick="number"
|
||||
android:text="1"
|
||||
app:layout_constraintBottom_toTopOf="@+id/zero"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
tools:ignore="HardcodedText" />
|
||||
android:id="@+id/one"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:layout_marginLeft="8dp"
|
||||
android:layout_marginStart="8dp"
|
||||
android:onClick="number"
|
||||
android:text="1"
|
||||
app:layout_constraintBottom_toTopOf="@+id/zero"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
tools:ignore="HardcodedText" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/two"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:layout_marginLeft="8dp"
|
||||
android:layout_marginStart="8dp"
|
||||
android:onClick="number"
|
||||
android:text="2"
|
||||
app:layout_constraintBottom_toTopOf="@+id/comma"
|
||||
app:layout_constraintStart_toEndOf="@+id/one"
|
||||
tools:ignore="HardcodedText" />
|
||||
android:id="@+id/two"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:layout_marginLeft="8dp"
|
||||
android:layout_marginStart="8dp"
|
||||
android:onClick="number"
|
||||
android:text="2"
|
||||
app:layout_constraintBottom_toTopOf="@+id/comma"
|
||||
app:layout_constraintStart_toEndOf="@+id/one"
|
||||
tools:ignore="HardcodedText" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/three"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:layout_marginLeft="8dp"
|
||||
android:layout_marginStart="8dp"
|
||||
android:onClick="number"
|
||||
android:text="3"
|
||||
app:layout_constraintBottom_toTopOf="@+id/percent"
|
||||
app:layout_constraintStart_toEndOf="@+id/two"
|
||||
tools:ignore="HardcodedText" />
|
||||
android:id="@+id/three"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:layout_marginLeft="8dp"
|
||||
android:layout_marginStart="8dp"
|
||||
android:onClick="number"
|
||||
android:text="3"
|
||||
app:layout_constraintBottom_toTopOf="@+id/percent"
|
||||
app:layout_constraintStart_toEndOf="@+id/two"
|
||||
tools:ignore="HardcodedText" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/zero"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:layout_marginLeft="8dp"
|
||||
android:layout_marginStart="8dp"
|
||||
android:onClick="number"
|
||||
android:text="0"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
tools:ignore="HardcodedText" />
|
||||
android:id="@+id/zero"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:layout_marginLeft="8dp"
|
||||
android:layout_marginStart="8dp"
|
||||
android:onClick="number"
|
||||
android:text="0"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
tools:ignore="HardcodedText" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/comma"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:layout_marginLeft="8dp"
|
||||
android:layout_marginStart="8dp"
|
||||
android:onClick="number"
|
||||
android:text="."
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@+id/zero"
|
||||
tools:ignore="HardcodedText" />
|
||||
android:id="@+id/comma"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:layout_marginLeft="8dp"
|
||||
android:layout_marginStart="8dp"
|
||||
android:onClick="number"
|
||||
android:text="."
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@+id/zero"
|
||||
tools:ignore="HardcodedText" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/percent"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:layout_marginLeft="8dp"
|
||||
android:layout_marginStart="8dp"
|
||||
android:onClick="op"
|
||||
android:text="%"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@+id/comma"
|
||||
tools:ignore="HardcodedText" />
|
||||
android:id="@+id/percent"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:layout_marginLeft="8dp"
|
||||
android:layout_marginStart="8dp"
|
||||
android:onClick="op"
|
||||
android:text="%"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@+id/comma"
|
||||
tools:ignore="HardcodedText" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/equals"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:layout_marginStart="8dp"
|
||||
android:onClick="op"
|
||||
android:text="="
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHorizontal_bias="0.0"
|
||||
app:layout_constraintStart_toEndOf="@+id/three"
|
||||
app:layout_constraintTop_toTopOf="@+id/three"
|
||||
tools:ignore="HardcodedText" />
|
||||
android:id="@+id/equals"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:layout_marginStart="8dp"
|
||||
android:onClick="op"
|
||||
android:text="="
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHorizontal_bias="0.0"
|
||||
app:layout_constraintStart_toEndOf="@+id/three"
|
||||
app:layout_constraintTop_toTopOf="@+id/three"
|
||||
tools:ignore="HardcodedText" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
@ -1,32 +1,21 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
|
||||
<androidx.appcompat.widget.Toolbar
|
||||
android:id="@+id/toolbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
android:fitsSystemWindows="true">
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?attr/colorPrimary"
|
||||
app:theme="?attr/actionBarTheme" />
|
||||
|
||||
<com.google.android.material.appbar.AppBarLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:fitsSystemWindows="true"
|
||||
app:liftOnScroll="true">
|
||||
|
||||
<com.google.android.material.appbar.MaterialToolbar
|
||||
android:id="@+id/toolbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="?attr/actionBarSize"
|
||||
app:title="@string/panic_settings"
|
||||
app:navigationIcon="@drawable/ic_back"
|
||||
style="@style/Widget.MaterialComponents.Toolbar.PrimarySurface" />
|
||||
|
||||
</com.google.android.material.appbar.AppBarLayout>
|
||||
|
||||
<androidx.fragment.app.FragmentContainerView
|
||||
android:id="@+id/fragment_container"
|
||||
class="org.fdroid.fdroid.panic.PanicPreferencesFragment"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" />
|
||||
<fragment xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/fragment_container"
|
||||
class="org.fdroid.fdroid.panic.PanicPreferencesFragment"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" />
|
||||
|
||||
</LinearLayout>
|
||||
|
@ -5,8 +5,7 @@
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:orientation="vertical"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:fitsSystemWindows="true">
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
|
||||
android:layout_width="match_parent"
|
||||
@ -17,7 +16,7 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<org.fdroid.fdroid.views.StatusBanner
|
||||
<org.fdroid.fdroid.views.BannerUpdatingRepos
|
||||
android:id="@+id/banner_updating_repos"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
|
@ -11,7 +11,7 @@
|
||||
android:id="@+id/image"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
app:srcCompat="@drawable/nearby_splash"
|
||||
android:src="@drawable/nearby_splash"
|
||||
android:importantForAccessibility="no"
|
||||
app:layout_constraintRight_toRightOf="parent"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
|
@ -16,7 +16,7 @@
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:minHeight="?attr/listPreferredItemHeight"
|
||||
android:minHeight="?android:attr/listPreferredItemHeight"
|
||||
android:paddingBottom="2dip"
|
||||
android:paddingTop="2dip">
|
||||
|
||||
@ -25,9 +25,10 @@
|
||||
android:layout_width="48dip"
|
||||
android:layout_height="48dip"
|
||||
android:layout_marginLeft="?attr/listPreferredItemPaddingLeft"
|
||||
android:layout_marginStart="?attr/listPreferredItemPaddingStart"
|
||||
android:layout_marginStart="?android:attr/listPreferredItemPaddingStart"
|
||||
android:layout_marginTop="6dip"
|
||||
android:layout_alignParentStart="true"
|
||||
android:layout_alignParentLeft="true"
|
||||
tools:src="@drawable/ic_launcher"
|
||||
tools:ignore="ContentDescription" />
|
||||
|
||||
@ -36,13 +37,15 @@
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="?attr/listPreferredItemPaddingLeft"
|
||||
android:layout_marginStart="?attr/listPreferredItemPaddingStart"
|
||||
android:layout_marginStart="?android:attr/listPreferredItemPaddingStart"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_centerVertical="true" />
|
||||
|
||||
<TwoLineListItem
|
||||
android:layout_toRightOf="@android:id/icon"
|
||||
android:layout_toEndOf="@android:id/icon"
|
||||
android:layout_toLeftOf="@id/checkbox"
|
||||
android:layout_toStartOf="@id/checkbox"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
@ -53,7 +56,7 @@
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="?attr/listPreferredItemPaddingLeft"
|
||||
android:layout_marginStart="?attr/listPreferredItemPaddingStart"
|
||||
android:layout_marginStart="?android:attr/listPreferredItemPaddingStart"
|
||||
android:layout_marginTop="6dip"
|
||||
android:textAppearance="?android:attr/textAppearanceMedium"
|
||||
tools:text="F-Droid" />
|
||||
@ -63,6 +66,7 @@
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignStart="@+id/application_label"
|
||||
android:layout_alignLeft="@+id/application_label"
|
||||
android:layout_below="@+id/application_label"
|
||||
android:textAppearance="?android:attr/textAppearanceSmall"
|
||||
tools:text="Application Manager" />
|
||||
|
@ -1,29 +1,24 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout
|
||||
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"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:orientation="vertical"
|
||||
android:fitsSystemWindows="true">
|
||||
<com.google.android.material.appbar.AppBarLayout
|
||||
android:layout_width="match_parent"
|
||||
android:orientation="vertical">
|
||||
|
||||
<androidx.appcompat.widget.Toolbar
|
||||
android:id="@+id/toolbar"
|
||||
android:layout_height="wrap_content"
|
||||
android:fitsSystemWindows="true"
|
||||
app:liftOnScroll="true">
|
||||
|
||||
<com.google.android.material.appbar.MaterialToolbar
|
||||
android:id="@+id/toolbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="?attr/actionBarSize"
|
||||
app:navigationIcon="@drawable/ic_back"
|
||||
style="@style/Widget.MaterialComponents.Toolbar.PrimarySurface" />
|
||||
|
||||
</com.google.android.material.appbar.AppBarLayout>
|
||||
android:layout_width="match_parent"
|
||||
android:titleTextAppearance="@style/SwapTheme.Wizard.Text"
|
||||
titleTextAppearance="@style/SwapTheme.Wizard.Text"
|
||||
android:minHeight="?attr/actionBarSize"
|
||||
android:background="?attr/colorPrimary"
|
||||
tools:ignore="UnusedAttribute"/>
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/container"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent" />
|
||||
android:layout_height="fill_parent"/>
|
||||
|
||||
</LinearLayout>
|
@ -4,7 +4,7 @@
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:minHeight="?attr/listPreferredItemHeight"
|
||||
android:minHeight="?android:attr/listPreferredItemHeight"
|
||||
android:paddingBottom="2dip"
|
||||
android:paddingTop="2dip">
|
||||
|
||||
@ -12,7 +12,7 @@
|
||||
android:id="@android:id/icon"
|
||||
android:layout_width="48dip"
|
||||
android:layout_height="48dip"
|
||||
android:layout_marginStart="?attr/listPreferredItemPaddingStart"
|
||||
android:layout_marginStart="?android:attr/listPreferredItemPaddingStart"
|
||||
android:layout_marginLeft="10dp"
|
||||
android:layout_marginTop="6dip"
|
||||
android:layout_alignParentStart="true"
|
||||
@ -28,7 +28,7 @@
|
||||
android:layout_centerInParent="true"
|
||||
android:orientation="vertical"
|
||||
android:gravity="end"
|
||||
android:layout_marginEnd="?attr/listPreferredItemPaddingEnd"
|
||||
android:layout_marginEnd="?android:attr/listPreferredItemPaddingEnd"
|
||||
android:layout_marginRight="10dp">
|
||||
|
||||
<Button
|
||||
@ -68,7 +68,7 @@
|
||||
android:layout_toLeftOf="@+id/button_or_text"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="?attr/listPreferredItemPaddingStart"
|
||||
android:layout_marginStart="?android:attr/listPreferredItemPaddingStart"
|
||||
android:layout_marginLeft="10dp"
|
||||
android:layout_marginTop="6dip"
|
||||
android:layout_marginBottom="6dip"
|
||||
|
@ -14,7 +14,7 @@
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/icon"
|
||||
swap:srcCompat="@drawable/ic_launcher"
|
||||
android:src="@drawable/ic_launcher"
|
||||
android:contentDescription="@string/icon"
|
||||
android:layout_alignParentTop="true"
|
||||
android:layout_width="117.6dp"
|
||||
|
@ -25,7 +25,7 @@
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:id="@+id/wifi_icon"
|
||||
swap:srcCompat="@drawable/ic_wifi"
|
||||
android:src="@drawable/ic_wifi"
|
||||
android:layout_below="@+id/text_description"
|
||||
android:layout_centerHorizontal="true"/>
|
||||
|
||||
|
@ -14,7 +14,7 @@
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:id="@+id/icon_nfc"
|
||||
swap:srcCompat="@drawable/nfc_touch"
|
||||
android:src="@drawable/nfc_touch"
|
||||
android:layout_alignParentTop="true"
|
||||
android:layout_centerHorizontal="true"/>
|
||||
|
||||
|
@ -14,13 +14,13 @@
|
||||
android:layout_width="32dp"
|
||||
android:layout_height="32dp"
|
||||
android:layout_marginLeft="?attr/listPreferredItemPaddingLeft"
|
||||
android:layout_marginStart="?attr/listPreferredItemPaddingStart"
|
||||
android:layout_marginStart="?android:attr/listPreferredItemPaddingStart"
|
||||
android:layout_gravity="center_vertical">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
app:srcCompat="@drawable/circle"
|
||||
android:src="@drawable/circle"
|
||||
app:tint="@color/swap_light_grey_icon"/>
|
||||
|
||||
<ImageView
|
||||
@ -38,7 +38,7 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_marginLeft="?attr/listPreferredItemPaddingLeft"
|
||||
android:layout_marginStart="?attr/listPreferredItemPaddingStart"
|
||||
android:layout_marginStart="?android:attr/listPreferredItemPaddingStart"
|
||||
android:textSize="20sp"
|
||||
android:textAppearance="?android:attr/textAppearanceMedium"
|
||||
tools:text="Nexus 4"/>
|
||||
|
@ -26,7 +26,7 @@
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="24dp"
|
||||
android:contentDescription="@string/use_bluetooth"
|
||||
swap:srcCompat="@drawable/ic_bluetooth_searching"/>
|
||||
android:src="@drawable/ic_bluetooth_searching"/>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="0dp"
|
||||
@ -53,7 +53,7 @@
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<com.google.android.material.switchmaterial.SwitchMaterial
|
||||
<androidx.appcompat.widget.SwitchCompat
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:enabled="false"
|
||||
@ -74,7 +74,7 @@
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="24dp"
|
||||
android:contentDescription="@string/wifi"
|
||||
swap:srcCompat="@drawable/ic_wifi"/>
|
||||
android:src="@drawable/ic_wifi"/>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="0dp"
|
||||
@ -110,7 +110,7 @@
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<com.google.android.material.switchmaterial.SwitchMaterial
|
||||
<androidx.appcompat.widget.SwitchCompat
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:id="@+id/switch_wifi"/>
|
||||
@ -155,7 +155,7 @@
|
||||
|
||||
<Button
|
||||
android:id="@+id/btn_send_fdroid"
|
||||
style="@style/Widget.App.Button.TextButton"
|
||||
style="@style/Widget.MaterialComponents.Button.TextButton"
|
||||
android:layout_width="wrap_content"
|
||||
swap:icon="@drawable/ic_fdroid_grey"
|
||||
android:layout_height="wrap_content"
|
||||
@ -163,7 +163,7 @@
|
||||
|
||||
<Button
|
||||
android:id="@+id/btn_scan_qr"
|
||||
style="@style/Widget.App.Button.TextButton"
|
||||
style="@style/Widget.MaterialComponents.Button.TextButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/swap_scan_qr"
|
||||
|
@ -1,42 +1,22 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<menu 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"
|
||||
tools:ignore="MenuTitle">
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
tools:ignore="MenuTitle">
|
||||
<!-- android:title and android:icon are set dynamically in MainActivity -->
|
||||
<item
|
||||
android:id="@+id/latest"
|
||||
android:enabled="true"
|
||||
android:icon="@drawable/ic_latest"
|
||||
android:orderInCategory="0"
|
||||
android:title="@string/main_menu__latest_apps"
|
||||
app:showAsAction="ifRoom|withText" />
|
||||
app:showAsAction="ifRoom|withText"
|
||||
android:id="@+id/latest"/>
|
||||
<item
|
||||
android:id="@+id/categories"
|
||||
android:enabled="true"
|
||||
android:icon="@drawable/ic_categories"
|
||||
android:orderInCategory="1"
|
||||
android:title="@string/main_menu__categories"
|
||||
app:showAsAction="ifRoom|withText" />
|
||||
app:showAsAction="ifRoom|withText"
|
||||
android:id="@+id/categories"/>
|
||||
<item
|
||||
android:id="@+id/nearby"
|
||||
android:enabled="true"
|
||||
android:icon="@drawable/ic_nearby"
|
||||
android:orderInCategory="2"
|
||||
android:title="@string/main_menu__swap_nearby"
|
||||
app:showAsAction="ifRoom|withText" />
|
||||
app:showAsAction="ifRoom|withText"
|
||||
android:id="@+id/nearby"/>
|
||||
<item
|
||||
android:id="@+id/updates"
|
||||
android:enabled="true"
|
||||
android:icon="@drawable/ic_updates"
|
||||
android:orderInCategory="3"
|
||||
android:title="@string/main_menu__updates"
|
||||
app:showAsAction="ifRoom|withText" />
|
||||
app:showAsAction="ifRoom|withText"
|
||||
android:id="@+id/updates"/>
|
||||
<item
|
||||
android:id="@+id/settings"
|
||||
android:enabled="true"
|
||||
android:icon="@drawable/ic_settings"
|
||||
android:orderInCategory="4"
|
||||
android:title="@string/menu_settings"
|
||||
app:showAsAction="ifRoom|withText" />
|
||||
app:showAsAction="ifRoom|withText"
|
||||
android:id="@+id/settings"/>
|
||||
</menu>
|
@ -4,7 +4,7 @@
|
||||
<style name="SwapTheme.AppList.SwapSuccess" parent="SwapTheme.AppList.SwapSuccessBase">
|
||||
<item name="android:textAlignment">center</item>
|
||||
<item name="android:gravity">center</item>
|
||||
<item name="fontFamily">sans-serif-light</item>
|
||||
<item name="android:fontFamily">sans-serif-light</item>
|
||||
</style>
|
||||
|
||||
<style name="SwapTheme.AppList.SwapSuccessDetails" parent="SwapTheme.AppList.SwapSuccessDetailsBase">
|
||||
@ -23,7 +23,7 @@
|
||||
</style>
|
||||
|
||||
<style name="SwapTheme.Wizard.MainText" parent="SwapTheme.Wizard.MainTextBase">
|
||||
<item name="fontFamily">sans-serif-light</item>
|
||||
<item name="android:fontFamily">sans-serif-light</item>
|
||||
</style>
|
||||
|
||||
</resources>
|
||||
|
@ -2,7 +2,7 @@
|
||||
<resources>
|
||||
|
||||
<style name="SwapTheme.Wizard" parent="Theme.AppCompat.Light.NoActionBar">
|
||||
<item name="colorButtonNormal">#04b9e6</item>
|
||||
<item name="android:colorButtonNormal">#04b9e6</item>
|
||||
</style>
|
||||
|
||||
</resources>
|
||||
|
@ -3,9 +3,13 @@
|
||||
|
||||
<style name="SwapTheme.Wizard" parent="Theme.AppCompat.Light.NoActionBar">
|
||||
<item name="colorButtonNormal">@color/swap_bright_blue</item>
|
||||
<item name="actionButtonStyle">@style/SwapTheme.Wizard.ActionButton</item>
|
||||
<item name="actionBarStyle">@style/Widget.AppCompat.ActionBar.Solid</item>
|
||||
</style>
|
||||
|
||||
<style name="SwapTheme.StartSwap" parent="Theme.App"/>
|
||||
<style name="SwapTheme.StartSwap" parent="AppThemeLight">
|
||||
<item name="android:background">@android:color/white</item>
|
||||
</style>
|
||||
|
||||
<style name="SwapTheme.StartSwap.Text" parent="@style/SwapTheme.StartSwap">
|
||||
</style>
|
||||
@ -13,10 +17,10 @@
|
||||
<style name="SwapTheme.BluetoothDeviceList" parent="@style/SwapTheme.Wizard">
|
||||
</style>
|
||||
|
||||
<style name="SwapTheme.AppList" parent="Base.Theme.App">
|
||||
<style name="SwapTheme.AppList" parent="AppThemeLight">
|
||||
</style>
|
||||
|
||||
<style name="SwapTheme.AppList.ListItem" parent="Theme.App">
|
||||
<style name="SwapTheme.AppList.ListItem" parent="AppThemeLight">
|
||||
</style>
|
||||
|
||||
<style name="SwapTheme.AppList.SwapSuccessBase">
|
||||
|
@ -1,5 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<!--
|
||||
* Copyright (C) 2010-2012 Ciaran Gultnieks
|
||||
* Copyright (C) 2013-2017 Peter Serwylo
|
||||
@ -23,328 +22,397 @@
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
-->
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
package="org.fdroid.fdroid"
|
||||
android:installLocation="auto">
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
package="org.fdroid.fdroid"
|
||||
android:installLocation="auto">
|
||||
|
||||
<supports-screens
|
||||
android:anyDensity="true"
|
||||
android:largeScreens="true"
|
||||
android:normalScreens="true"
|
||||
android:resizeable="true"
|
||||
android:smallScreens="true"
|
||||
android:xlargeScreens="true" />
|
||||
android:anyDensity="true"
|
||||
android:largeScreens="true"
|
||||
android:normalScreens="true"
|
||||
android:resizeable="true"
|
||||
android:smallScreens="true"
|
||||
android:xlargeScreens="true"
|
||||
/>
|
||||
|
||||
<uses-feature
|
||||
android:name="android.hardware.telephony"
|
||||
android:required="false" />
|
||||
android:name="android.hardware.telephony"
|
||||
android:required="false"/>
|
||||
<uses-feature
|
||||
android:name="android.hardware.wifi"
|
||||
android:required="false" />
|
||||
|
||||
android:name="android.hardware.wifi"
|
||||
android:required="false"/>
|
||||
<uses-feature
|
||||
android:name="android.hardware.touchscreen"
|
||||
android:required="false" />
|
||||
android:name="android.hardware.touchscreen"
|
||||
android:required="false"/>
|
||||
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
|
||||
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||
<uses-permission android:name="android.permission.NFC" />
|
||||
<uses-permission android:name="android.permission.WAKE_LOCK" />
|
||||
<uses-permission android:name="android.permission.INTERNET"/>
|
||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
|
||||
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
|
||||
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
|
||||
<uses-permission android:name="android.permission.NFC"/>
|
||||
<uses-permission android:name="android.permission.WAKE_LOCK"/>
|
||||
|
||||
<application
|
||||
android:name=".FDroidApp"
|
||||
android:allowBackup="true"
|
||||
android:description="@string/app_description"
|
||||
android:fullBackupContent="@xml/backup_rules"
|
||||
android:icon="@drawable/ic_launcher"
|
||||
android:label="BobStore"
|
||||
android:networkSecurityConfig="@xml/network_security_config"
|
||||
android:supportsRtl="true"
|
||||
android:theme="@style/Theme.App">
|
||||
android:name=".FDroidApp"
|
||||
android:icon="@drawable/ic_launcher"
|
||||
android:label="@string/app_name"
|
||||
android:description="@string/app_description"
|
||||
android:allowBackup="true"
|
||||
android:fullBackupContent="@xml/backup_rules"
|
||||
android:networkSecurityConfig="@xml/network_security_config"
|
||||
android:theme="@style/AppThemeLight"
|
||||
android:supportsRtl="true">
|
||||
|
||||
<provider
|
||||
android:authorities="${applicationId}.data.AppProvider"
|
||||
android:name="org.fdroid.fdroid.data.AppProvider"
|
||||
android:exported="false"/>
|
||||
|
||||
<provider
|
||||
android:authorities="${applicationId}.data.RepoProvider"
|
||||
android:name="org.fdroid.fdroid.data.RepoProvider"
|
||||
android:exported="false"/>
|
||||
|
||||
<provider
|
||||
android:authorities="${applicationId}.data.ApkProvider"
|
||||
android:name="org.fdroid.fdroid.data.ApkProvider"
|
||||
android:exported="false"/>
|
||||
|
||||
<provider
|
||||
android:authorities="${applicationId}.data.TempApkProvider"
|
||||
android:name="org.fdroid.fdroid.data.TempApkProvider"
|
||||
android:exported="false"/>
|
||||
|
||||
<provider
|
||||
android:authorities="${applicationId}.data.TempAppProvider"
|
||||
android:name="org.fdroid.fdroid.data.TempAppProvider"
|
||||
android:exported="false"/>
|
||||
|
||||
<provider
|
||||
android:authorities="${applicationId}.data.InstalledAppProvider"
|
||||
android:name="org.fdroid.fdroid.data.InstalledAppProvider"
|
||||
android:exported="false"/>
|
||||
|
||||
<provider
|
||||
android:authorities="${applicationId}.data.AppPrefsProvider"
|
||||
android:name="org.fdroid.fdroid.data.AppPrefsProvider"
|
||||
android:exported="false"/>
|
||||
|
||||
<provider
|
||||
android:authorities="${applicationId}.data.PackageIdProvider"
|
||||
android:name="org.fdroid.fdroid.data.PackageIdProvider"
|
||||
android:exported="false"/>
|
||||
|
||||
<provider
|
||||
android:authorities="${applicationId}.data.CategoryProvider"
|
||||
android:name="org.fdroid.fdroid.data.CategoryProvider"
|
||||
android:exported="false"/>
|
||||
|
||||
<provider
|
||||
android:name="org.fdroid.fdroid.installer.ApkFileProvider"
|
||||
android:authorities="${applicationId}.installer.ApkFileProvider"
|
||||
android:exported="false"
|
||||
android:grantUriPermissions="true">
|
||||
<meta-data
|
||||
android:name="android.support.FILE_PROVIDER_PATHS"
|
||||
android:resource="@xml/apk_file_provider"/>
|
||||
</provider>
|
||||
<provider
|
||||
android:name="androidx.core.content.FileProvider"
|
||||
android:authorities="${applicationId}.installer"
|
||||
android:exported="false"
|
||||
android:grantUriPermissions="true">
|
||||
<meta-data
|
||||
android:name="android.support.FILE_PROVIDER_PATHS"
|
||||
android:resource="@xml/installer_file_provider"/>
|
||||
</provider>
|
||||
|
||||
<activity
|
||||
android:name=".privileged.views.InstallConfirmActivity"
|
||||
android:configChanges="layoutDirection|locale"
|
||||
android:excludeFromRecents="true"
|
||||
android:label="@string/menu_install"
|
||||
android:parentActivityName=".views.main.MainActivity">
|
||||
android:name=".privileged.views.InstallConfirmActivity"
|
||||
android:label="@string/menu_install"
|
||||
android:theme="@style/MinWithDialogBaseThemeLight"
|
||||
android:excludeFromRecents="true"
|
||||
android:parentActivityName=".views.main.MainActivity"
|
||||
android:configChanges="layoutDirection|locale">
|
||||
<meta-data
|
||||
android:name="android.support.PARENT_ACTIVITY"
|
||||
android:value=".views.main.MainActivity" />
|
||||
android:name="android.support.PARENT_ACTIVITY"
|
||||
android:value=".views.main.MainActivity"/>
|
||||
</activity>
|
||||
<activity
|
||||
android:name=".privileged.views.UninstallDialogActivity"
|
||||
android:excludeFromRecents="true"
|
||||
android:theme="@style/AppThemeTransparent"/>
|
||||
<activity
|
||||
android:name=".views.ManageReposActivity"
|
||||
android:label="@string/menu_manage"
|
||||
android:launchMode="singleTask"
|
||||
android:parentActivityName=".views.main.MainActivity"
|
||||
android:configChanges="layoutDirection|locale">
|
||||
<meta-data
|
||||
android:name="android.support.PARENT_ACTIVITY"
|
||||
android:value=".views.main.MainActivity"/>
|
||||
</activity>
|
||||
<activity
|
||||
android:name=".NfcNotEnabledActivity"
|
||||
android:noHistory="true"
|
||||
android:configChanges="layoutDirection|locale"/>
|
||||
<activity
|
||||
android:name=".views.RepoDetailsActivity"
|
||||
android:label="@string/repo_details"
|
||||
android:parentActivityName=".views.ManageReposActivity"
|
||||
android:windowSoftInputMode="stateHidden"
|
||||
android:configChanges="layoutDirection|locale">
|
||||
<meta-data
|
||||
android:name="android.support.PARENT_ACTIVITY"
|
||||
android:value=".views.ManageReposActivity"/>
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:name=".privileged.views.UninstallDialogActivity"
|
||||
android:excludeFromRecents="true" />
|
||||
|
||||
<activity
|
||||
android:name=".views.ManageReposActivity"
|
||||
android:configChanges="layoutDirection|locale"
|
||||
android:label="@string/menu_manage"
|
||||
android:launchMode="singleTask"
|
||||
android:parentActivityName=".views.main.MainActivity">
|
||||
android:name=".views.AppDetailsActivity"
|
||||
android:label="@string/app_details"
|
||||
android:exported="true"
|
||||
android:parentActivityName=".views.main.MainActivity"
|
||||
android:configChanges="layoutDirection|locale">
|
||||
<meta-data
|
||||
android:name="android.support.PARENT_ACTIVITY"
|
||||
android:value=".views.main.MainActivity" />
|
||||
android:name="android.support.PARENT_ACTIVITY"
|
||||
android:value=".views.main.MainActivity"/>
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:name=".NfcNotEnabledActivity"
|
||||
android:configChanges="layoutDirection|locale"
|
||||
android:noHistory="true" />
|
||||
|
||||
android:name=".acra.CrashReportActivity"
|
||||
android:theme="@style/AppThemeDark"
|
||||
android:process=":error_report"
|
||||
android:launchMode="singleInstance"
|
||||
android:excludeFromRecents="true"
|
||||
android:finishOnTaskLaunch="true"/>
|
||||
<activity android:name=".views.ScreenShotsActivity"/>
|
||||
<!-- Note: AppThemeTransparent, this activity shows dialogs only -->
|
||||
<activity android:name=".data.ObbUrlActivity"
|
||||
android:theme="@android:style/Theme.NoDisplay"/>
|
||||
<!-- Note: AppThemeTransparent, this activity shows dialogs only -->
|
||||
<activity
|
||||
android:name=".views.RepoDetailsActivity"
|
||||
android:configChanges="layoutDirection|locale"
|
||||
android:label="@string/repo_details"
|
||||
android:parentActivityName=".views.ManageReposActivity"
|
||||
android:windowSoftInputMode="stateHidden">
|
||||
<meta-data
|
||||
android:name="android.support.PARENT_ACTIVITY"
|
||||
android:value=".views.ManageReposActivity" />
|
||||
</activity>
|
||||
|
||||
android:name=".installer.DefaultInstallerActivity"
|
||||
android:theme="@style/AppThemeTransparent"/>
|
||||
<!-- Note: AppThemeTransparent, this activity shows dialogs only -->
|
||||
<activity
|
||||
android:name=".views.AppDetailsActivity"
|
||||
android:configChanges="layoutDirection|locale"
|
||||
android:exported="true"
|
||||
android:label="@string/app_details"
|
||||
android:parentActivityName=".views.main.MainActivity">
|
||||
<meta-data
|
||||
android:name="android.support.PARENT_ACTIVITY"
|
||||
android:value=".views.main.MainActivity" />
|
||||
</activity>
|
||||
android:name=".installer.ErrorDialogActivity"
|
||||
android:theme="@style/AppThemeTransparent"/>
|
||||
|
||||
<activity
|
||||
android:name=".acra.CrashReportActivity"
|
||||
android:excludeFromRecents="true"
|
||||
android:finishOnTaskLaunch="true"
|
||||
android:launchMode="singleInstance"
|
||||
android:process=":error_report" />
|
||||
|
||||
<activity android:name=".views.ScreenShotsActivity" />
|
||||
|
||||
<activity
|
||||
android:name=".data.ObbUrlActivity"
|
||||
android:theme="@android:style/Theme.NoDisplay" />
|
||||
|
||||
<activity
|
||||
android:name=".installer.DefaultInstallerActivity"
|
||||
android:theme="@style/AppThemeTransparent" />
|
||||
<activity
|
||||
android:name=".installer.ErrorDialogActivity"
|
||||
android:theme="@style/AppThemeTransparent" />
|
||||
|
||||
<activity
|
||||
android:name=".views.main.MainActivity"
|
||||
android:launchMode="singleTop"
|
||||
android:windowSoftInputMode="adjustResize">
|
||||
<receiver android:name=".receiver.StartupReceiver">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<action android:name="android.intent.action.BOOT_COMPLETED"/>
|
||||
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
<category android:name="android.intent.category.HOME"/>
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
|
||||
<receiver android:name=".receiver.PackageManagerReceiver">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.PACKAGE_ADDED"/>
|
||||
<action android:name="android.intent.action.PACKAGE_CHANGED"/>
|
||||
<action android:name="android.intent.action.PACKAGE_REMOVED"/>
|
||||
|
||||
<data android:scheme="package"/>
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
|
||||
<receiver android:name=".NotificationBroadcastReceiver" android:exported="false">
|
||||
<!-- Doesn't require an intent-filter because it is explicitly invoked via Intent.setClass() -->
|
||||
</receiver>
|
||||
|
||||
<receiver android:name=".receiver.DeviceStorageReceiver">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.DEVICE_STORAGE_LOW"/>
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
|
||||
<service
|
||||
android:name=".UpdateService"
|
||||
android:permission="android.permission.BIND_JOB_SERVICE"
|
||||
android:exported="false"/>
|
||||
<service
|
||||
android:name=".UpdateJobService"
|
||||
android:exported="false"
|
||||
android:permission="android.permission.BIND_JOB_SERVICE"/>
|
||||
<service
|
||||
android:name=".net.DownloaderService"
|
||||
android:exported="false"/>
|
||||
<service
|
||||
android:name=".installer.InstallerService"
|
||||
android:permission="android.permission.BIND_JOB_SERVICE"
|
||||
android:exported="false"/>
|
||||
<service
|
||||
android:name=".DeleteCacheService"
|
||||
android:permission="android.permission.BIND_JOB_SERVICE"
|
||||
android:exported="false"/>
|
||||
<service
|
||||
android:name=".net.ConnectivityMonitorService"
|
||||
android:permission="android.permission.BIND_JOB_SERVICE"
|
||||
android:exported="false"/>
|
||||
<service
|
||||
android:name=".installer.InstallManagerService"
|
||||
android:exported="false"/>
|
||||
<service
|
||||
android:name=".installer.InstallHistoryService"
|
||||
android:exported="false"/>
|
||||
<service
|
||||
android:name=".installer.ObfInstallerService"
|
||||
android:exported="false"/>
|
||||
<service
|
||||
android:name=".data.InstalledAppProviderService"
|
||||
android:permission="android.permission.BIND_JOB_SERVICE"
|
||||
android:exported="false"/>
|
||||
<service
|
||||
android:name=".AddRepoIntentService"
|
||||
android:exported="false"/>
|
||||
|
||||
<provider
|
||||
android:name="androidx.work.impl.WorkManagerInitializer"
|
||||
android:authorities="${applicationId}.workmanager-init"
|
||||
android:exported="false"
|
||||
tools:node="remove" />
|
||||
|
||||
<activity
|
||||
android:name=".views.main.MainActivity"
|
||||
android:launchMode="singleTop"
|
||||
android:windowSoftInputMode="adjustResize">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN"/>
|
||||
|
||||
<category android:name="android.intent.category.LAUNCHER"/>
|
||||
</intent-filter>
|
||||
|
||||
|
||||
<!-- App URLs -->
|
||||
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
<action android:name="android.intent.action.VIEW"/>
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
<category android:name="android.intent.category.DEFAULT"/>
|
||||
<category android:name="android.intent.category.BROWSABLE"/>
|
||||
|
||||
<data android:scheme="fdroid.app" />
|
||||
<data android:scheme="fdroid.app"/>
|
||||
</intent-filter>
|
||||
|
||||
<intent-filter android:autoVerify="false">
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
<action android:name="android.intent.action.VIEW"/>
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
<category android:name="android.intent.category.DEFAULT"/>
|
||||
<category android:name="android.intent.category.BROWSABLE"/>
|
||||
|
||||
<data android:scheme="https" />
|
||||
<data android:host="f-droid.org" />
|
||||
<data android:host="www.f-droid.org" />
|
||||
<data android:host="staging.f-droid.org" />
|
||||
<data android:pathPrefix="/app/" />
|
||||
<data android:pathPrefix="/packages/" />
|
||||
<data android:pathPrefix="/repository/browse" />
|
||||
<data android:scheme="https"/>
|
||||
<data android:host="f-droid.org"/>
|
||||
<data android:host="www.f-droid.org"/>
|
||||
<data android:host="staging.f-droid.org"/>
|
||||
<data android:pathPrefix="/app/"/>
|
||||
<data android:pathPrefix="/packages/"/>
|
||||
<data android:pathPrefix="/repository/browse"/>
|
||||
<!-- support localized URLs -->
|
||||
<data android:pathPattern="/.*/packages/.*" />
|
||||
<data android:pathPattern="/.*/packages/.*/" />
|
||||
<data android:pathPattern="/.*/packages/.*"/>
|
||||
<data android:pathPattern="/.*/packages/.*/"/>
|
||||
</intent-filter>
|
||||
|
||||
<intent-filter android:autoVerify="false">
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
<action android:name="android.intent.action.VIEW"/>
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
<category android:name="android.intent.category.DEFAULT"/>
|
||||
<category android:name="android.intent.category.BROWSABLE"/>
|
||||
|
||||
<data android:scheme="http" />
|
||||
<data android:host="f-droid.org" />
|
||||
<data android:host="www.f-droid.org" />
|
||||
<data android:host="staging.f-droid.org" />
|
||||
<data android:pathPrefix="/app/" />
|
||||
<data android:pathPrefix="/packages/" />
|
||||
<data android:pathPrefix="/repository/browse" />
|
||||
<data android:scheme="http"/>
|
||||
<data android:host="f-droid.org"/>
|
||||
<data android:host="www.f-droid.org"/>
|
||||
<data android:host="staging.f-droid.org"/>
|
||||
<data android:pathPrefix="/app/"/>
|
||||
<data android:pathPrefix="/packages/"/>
|
||||
<data android:pathPrefix="/repository/browse"/>
|
||||
<!-- support localized URLs -->
|
||||
<data android:pathPattern="/.*/packages/.*" />
|
||||
<data android:pathPattern="/.*/packages/.*/" />
|
||||
<data android:pathPattern="/.*/packages/.*"/>
|
||||
<data android:pathPattern="/.*/packages/.*/"/>
|
||||
</intent-filter>
|
||||
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
<action android:name="android.intent.action.VIEW"/>
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
<category android:name="android.intent.category.DEFAULT"/>
|
||||
<category android:name="android.intent.category.BROWSABLE"/>
|
||||
|
||||
<data
|
||||
android:host="details"
|
||||
android:scheme="market" />
|
||||
<data android:scheme="market" android:host="details"/>
|
||||
</intent-filter>
|
||||
|
||||
<intent-filter android:autoVerify="false">
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
<action android:name="android.intent.action.VIEW"/>
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
<category android:name="android.intent.category.DEFAULT"/>
|
||||
<category android:name="android.intent.category.BROWSABLE"/>
|
||||
|
||||
<data android:scheme="http" />
|
||||
<data android:scheme="https" />
|
||||
<data android:host="play.google.com" /> <!-- they don't do www. -->
|
||||
<data android:path="/store/apps/details" />
|
||||
<data android:scheme="http"/>
|
||||
<data android:scheme="https"/>
|
||||
<data android:host="play.google.com"/> <!-- they don't do www. -->
|
||||
<data android:path="/store/apps/details"/>
|
||||
</intent-filter>
|
||||
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
<action android:name="android.intent.action.VIEW"/>
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
<category android:name="android.intent.category.DEFAULT"/>
|
||||
<category android:name="android.intent.category.BROWSABLE"/>
|
||||
|
||||
<data
|
||||
android:host="apps"
|
||||
android:path="/android"
|
||||
android:scheme="amzn" />
|
||||
<data android:scheme="amzn" android:host="apps" android:path="/android"/>
|
||||
</intent-filter>
|
||||
|
||||
<intent-filter android:autoVerify="false">
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
<action android:name="android.intent.action.VIEW"/>
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
<category android:name="android.intent.category.DEFAULT"/>
|
||||
<category android:name="android.intent.category.BROWSABLE"/>
|
||||
|
||||
<data android:scheme="http" />
|
||||
<data android:scheme="https" />
|
||||
<data android:host="amazon.com" />
|
||||
<data android:host="www.amazon.com" />
|
||||
<data android:path="/gp/mas/dl/android" />
|
||||
<data android:scheme="http"/>
|
||||
<data android:scheme="https"/>
|
||||
<data android:host="amazon.com"/>
|
||||
<data android:host="www.amazon.com"/>
|
||||
<data android:path="/gp/mas/dl/android"/>
|
||||
</intent-filter>
|
||||
|
||||
|
||||
<!-- Search URLs -->
|
||||
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
<action android:name="android.intent.action.VIEW"/>
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
<category android:name="android.intent.category.DEFAULT"/>
|
||||
<category android:name="android.intent.category.BROWSABLE"/>
|
||||
|
||||
<data android:scheme="fdroid.search" />
|
||||
<data android:scheme="fdroid.search"/>
|
||||
</intent-filter>
|
||||
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
<action android:name="android.intent.action.VIEW"/>
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
<category android:name="android.intent.category.DEFAULT"/>
|
||||
<category android:name="android.intent.category.BROWSABLE"/>
|
||||
|
||||
<data
|
||||
android:host="search"
|
||||
android:scheme="market" />
|
||||
<data android:scheme="market" android:host="search"/>
|
||||
</intent-filter>
|
||||
|
||||
<intent-filter android:autoVerify="false">
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
<action android:name="android.intent.action.VIEW"/>
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
<category android:name="android.intent.category.DEFAULT"/>
|
||||
<category android:name="android.intent.category.BROWSABLE"/>
|
||||
|
||||
<data android:scheme="http" />
|
||||
<data android:scheme="https" />
|
||||
<data android:host="play.google.com" /> <!-- they don't do www. -->
|
||||
<data android:path="/store/search" />
|
||||
<data android:scheme="http"/>
|
||||
<data android:scheme="https"/>
|
||||
<data android:host="play.google.com"/> <!-- they don't do www. -->
|
||||
<data android:path="/store/search"/>
|
||||
</intent-filter>
|
||||
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.SEARCH" />
|
||||
<action android:name="android.intent.action.SEARCH"/>
|
||||
</intent-filter>
|
||||
|
||||
<intent-filter android:autoVerify="false">
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
|
||||
<!--
|
||||
Android's scheme matcher is case-sensitive, so include
|
||||
ALL CAPS versions to support ALL CAPS URLs in QR Codes.
|
||||
QR Codes have a special ALL CAPS mode that uses a reduced
|
||||
character set, making for more compact QR Codes.
|
||||
-->
|
||||
<data android:scheme="http" />
|
||||
<data
|
||||
android:scheme="HTTP"
|
||||
tools:ignore="AppLinkUrlError" />
|
||||
<data android:scheme="https" />
|
||||
<data
|
||||
android:scheme="HTTPS"
|
||||
tools:ignore="AppLinkUrlError" />
|
||||
|
||||
<data android:host="*" />
|
||||
|
||||
<!--
|
||||
The pattern matcher here is poorly implemented, in particular the * is
|
||||
non-greedy, so you have to do stupid tricks to match patterns that have
|
||||
repeat characters in them. http://stackoverflow.com/a/8599921/306864
|
||||
-->
|
||||
<data android:path="/fdroid/repo" />
|
||||
<data android:pathPattern="/fdroid/repo/*" />
|
||||
<data android:pathPattern="/.*/fdroid/repo" />
|
||||
<data android:pathPattern="/.*/fdroid/repo/*" />
|
||||
<data android:pathPattern="/.*/.*/fdroid/repo" />
|
||||
<data android:pathPattern="/.*/.*/fdroid/repo/*" />
|
||||
<data android:pathPattern="/.*/.*/.*/fdroid/repo" />
|
||||
<data android:pathPattern="/.*/.*/.*/fdroid/repo/*" />
|
||||
<data android:pathPattern="/.*/.*/.*/.*/fdroid/repo" />
|
||||
<data android:pathPattern="/.*/.*/.*/.*/fdroid/repo/*" />
|
||||
<data android:pathPattern="/.*/.*/.*/.*/.*/fdroid/repo" />
|
||||
<data android:pathPattern="/.*/.*/.*/.*/.*/fdroid/repo/*" />
|
||||
<data android:pathPattern="/.*/.*/.*/.*/.*/.*/fdroid/repo" />
|
||||
<data android:pathPattern="/.*/.*/.*/.*/.*/.*/fdroid/repo/*" />
|
||||
<data android:path="/fdroid/archive" />
|
||||
<data android:pathPattern="/fdroid/archive/*" />
|
||||
<data android:pathPattern="/.*/fdroid/archive" />
|
||||
<data android:pathPattern="/.*/fdroid/archive/*" />
|
||||
<data android:pathPattern="/.*/.*/fdroid/archive" />
|
||||
<data android:pathPattern="/.*/.*/fdroid/archive/*" />
|
||||
<data android:pathPattern="/.*/.*/.*/fdroid/archive" />
|
||||
<data android:pathPattern="/.*/.*/.*/fdroid/archive/*" />
|
||||
<data android:pathPattern="/.*/.*/.*/.*/fdroid/archive" />
|
||||
<data android:pathPattern="/.*/.*/.*/.*/fdroid/archive/*" />
|
||||
<!--
|
||||
Some QR Code scanners don't respect custom schemes like fdroidrepo://,
|
||||
so this is a workaround, since the local repo URL is all uppercase in
|
||||
the QR Code for sending the local repo to another device.
|
||||
-->
|
||||
<data android:path="/FDROID/REPO" />
|
||||
<data android:pathPattern="/.*/FDROID/REPO" />
|
||||
<data android:pathPattern="/.*/.*/FDROID/REPO" />
|
||||
<data android:pathPattern="/.*/.*/.*/FDROID/REPO" />
|
||||
</intent-filter>
|
||||
<meta-data
|
||||
android:name="android.app.searchable"
|
||||
android:resource="@xml/searchable"/>
|
||||
|
||||
|
||||
<!-- Repo URLs -->
|
||||
@ -364,11 +432,11 @@
|
||||
This filter supports HTTP and HTTPS schemes. There is an additional filter for
|
||||
fdroidrepo:// and fdroidrepos://
|
||||
-->
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
<intent-filter android:autoVerify="false">
|
||||
<action android:name="android.intent.action.VIEW"/>
|
||||
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE"/>
|
||||
<category android:name="android.intent.category.DEFAULT"/>
|
||||
|
||||
<!--
|
||||
Android's scheme matcher is case-sensitive, so include
|
||||
@ -376,14 +444,51 @@
|
||||
QR Codes have a special ALL CAPS mode that uses a reduced
|
||||
character set, making for more compact QR Codes.
|
||||
-->
|
||||
<data android:scheme="fdroidrepo" />
|
||||
<data
|
||||
android:scheme="FDROIDREPO"
|
||||
tools:ignore="AppLinkUrlError" />
|
||||
<data android:scheme="fdroidrepos" />
|
||||
<data
|
||||
android:scheme="FDROIDREPOS"
|
||||
tools:ignore="AppLinkUrlError" />
|
||||
<data android:scheme="http"/>
|
||||
<data android:scheme="HTTP" tools:ignore="AppLinkUrlError"/>
|
||||
<data android:scheme="https"/>
|
||||
<data android:scheme="HTTPS" tools:ignore="AppLinkUrlError"/>
|
||||
|
||||
<data android:host="*"/>
|
||||
|
||||
<!--
|
||||
The pattern matcher here is poorly implemented, in particular the * is
|
||||
non-greedy, so you have to do stupid tricks to match patterns that have
|
||||
repeat characters in them. http://stackoverflow.com/a/8599921/306864
|
||||
-->
|
||||
<data android:path="/fdroid/repo"/>
|
||||
<data android:pathPattern="/fdroid/repo/*"/>
|
||||
<data android:pathPattern="/.*/fdroid/repo"/>
|
||||
<data android:pathPattern="/.*/fdroid/repo/*"/>
|
||||
<data android:pathPattern="/.*/.*/fdroid/repo"/>
|
||||
<data android:pathPattern="/.*/.*/fdroid/repo/*"/>
|
||||
<data android:pathPattern="/.*/.*/.*/fdroid/repo"/>
|
||||
<data android:pathPattern="/.*/.*/.*/fdroid/repo/*"/>
|
||||
<data android:pathPattern="/.*/.*/.*/.*/fdroid/repo"/>
|
||||
<data android:pathPattern="/.*/.*/.*/.*/fdroid/repo/*"/>
|
||||
<data android:pathPattern="/.*/.*/.*/.*/.*/fdroid/repo"/>
|
||||
<data android:pathPattern="/.*/.*/.*/.*/.*/fdroid/repo/*"/>
|
||||
<data android:pathPattern="/.*/.*/.*/.*/.*/.*/fdroid/repo"/>
|
||||
<data android:pathPattern="/.*/.*/.*/.*/.*/.*/fdroid/repo/*"/>
|
||||
<data android:path="/fdroid/archive"/>
|
||||
<data android:pathPattern="/fdroid/archive/*"/>
|
||||
<data android:pathPattern="/.*/fdroid/archive"/>
|
||||
<data android:pathPattern="/.*/fdroid/archive/*"/>
|
||||
<data android:pathPattern="/.*/.*/fdroid/archive"/>
|
||||
<data android:pathPattern="/.*/.*/fdroid/archive/*"/>
|
||||
<data android:pathPattern="/.*/.*/.*/fdroid/archive"/>
|
||||
<data android:pathPattern="/.*/.*/.*/fdroid/archive/*"/>
|
||||
<data android:pathPattern="/.*/.*/.*/.*/fdroid/archive"/>
|
||||
<data android:pathPattern="/.*/.*/.*/.*/fdroid/archive/*"/>
|
||||
<!--
|
||||
Some QR Code scanners don't respect custom schemes like fdroidrepo://,
|
||||
so this is a workaround, since the local repo URL is all uppercase in
|
||||
the QR Code for sending the local repo to another device.
|
||||
-->
|
||||
<data android:path="/FDROID/REPO"/>
|
||||
<data android:pathPattern="/.*/FDROID/REPO"/>
|
||||
<data android:pathPattern="/.*/.*/FDROID/REPO"/>
|
||||
<data android:pathPattern="/.*/.*/.*/FDROID/REPO"/>
|
||||
</intent-filter>
|
||||
|
||||
<!--
|
||||
@ -391,186 +496,58 @@
|
||||
looks for fdroidrepos://* and doesn't care what the path is.
|
||||
-->
|
||||
<intent-filter>
|
||||
<action android:name="android.nfc.action.NDEF_DISCOVERED" />
|
||||
<action android:name="android.intent.action.VIEW"/>
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE"/>
|
||||
<category android:name="android.intent.category.DEFAULT"/>
|
||||
|
||||
<!--
|
||||
URIs that come in via NFC have scheme/host normalized to all lower case
|
||||
https://developer.android.com/reference/android/nfc/NfcAdapter.html#ACTION_NDEF_DISCOVERED
|
||||
Android's scheme matcher is case-sensitive, so include
|
||||
ALL CAPS versions to support ALL CAPS URLs in QR Codes.
|
||||
QR Codes have a special ALL CAPS mode that uses a reduced
|
||||
character set, making for more compact QR Codes.
|
||||
-->
|
||||
<data android:scheme="fdroidrepo" />
|
||||
<data android:scheme="fdroidrepos" />
|
||||
<data android:scheme="fdroidrepo"/>
|
||||
<data android:scheme="FDROIDREPO" tools:ignore="AppLinkUrlError"/>
|
||||
<data android:scheme="fdroidrepos"/>
|
||||
<data android:scheme="FDROIDREPOS" tools:ignore="AppLinkUrlError"/>
|
||||
</intent-filter>
|
||||
|
||||
|
||||
<!-- Handle NFC tags detected from outside our application -->
|
||||
|
||||
<meta-data
|
||||
android:name="android.app.searchable"
|
||||
android:resource="@xml/searchable" />
|
||||
<intent-filter>
|
||||
<action android:name="android.nfc.action.NDEF_DISCOVERED"/>
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT"/>
|
||||
|
||||
<!--
|
||||
URIs that come in via NFC have scheme/host normalized to all lower case
|
||||
https://developer.android.com/reference/android/nfc/NfcAdapter.html#ACTION_NDEF_DISCOVERED
|
||||
-->
|
||||
<data android:scheme="fdroidrepo"/>
|
||||
<data android:scheme="fdroidrepos"/>
|
||||
</intent-filter>
|
||||
|
||||
</activity>
|
||||
<activity android:name=".views.apps.AppListActivity" />
|
||||
<activity
|
||||
android:name=".views.installed.InstalledAppsActivity"
|
||||
android:parentActivityName=".views.main.MainActivity">
|
||||
|
||||
<activity android:name=".views.apps.AppListActivity"/>
|
||||
|
||||
<activity android:name=".views.installed.InstalledAppsActivity"
|
||||
android:parentActivityName=".views.main.MainActivity">
|
||||
<meta-data
|
||||
android:name="android.support.PARENT_ACTIVITY"
|
||||
android:value=".views.main.MainActivity" />
|
||||
android:name="android.support.PARENT_ACTIVITY"
|
||||
android:value=".views.main.MainActivity"/>
|
||||
</activity>
|
||||
<activity
|
||||
android:name=".views.InstallHistoryActivity"
|
||||
android:parentActivityName=".views.main.MainActivity">
|
||||
<activity android:name=".views.InstallHistoryActivity"
|
||||
android:parentActivityName=".views.main.MainActivity">
|
||||
<meta-data
|
||||
android:name="android.support.PARENT_ACTIVITY"
|
||||
android:value=".views.main.MainActivity" />
|
||||
android:name="android.support.PARENT_ACTIVITY"
|
||||
android:value=".views.main.MainActivity"/>
|
||||
</activity>
|
||||
<activity android:name=".AboutActivity" />
|
||||
|
||||
<activity
|
||||
android:name=".installer.FileInstallerActivity"
|
||||
android:theme="@style/AppThemeTransparent" />
|
||||
|
||||
<provider
|
||||
android:name="org.fdroid.fdroid.data.AppProvider"
|
||||
android:authorities="${applicationId}.data.AppProvider"
|
||||
android:exported="false" />
|
||||
<provider
|
||||
android:name="org.fdroid.fdroid.data.RepoProvider"
|
||||
android:authorities="${applicationId}.data.RepoProvider"
|
||||
android:exported="false" />
|
||||
<!-- Note: AppThemeTransparent, this activity shows dialogs only -->
|
||||
<provider
|
||||
android:name="org.fdroid.fdroid.data.ApkProvider"
|
||||
android:authorities="${applicationId}.data.ApkProvider"
|
||||
android:exported="false" />
|
||||
<!-- Note: AppThemeTransparent, this activity shows dialogs only -->
|
||||
<provider
|
||||
android:name="org.fdroid.fdroid.data.TempApkProvider"
|
||||
android:authorities="${applicationId}.data.TempApkProvider"
|
||||
android:exported="false" />
|
||||
<!-- Note: AppThemeTransparent, this activity shows dialogs only -->
|
||||
<provider
|
||||
android:name="org.fdroid.fdroid.data.TempAppProvider"
|
||||
android:authorities="${applicationId}.data.TempAppProvider"
|
||||
android:exported="false" />
|
||||
|
||||
<provider
|
||||
android:name="org.fdroid.fdroid.data.InstalledAppProvider"
|
||||
android:authorities="${applicationId}.data.InstalledAppProvider"
|
||||
android:exported="false" />
|
||||
|
||||
<provider
|
||||
android:name="org.fdroid.fdroid.data.AppPrefsProvider"
|
||||
android:authorities="${applicationId}.data.AppPrefsProvider"
|
||||
android:exported="false" />
|
||||
|
||||
<provider
|
||||
android:name="org.fdroid.fdroid.data.PackageIdProvider"
|
||||
android:authorities="${applicationId}.data.PackageIdProvider"
|
||||
android:exported="false" />
|
||||
|
||||
<provider
|
||||
android:name="org.fdroid.fdroid.data.CategoryProvider"
|
||||
android:authorities="${applicationId}.data.CategoryProvider"
|
||||
android:exported="false" />
|
||||
|
||||
<provider
|
||||
android:name="org.fdroid.fdroid.installer.ApkFileProvider"
|
||||
android:authorities="${applicationId}.installer.ApkFileProvider"
|
||||
android:exported="false"
|
||||
android:grantUriPermissions="true">
|
||||
<meta-data
|
||||
android:name="android.support.FILE_PROVIDER_PATHS"
|
||||
android:resource="@xml/apk_file_provider" />
|
||||
</provider>
|
||||
<provider
|
||||
android:name="androidx.core.content.FileProvider"
|
||||
android:authorities="${applicationId}.installer"
|
||||
android:exported="false"
|
||||
android:grantUriPermissions="true">
|
||||
<meta-data
|
||||
android:name="android.support.FILE_PROVIDER_PATHS"
|
||||
android:resource="@xml/installer_file_provider" />
|
||||
</provider>
|
||||
<provider
|
||||
android:name="androidx.work.impl.WorkManagerInitializer"
|
||||
android:authorities="${applicationId}.workmanager-init"
|
||||
android:exported="false"
|
||||
tools:node="remove" />
|
||||
|
||||
<receiver android:name=".receiver.StartupReceiver">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.BOOT_COMPLETED" />
|
||||
|
||||
<category android:name="android.intent.category.HOME" />
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
<receiver android:name=".receiver.PackageManagerReceiver">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.PACKAGE_ADDED" />
|
||||
<action android:name="android.intent.action.PACKAGE_CHANGED" />
|
||||
<action android:name="android.intent.action.PACKAGE_REMOVED" />
|
||||
|
||||
<data android:scheme="package" />
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
<receiver
|
||||
android:name=".NotificationBroadcastReceiver"
|
||||
android:exported="false">
|
||||
<!-- Doesn't require an intent-filter because it is explicitly invoked via Intent.setClass() -->
|
||||
</receiver>
|
||||
<receiver android:name=".receiver.DeviceStorageReceiver">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.DEVICE_STORAGE_LOW" />
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
|
||||
<service
|
||||
android:name=".UpdateService"
|
||||
android:exported="false"
|
||||
android:permission="android.permission.BIND_JOB_SERVICE" />
|
||||
<service
|
||||
android:name=".UpdateJobService"
|
||||
android:exported="false"
|
||||
android:permission="android.permission.BIND_JOB_SERVICE" />
|
||||
<service
|
||||
android:name=".net.DownloaderService"
|
||||
android:exported="false" />
|
||||
<service
|
||||
android:name=".installer.InstallerService"
|
||||
android:exported="false"
|
||||
android:permission="android.permission.BIND_JOB_SERVICE" />
|
||||
|
||||
<service
|
||||
android:name=".DeleteCacheService"
|
||||
android:exported="false"
|
||||
android:permission="android.permission.BIND_JOB_SERVICE" />
|
||||
|
||||
<service
|
||||
android:name=".net.ConnectivityMonitorService"
|
||||
android:exported="false"
|
||||
android:permission="android.permission.BIND_JOB_SERVICE" />
|
||||
|
||||
<service
|
||||
android:name=".installer.InstallManagerService"
|
||||
android:exported="false" />
|
||||
|
||||
<service
|
||||
android:name=".installer.InstallHistoryService"
|
||||
android:exported="false" />
|
||||
<service
|
||||
android:name=".installer.ObfInstallerService"
|
||||
android:exported="false" />
|
||||
|
||||
<service
|
||||
android:name=".data.InstalledAppProviderService"
|
||||
android:exported="false"
|
||||
android:permission="android.permission.BIND_JOB_SERVICE" />
|
||||
<service
|
||||
android:name=".AddRepoIntentService"
|
||||
android:exported="false" />
|
||||
<activity android:name=".AboutActivity" android:theme="@style/Theme.AppCompat.Light.Dialog"/>
|
||||
<activity android:name=".installer.FileInstallerActivity" android:theme="@style/AppThemeTransparent"/>
|
||||
|
||||
</application>
|
||||
|
||||
|
@ -16,6 +16,7 @@
|
||||
|
||||
package com.google.zxing.integration.android;
|
||||
|
||||
import android.app.AlertDialog;
|
||||
import android.content.ActivityNotFoundException;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
@ -25,7 +26,6 @@ import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.fragment.app.Fragment;
|
||||
|
||||
@ -336,7 +336,7 @@ public class IntentIntegrator {
|
||||
* @param intent Intent to start.
|
||||
* @param code Request code for the activity
|
||||
* @see android.app.AppCompatActivity#startActivityForResult(Intent, int)
|
||||
* @see Fragment#startActivityForResult(Intent, int)
|
||||
* @see android.app.Fragment#startActivityForResult(Intent, int)
|
||||
*/
|
||||
protected void startActivityForResult(Intent intent, int code) {
|
||||
if (fragment == null) {
|
||||
|
32
app/src/main/java/org/fdroid/fdroid/AboutActivity.java
Normal file
@ -0,0 +1,32 @@
|
||||
package org.fdroid.fdroid;
|
||||
|
||||
import android.os.Bundle;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import android.view.View;
|
||||
import android.widget.TextView;
|
||||
|
||||
public class AboutActivity extends AppCompatActivity {
|
||||
|
||||
@Override
|
||||
protected void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
FDroidApp fdroidApp = (FDroidApp) getApplication();
|
||||
fdroidApp.applyDialogTheme(this);
|
||||
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
setContentView(R.layout.about);
|
||||
|
||||
String versionName = Utils.getVersionName(this);
|
||||
if (versionName != null) {
|
||||
((TextView) findViewById(R.id.version)).setText(versionName);
|
||||
}
|
||||
|
||||
findViewById(R.id.ok_button).setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
finish();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
@ -5,9 +5,10 @@ import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
|
||||
import org.fdroid.fdroid.data.Repo;
|
||||
import org.fdroid.fdroid.data.RepoProvider;
|
||||
import org.fdroid.fdroid.views.ManageReposActivity;
|
||||
@ -17,9 +18,6 @@ import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.Locale;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* Handles requests to add new repos via URLs. This is an {@code IntentService}
|
||||
* so that requests are queued, which is necessary when either
|
||||
|
@ -9,7 +9,10 @@ import android.content.SharedPreferences;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.core.app.TaskStackBuilder;
|
||||
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
|
||||
import org.fdroid.fdroid.data.Apk;
|
||||
import org.fdroid.fdroid.data.App;
|
||||
import org.fdroid.fdroid.data.AppProvider;
|
||||
@ -25,11 +28,6 @@ import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.core.app.TaskStackBuilder;
|
||||
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
|
||||
|
||||
/**
|
||||
* Manages the state of APKs that are being installed or that have updates available.
|
||||
* This also ensures the state is saved across F-Droid restarts, and repopulates
|
||||
|
@ -4,7 +4,7 @@ import android.content.Context;
|
||||
import android.content.pm.FeatureInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.os.Build;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import org.fdroid.fdroid.compat.SupportedArchitectures;
|
||||
import org.fdroid.fdroid.data.Apk;
|
||||
|
||||
@ -14,8 +14,6 @@ import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
// Call getIncompatibleReasons(apk) on an instance of this class to
|
||||
// find reasons why an apk may be incompatible with the user's device.
|
||||
public class CompatibilityChecker {
|
||||
|
@ -3,15 +3,13 @@ package org.fdroid.fdroid;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Process;
|
||||
import android.util.Log;
|
||||
|
||||
import org.apache.commons.io.FileUtils;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.core.app.JobIntentService;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import android.util.Log;
|
||||
import org.apache.commons.io.FileUtils;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
/**
|
||||
* An {@link JobIntentService} subclass for deleting the full cache for this app.
|
||||
|
@ -24,6 +24,7 @@
|
||||
package org.fdroid.fdroid;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import android.app.ActivityManager;
|
||||
import android.app.ActivityManager.RunningAppProcessInfo;
|
||||
import android.app.Application;
|
||||
@ -45,7 +46,10 @@ import android.util.Log;
|
||||
import android.view.Display;
|
||||
import android.view.WindowManager;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.collection.LongSparseArray;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import com.nostra13.universalimageloader.cache.disc.DiskCache;
|
||||
import com.nostra13.universalimageloader.cache.disc.impl.UnlimitedDiskCache;
|
||||
import com.nostra13.universalimageloader.cache.disc.impl.ext.LruDiskCache;
|
||||
@ -53,7 +57,8 @@ import com.nostra13.universalimageloader.core.DefaultConfigurationFactory;
|
||||
import com.nostra13.universalimageloader.core.ImageLoader;
|
||||
import com.nostra13.universalimageloader.core.ImageLoaderConfiguration;
|
||||
import com.nostra13.universalimageloader.core.process.BitmapProcessor;
|
||||
|
||||
import info.guardianproject.netcipher.NetCipher;
|
||||
import info.guardianproject.netcipher.proxy.OrbotHelper;
|
||||
import org.acra.ACRA;
|
||||
import org.acra.ReportField;
|
||||
import org.acra.ReportingInteractionMode;
|
||||
@ -77,23 +82,13 @@ import org.fdroid.fdroid.net.ImageLoaderForUIL;
|
||||
import org.fdroid.fdroid.panic.HidingManager;
|
||||
import org.fdroid.fdroid.work.CleanCacheWorker;
|
||||
|
||||
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;
|
||||
|
||||
import javax.microedition.khronos.opengles.GL10;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.appcompat.app.AppCompatDelegate;
|
||||
import androidx.collection.LongSparseArray;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import info.guardianproject.netcipher.NetCipher;
|
||||
import info.guardianproject.netcipher.proxy.OrbotHelper;
|
||||
|
||||
@ReportsCrashes(mailTo = BuildConfig.ACRA_REPORT_EMAIL,
|
||||
mode = ReportingInteractionMode.DIALOG,
|
||||
reportDialogClass = org.fdroid.fdroid.acra.CrashReportActivity.class,
|
||||
@ -157,47 +152,30 @@ public class FDroidApp extends Application implements androidx.work.Configuratio
|
||||
|
||||
private static Theme curTheme = Theme.light;
|
||||
|
||||
/**
|
||||
* Apply pure black background in dark theme setting. Must be called in every activity's
|
||||
* {@link AppCompatActivity#onCreate()}, before super.onCreate().
|
||||
*
|
||||
* @param activity The activity to apply the setting.
|
||||
*/
|
||||
public void applyPureBlackBackgroundInDarkTheme(AppCompatActivity activity) {
|
||||
final boolean isPureBlack = Preferences.get().isPureBlack();
|
||||
if (isPureBlack) {
|
||||
activity.setTheme(R.style.Theme_App_Black);
|
||||
}
|
||||
}
|
||||
|
||||
public void applyTheme() {
|
||||
public void reloadTheme() {
|
||||
curTheme = Preferences.get().getTheme();
|
||||
switch (curTheme) {
|
||||
case dark:
|
||||
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES);
|
||||
break;
|
||||
case light:
|
||||
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO);
|
||||
break;
|
||||
default:
|
||||
// `Set by Battery Saver` for Q above (inclusive), `Use system default` for Q below
|
||||
// https://medium.com/androiddevelopers/appcompat-v23-2-daynight-d10f90c83e94
|
||||
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.P) {
|
||||
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_AUTO_BATTERY);
|
||||
} else {
|
||||
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: ResId no longer exists.
|
||||
public void applyTheme(AppCompatActivity activity) {
|
||||
activity.setTheme(getCurThemeResId());
|
||||
setSecureWindow(activity);
|
||||
}
|
||||
|
||||
public static int getCurThemeResId() {
|
||||
return R.style.Theme_App;
|
||||
switch (curTheme) {
|
||||
case light:
|
||||
return R.style.AppThemeLight;
|
||||
case dark:
|
||||
return R.style.AppThemeDark;
|
||||
case night:
|
||||
return R.style.AppThemeNight;
|
||||
default:
|
||||
return R.style.AppThemeLight;
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isAppThemeLight() {
|
||||
return AppCompatDelegate.getDefaultNightMode() == AppCompatDelegate.MODE_NIGHT_NO;
|
||||
return curTheme == Theme.light;
|
||||
}
|
||||
|
||||
public void applyDialogTheme(AppCompatActivity activity) {
|
||||
@ -213,7 +191,10 @@ public class FDroidApp extends Application implements androidx.work.Configuratio
|
||||
|
||||
private static int getCurDialogThemeResId() {
|
||||
switch (curTheme) {
|
||||
case light:
|
||||
return R.style.MinWithDialogBaseThemeLight;
|
||||
case dark:
|
||||
return R.style.MinWithDialogBaseThemeDark;
|
||||
case night:
|
||||
return R.style.MinWithDialogBaseThemeDark;
|
||||
default:
|
||||
@ -221,6 +202,24 @@ public class FDroidApp extends Application implements androidx.work.Configuratio
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Force reload the {@link AppCompatActivity to make theme changes take effect.}
|
||||
* Same as {@link Languages#forceChangeLanguage(AppCompatActivity)}
|
||||
*
|
||||
* @param activity the {@code AppCompatActivity} to force reload
|
||||
*/
|
||||
public static void forceChangeTheme(AppCompatActivity activity) {
|
||||
Intent intent = activity.getIntent();
|
||||
if (intent == null) { // when launched as LAUNCHER
|
||||
return;
|
||||
}
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
|
||||
activity.finish();
|
||||
activity.overridePendingTransition(0, 0);
|
||||
activity.startActivity(intent);
|
||||
activity.overridePendingTransition(0, 0);
|
||||
}
|
||||
|
||||
public static void enableBouncyCastle() {
|
||||
Security.addProvider(BOUNCYCASTLE_PROVIDER);
|
||||
}
|
||||
@ -269,7 +268,7 @@ public class FDroidApp extends Application implements androidx.work.Configuratio
|
||||
* @see #getTimeout()
|
||||
* @see Repo#getRandomMirror(String)
|
||||
*/
|
||||
public static synchronized String getNewMirrorOnError(@Nullable String urlString, Repo repo2) throws IOException {
|
||||
public static String getNewMirrorOnError(@Nullable String urlString, Repo repo2) throws IOException {
|
||||
if (repo2.hasMirrors()) {
|
||||
if (numTries <= 0) {
|
||||
if (timeout == Downloader.DEFAULT_TIMEOUT) {
|
||||
@ -394,8 +393,7 @@ public class FDroidApp extends Application implements androidx.work.Configuratio
|
||||
|
||||
PRNGFixes.apply();
|
||||
|
||||
applyTheme();
|
||||
|
||||
curTheme = preferences.getTheme();
|
||||
configureProxy(preferences);
|
||||
|
||||
|
||||
|
@ -27,9 +27,9 @@ import android.content.ContentResolver;
|
||||
import android.content.ContentValues;
|
||||
import android.content.Context;
|
||||
import android.content.pm.PackageInfo;
|
||||
import androidx.annotation.NonNull;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
|
||||
import org.fdroid.fdroid.data.Apk;
|
||||
import org.fdroid.fdroid.data.ApkProvider;
|
||||
import org.fdroid.fdroid.data.App;
|
||||
@ -48,6 +48,9 @@ import org.xml.sax.InputSource;
|
||||
import org.xml.sax.SAXException;
|
||||
import org.xml.sax.XMLReader;
|
||||
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
import javax.xml.parsers.SAXParser;
|
||||
import javax.xml.parsers.SAXParserFactory;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
@ -61,12 +64,6 @@ import java.util.List;
|
||||
import java.util.jar.JarEntry;
|
||||
import java.util.jar.JarFile;
|
||||
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
import javax.xml.parsers.SAXParser;
|
||||
import javax.xml.parsers.SAXParserFactory;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
// TODO move to org.fdroid.fdroid.updater
|
||||
// TODO reduce visibility of methods once in .updater package (.e.g tests need it public now)
|
||||
|
||||
|
@ -25,9 +25,9 @@ package org.fdroid.fdroid;
|
||||
import android.content.ContentValues;
|
||||
import android.content.Context;
|
||||
import android.content.pm.PackageInfo;
|
||||
import androidx.annotation.NonNull;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonAutoDetect;
|
||||
import com.fasterxml.jackson.annotation.PropertyAccessor;
|
||||
import com.fasterxml.jackson.core.JsonFactory;
|
||||
@ -36,7 +36,6 @@ import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import com.fasterxml.jackson.databind.DeserializationFeature;
|
||||
import com.fasterxml.jackson.databind.InjectableValues;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.fdroid.fdroid.data.Apk;
|
||||
import org.fdroid.fdroid.data.App;
|
||||
@ -48,6 +47,10 @@ import org.fdroid.fdroid.data.Schema;
|
||||
import org.fdroid.fdroid.net.Downloader;
|
||||
import org.fdroid.fdroid.net.DownloaderFactory;
|
||||
|
||||
import javax.net.ssl.SSLHandshakeException;
|
||||
import javax.net.ssl.SSLKeyException;
|
||||
import javax.net.ssl.SSLPeerUnverifiedException;
|
||||
import javax.net.ssl.SSLProtocolException;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
@ -68,13 +71,6 @@ import java.util.Map;
|
||||
import java.util.jar.JarEntry;
|
||||
import java.util.jar.JarFile;
|
||||
|
||||
import javax.net.ssl.SSLHandshakeException;
|
||||
import javax.net.ssl.SSLKeyException;
|
||||
import javax.net.ssl.SSLPeerUnverifiedException;
|
||||
import javax.net.ssl.SSLProtocolException;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
/**
|
||||
* Receives the index data about all available apps and packages via the V1
|
||||
* JSON data {@link #DATA_FILE_NAME}, embedded in a signed jar
|
||||
|
@ -8,6 +8,8 @@ import android.content.res.Resources;
|
||||
import android.os.Build;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashSet;
|
||||
@ -16,8 +18,6 @@ import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.TreeMap;
|
||||
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
|
||||
public final class Languages {
|
||||
public static final String TAG = "Languages";
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
package org.fdroid.fdroid;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import android.content.Context;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
@ -11,8 +12,6 @@ import android.nfc.NfcAdapter;
|
||||
import android.os.Build;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
|
||||
public class NfcHelper {
|
||||
|
||||
private static final String TAG = "NfcHelper";
|
||||
|
@ -6,7 +6,6 @@ import android.nfc.NfcAdapter;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.provider.Settings;
|
||||
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
|
||||
// aka Android 4.0 aka Ice Cream Sandwich
|
||||
@ -40,9 +39,8 @@ public class NfcNotEnabledActivity extends AppCompatActivity {
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
FDroidApp fdroidApp = (FDroidApp) getApplication();
|
||||
fdroidApp.applyPureBlackBackgroundInDarkTheme(this);
|
||||
|
||||
((FDroidApp) getApplication()).applyTheme(this);
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
final Intent intent = new Intent();
|
||||
|
@ -20,6 +20,11 @@ import android.text.TextUtils;
|
||||
import android.text.style.StyleSpan;
|
||||
import android.view.View;
|
||||
|
||||
import androidx.core.app.NotificationCompat;
|
||||
import androidx.core.app.NotificationManagerCompat;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
|
||||
|
||||
import com.nostra13.universalimageloader.core.ImageLoader;
|
||||
import com.nostra13.universalimageloader.core.assist.FailReason;
|
||||
import com.nostra13.universalimageloader.core.assist.ImageSize;
|
||||
@ -33,11 +38,6 @@ import org.fdroid.fdroid.views.main.MainActivity;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
|
||||
import androidx.core.app.NotificationCompat;
|
||||
import androidx.core.app.NotificationManagerCompat;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
|
||||
|
||||
@SuppressWarnings("LineLength")
|
||||
public class NotificationHelper {
|
||||
public static final String CHANNEL_SWAPS = "swap-channel";
|
||||
|
@ -30,7 +30,8 @@ import android.net.NetworkInfo;
|
||||
import android.os.Build;
|
||||
import android.text.format.DateUtils;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.preference.PreferenceManager;
|
||||
import org.fdroid.fdroid.installer.PrivilegedInstaller;
|
||||
import org.fdroid.fdroid.net.ConnectivityMonitorService;
|
||||
|
||||
@ -43,9 +44,6 @@ import java.util.Random;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.preference.PreferenceManager;
|
||||
|
||||
/**
|
||||
* Handles shared preferences for FDroid, looking after the names of
|
||||
* preferences, default values and caching. Needs to be setup in the FDroidApp
|
||||
@ -89,7 +87,6 @@ public final class Preferences implements SharedPreferences.OnSharedPreferenceCh
|
||||
public static final String PREF_AUTO_DOWNLOAD_INSTALL_UPDATES = "updateAutoDownload";
|
||||
public static final String PREF_UPDATE_NOTIFICATION_ENABLED = "updateNotify";
|
||||
public static final String PREF_THEME = "theme";
|
||||
public static final String PREF_USE_PURE_BLACK_DARK_THEME = "usePureBlackDarkTheme";
|
||||
public static final String PREF_SHOW_INCOMPAT_VERSIONS = "incompatibleVersions";
|
||||
public static final String PREF_SHOW_ANTI_FEATURE_APPS = "showAntiFeatureApps";
|
||||
public static final String PREF_FORCE_TOUCH_APPS = "ignoreTouchscreen";
|
||||
@ -154,8 +151,7 @@ public final class Preferences implements SharedPreferences.OnSharedPreferenceCh
|
||||
public enum Theme {
|
||||
light,
|
||||
dark,
|
||||
followSystem,
|
||||
night, // Obsolete
|
||||
night,
|
||||
lightWithDarkActionBar, // Obsolete
|
||||
}
|
||||
|
||||
@ -399,10 +395,6 @@ public final class Preferences implements SharedPreferences.OnSharedPreferenceCh
|
||||
return Theme.valueOf(preferences.getString(Preferences.PREF_THEME, null));
|
||||
}
|
||||
|
||||
public boolean isPureBlack() {
|
||||
return preferences.getBoolean(Preferences.PREF_USE_PURE_BLACK_DARK_THEME, false);
|
||||
}
|
||||
|
||||
public boolean isLocalRepoHttpsEnabled() {
|
||||
return false; // disabled until it works well
|
||||
}
|
||||
|
@ -1,11 +1,11 @@
|
||||
package org.fdroid.fdroid;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
class ProgressBufferedInputStream extends BufferedInputStream {
|
||||
|
||||
private final ProgressListener progressListener;
|
||||
@ -24,7 +24,7 @@ class ProgressBufferedInputStream extends BufferedInputStream {
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized int read(@NonNull byte[] buffer, int byteOffset, int byteCount) throws IOException {
|
||||
public int read(@NonNull byte[] buffer, int byteOffset, int byteCount) throws IOException {
|
||||
if (progressListener != null) {
|
||||
currentBytes += byteCount;
|
||||
/* don't send every change to keep things efficient. 333333 bytes to keep all
|
||||
|
@ -4,9 +4,7 @@ import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.util.Base64;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.fdroid.fdroid.data.Repo;
|
||||
import org.fdroid.fdroid.data.RepoProvider;
|
||||
|
@ -30,6 +30,7 @@ import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.net.Uri;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Build;
|
||||
import android.os.Process;
|
||||
import android.os.SystemClock;
|
||||
@ -37,6 +38,12 @@ import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.core.app.JobIntentService;
|
||||
import androidx.core.app.NotificationCompat;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
|
||||
|
||||
import org.fdroid.fdroid.data.Apk;
|
||||
import org.fdroid.fdroid.data.ApkProvider;
|
||||
import org.fdroid.fdroid.data.App;
|
||||
@ -50,18 +57,9 @@ import org.fdroid.fdroid.installer.InstallManagerService;
|
||||
import org.fdroid.fdroid.net.BluetoothDownloader;
|
||||
import org.fdroid.fdroid.net.ConnectivityMonitorService;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.core.app.JobIntentService;
|
||||
import androidx.core.app.NotificationCompat;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
|
||||
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
|
||||
import io.reactivex.rxjava3.core.Completable;
|
||||
import io.reactivex.rxjava3.schedulers.Schedulers;
|
||||
|
||||
public class UpdateService extends JobIntentService {
|
||||
|
||||
@ -83,13 +81,6 @@ public class UpdateService extends JobIntentService {
|
||||
public static final int STATUS_ERROR_LOCAL_SMALL = 4;
|
||||
public static final int STATUS_INFO = 5;
|
||||
|
||||
/**
|
||||
* This number should never change, it is used by ROMs to trigger
|
||||
* the first background update of F-Droid during setup.
|
||||
*
|
||||
* @see <a href="https://gitlab.com/fdroid/fdroidclient/-/issues/2147">Add a way to trigger an index update externally</a>
|
||||
* @see <a href="https://review.calyxos.org/c/CalyxOS/platform_packages_apps_SetupWizard/+/3461"/>Schedule F-Droid index update on initialization and network connection</a>
|
||||
*/
|
||||
private static final int JOB_ID = 0xfedcba;
|
||||
|
||||
private static final int NOTIFY_ID_UPDATING = 0;
|
||||
@ -217,30 +208,42 @@ public class UpdateService extends JobIntentService {
|
||||
* unlimited networks over metered networks for index updates and auto
|
||||
* downloads of app updates. Starting with {@code android-21}, this uses
|
||||
* {@link android.app.job.JobScheduler} instead.
|
||||
*
|
||||
* @return a {@link Completable} that schedules the update. If this process is already running,
|
||||
* a {@code Completable} that completes immediately is returned.
|
||||
*/
|
||||
@NonNull
|
||||
public static Completable scheduleIfStillOnWifi(Context context) {
|
||||
public static void scheduleIfStillOnWifi(Context context) {
|
||||
if (Build.VERSION.SDK_INT >= 21) {
|
||||
throw new IllegalStateException("This should never be used on android-21 or newer!");
|
||||
}
|
||||
if (isScheduleIfStillOnWifiRunning || !Preferences.get().isBackgroundDownloadAllowed()) {
|
||||
return Completable.complete();
|
||||
return;
|
||||
}
|
||||
isScheduleIfStillOnWifiRunning = true;
|
||||
new StillOnWifiAsyncTask(context).execute();
|
||||
}
|
||||
|
||||
private static final class StillOnWifiAsyncTask extends AsyncTask<Void, Void, Void> {
|
||||
|
||||
private final WeakReference<Context> contextWeakReference;
|
||||
|
||||
private StillOnWifiAsyncTask(Context context) {
|
||||
this.contextWeakReference = new WeakReference<>(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Void doInBackground(Void... voids) {
|
||||
Context context = contextWeakReference.get();
|
||||
try {
|
||||
Thread.sleep(120000);
|
||||
if (Preferences.get().isBackgroundDownloadAllowed()) {
|
||||
Utils.debugLog(TAG, "scheduling update because there is good internet");
|
||||
schedule(context);
|
||||
}
|
||||
} catch (Throwable e) { // NOPMD
|
||||
Utils.debugLog(TAG, e.getMessage());
|
||||
}
|
||||
isScheduleIfStillOnWifiRunning = false;
|
||||
return null;
|
||||
}
|
||||
|
||||
return Completable.timer(2, TimeUnit.MINUTES)
|
||||
.andThen(Completable.fromAction(() -> {
|
||||
if (Preferences.get().isBackgroundDownloadAllowed()) {
|
||||
Utils.debugLog(TAG, "scheduling update because there is good internet");
|
||||
schedule(context);
|
||||
}
|
||||
isScheduleIfStillOnWifiRunning = false;
|
||||
}))
|
||||
.subscribeOn(Schedulers.computation())
|
||||
.observeOn(AndroidSchedulers.mainThread());
|
||||
}
|
||||
|
||||
public static void stopNow(Context context) {
|
||||
@ -250,37 +253,6 @@ public class UpdateService extends JobIntentService {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a {@link List} of all {@link Repo}s that have either a local
|
||||
* canonical URL or a local mirror URL. These are repos that can be
|
||||
* updated and used without using the Internet.
|
||||
*/
|
||||
public static List<Repo> getLocalRepos(Context context) {
|
||||
return getLocalRepos(RepoProvider.Helper.all(context));
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the repos in the {@code repos} {@link List} that have either a
|
||||
* local canonical URL or a local mirror URL. These are repos that can be
|
||||
* updated and used without using the Internet.
|
||||
*/
|
||||
public static List<Repo> getLocalRepos(List<Repo> repos) {
|
||||
ArrayList<Repo> localRepos = new ArrayList<>();
|
||||
for (Repo repo : repos) {
|
||||
if (isLocalRepoAddress(repo.address)) {
|
||||
localRepos.add(repo);
|
||||
} else {
|
||||
for (String mirrorAddress : repo.getMirrorList()) {
|
||||
if (isLocalRepoAddress(mirrorAddress)) {
|
||||
localRepos.add(repo);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return localRepos;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
@ -292,7 +264,7 @@ public class UpdateService extends JobIntentService {
|
||||
.setSmallIcon(R.drawable.ic_refresh)
|
||||
.setOngoing(true)
|
||||
.setCategory(NotificationCompat.CATEGORY_SERVICE)
|
||||
.setContentTitle(getString(R.string.banner_updating_repositories));
|
||||
.setContentTitle(getString(R.string.update_notification_title));
|
||||
appUpdateStatusManager = AppUpdateStatusManager.getInstance(this);
|
||||
}
|
||||
|
||||
@ -432,11 +404,22 @@ public class UpdateService extends JobIntentService {
|
||||
if (isLocalRepoAddress(address)) {
|
||||
Utils.debugLog(TAG, "skipping internet check, this is local: " + address);
|
||||
} else if (netState == ConnectivityMonitorService.FLAG_NET_UNAVAILABLE) {
|
||||
// keep track of repos that have a local copy in case internet is not available
|
||||
List<Repo> localRepos = getLocalRepos(repos);
|
||||
if (localRepos.size() > 0) {
|
||||
repos = localRepos;
|
||||
} else {
|
||||
boolean foundLocalRepo = false;
|
||||
for (Repo repo : repos) {
|
||||
if (isLocalRepoAddress(repo.address)) {
|
||||
foundLocalRepo = true;
|
||||
} else {
|
||||
for (String mirrorAddress : repo.getMirrorList()) {
|
||||
if (isLocalRepoAddress(mirrorAddress)) {
|
||||
foundLocalRepo = true;
|
||||
//localRepos.add(repo);
|
||||
//FDroidApp.setLastWorkingMirror(repo.getId(), mirrorAddress);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!foundLocalRepo) {
|
||||
Utils.debugLog(TAG, "No internet, cannot update");
|
||||
if (manualUpdate) {
|
||||
Utils.showToastFromService(this, getString(R.string.warning_no_internet), Toast.LENGTH_SHORT);
|
||||
|
@ -27,7 +27,6 @@ import android.content.pm.Signature;
|
||||
import android.content.res.Resources;
|
||||
import android.database.Cursor;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Point;
|
||||
import android.graphics.Rect;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
@ -45,21 +44,19 @@ import android.text.style.TypefaceSpan;
|
||||
import android.util.DisplayMetrics;
|
||||
import android.util.Log;
|
||||
import android.util.TypedValue;
|
||||
import android.view.Display;
|
||||
import android.view.View;
|
||||
import android.view.ViewTreeObserver;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.google.zxing.BarcodeFormat;
|
||||
import com.google.zxing.encode.Contents;
|
||||
import com.google.zxing.encode.QRCodeEncoder;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.RequiresApi;
|
||||
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
|
||||
import com.nostra13.universalimageloader.core.DisplayImageOptions;
|
||||
import com.nostra13.universalimageloader.core.ImageLoader;
|
||||
import com.nostra13.universalimageloader.core.assist.ImageScaleType;
|
||||
import com.nostra13.universalimageloader.core.display.FadeInBitmapDisplayer;
|
||||
import com.nostra13.universalimageloader.utils.StorageUtils;
|
||||
|
||||
import org.fdroid.fdroid.compat.FileCompat;
|
||||
import org.fdroid.fdroid.data.App;
|
||||
import org.fdroid.fdroid.data.Repo;
|
||||
@ -97,15 +94,6 @@ import java.util.TimeZone;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.RequiresApi;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
|
||||
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
|
||||
import io.reactivex.rxjava3.core.Single;
|
||||
import io.reactivex.rxjava3.schedulers.Schedulers;
|
||||
|
||||
public final class Utils {
|
||||
|
||||
private static final String TAG = "Utils";
|
||||
@ -492,7 +480,12 @@ public final class Utils {
|
||||
*/
|
||||
public static DisplayImageOptions.Builder getDefaultDisplayImageOptionsBuilder() {
|
||||
if (defaultDisplayImageOptionsBuilder == null) {
|
||||
defaultDisplayImageOptionsBuilder = createDefaultDisplayImageOptionsBuilder();
|
||||
defaultDisplayImageOptionsBuilder = new DisplayImageOptions.Builder()
|
||||
.cacheInMemory(true)
|
||||
.cacheOnDisk(true)
|
||||
.considerExifParams(false)
|
||||
.bitmapConfig(Bitmap.Config.RGB_565)
|
||||
.imageScaleType(ImageScaleType.EXACTLY);
|
||||
}
|
||||
return defaultDisplayImageOptionsBuilder;
|
||||
}
|
||||
@ -504,7 +497,7 @@ public final class Utils {
|
||||
*/
|
||||
public static DisplayImageOptions getRepoAppDisplayImageOptions() {
|
||||
if (repoAppDisplayImageOptions == null) {
|
||||
repoAppDisplayImageOptions = createDefaultDisplayImageOptionsBuilder()
|
||||
repoAppDisplayImageOptions = getDefaultDisplayImageOptionsBuilder()
|
||||
.showImageOnLoading(R.drawable.ic_repo_app_default)
|
||||
.showImageForEmptyUri(R.drawable.ic_repo_app_default)
|
||||
.showImageOnFail(R.drawable.ic_repo_app_default)
|
||||
@ -514,15 +507,6 @@ public final class Utils {
|
||||
return repoAppDisplayImageOptions;
|
||||
}
|
||||
|
||||
private static DisplayImageOptions.Builder createDefaultDisplayImageOptionsBuilder() {
|
||||
return new DisplayImageOptions.Builder()
|
||||
.cacheInMemory(true)
|
||||
.cacheOnDisk(true)
|
||||
.considerExifParams(false)
|
||||
.bitmapConfig(Bitmap.Config.RGB_565)
|
||||
.imageScaleType(ImageScaleType.EXACTLY);
|
||||
}
|
||||
|
||||
/**
|
||||
* If app has an iconUrl we feed that to UIL, otherwise we ask the PackageManager which will
|
||||
* return the app's icon directly when the app is installed.
|
||||
@ -995,27 +979,6 @@ public final class Utils {
|
||||
}
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public static Single<Bitmap> generateQrBitmap(@NonNull final AppCompatActivity activity,
|
||||
@NonNull final String qrData) {
|
||||
return Single.fromCallable(() -> {
|
||||
Display display = activity.getWindowManager().getDefaultDisplay();
|
||||
Point outSize = new Point();
|
||||
display.getSize(outSize);
|
||||
final int x = outSize.x;
|
||||
final int y = outSize.y;
|
||||
final int qrCodeDimension = Math.min(x, y);
|
||||
debugLog(TAG, "generating QRCode Bitmap of " + qrCodeDimension + "x" + qrCodeDimension);
|
||||
QRCodeEncoder qrCodeEncoder = new QRCodeEncoder(qrData, null,
|
||||
Contents.Type.TEXT, BarcodeFormat.QR_CODE.toString(), qrCodeDimension);
|
||||
|
||||
return qrCodeEncoder.encodeAsBitmap();
|
||||
})
|
||||
.subscribeOn(Schedulers.computation())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.doOnError(throwable -> Log.e(TAG, "Could not encode QR as bitmap", throwable));
|
||||
}
|
||||
|
||||
/**
|
||||
* Keep an instance of this class as an field in an AppCompatActivity for figuring out whether the on
|
||||
* screen keyboard is currently visible or not.
|
||||
|
@ -2,15 +2,12 @@ package org.fdroid.fdroid.acra;
|
||||
|
||||
import android.content.DialogInterface;
|
||||
import android.os.Bundle;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import android.widget.EditText;
|
||||
|
||||
import org.acra.dialog.BaseCrashReportDialog;
|
||||
import org.fdroid.fdroid.R;
|
||||
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
|
||||
import com.google.android.material.textfield.TextInputLayout;
|
||||
|
||||
public class CrashReportActivity extends BaseCrashReportDialog
|
||||
implements DialogInterface.OnDismissListener, DialogInterface.OnClickListener {
|
||||
|
||||
@ -32,8 +29,7 @@ public class CrashReportActivity extends BaseCrashReportDialog
|
||||
dialog.setOnDismissListener(this);
|
||||
dialog.show();
|
||||
|
||||
TextInputLayout commentLayout = dialog.findViewById(android.R.id.input);
|
||||
comment = commentLayout.getEditText();
|
||||
comment = (EditText) dialog.findViewById(android.R.id.input);
|
||||
if (savedInstanceState != null) {
|
||||
comment.setText(savedInstanceState.getString(STATE_COMMENT));
|
||||
}
|
||||
|
@ -4,15 +4,13 @@ package org.fdroid.fdroid.acra;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import org.acra.ReportField;
|
||||
import org.acra.collections.ImmutableSet;
|
||||
import org.acra.collector.CrashReportData;
|
||||
import org.acra.config.ACRAConfiguration;
|
||||
import org.acra.sender.ReportSender;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
public class CrashReportSender implements ReportSender {
|
||||
|
||||
private final ACRAConfiguration config;
|
||||
|
@ -1,13 +1,12 @@
|
||||
package org.fdroid.fdroid.acra;
|
||||
|
||||
import android.content.Context;
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import org.acra.config.ACRAConfiguration;
|
||||
import org.acra.sender.ReportSender;
|
||||
import org.acra.sender.ReportSenderFactory;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
public class CrashReportSenderFactory implements ReportSenderFactory {
|
||||
@NonNull
|
||||
@Override
|
||||
|
@ -5,6 +5,8 @@ import android.os.Build;
|
||||
import android.system.ErrnoException;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.annotation.RequiresApi;
|
||||
|
||||
import org.fdroid.fdroid.FDroidApp;
|
||||
import org.fdroid.fdroid.Utils;
|
||||
import org.fdroid.fdroid.data.SanitizedFile;
|
||||
@ -12,8 +14,6 @@ import org.fdroid.fdroid.data.SanitizedFile;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import androidx.annotation.RequiresApi;
|
||||
|
||||
/**
|
||||
* This class works only with {@link SanitizedFile} instances to enforce
|
||||
* filtering of the file names from files downloaded from the internet.
|
||||
|
@ -12,11 +12,11 @@ import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import android.text.TextUtils;
|
||||
import android.webkit.MimeTypeMap;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import com.fasterxml.jackson.annotation.JacksonInject;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
import org.fdroid.fdroid.BuildConfig;
|
||||
import org.fdroid.fdroid.Utils;
|
||||
import org.fdroid.fdroid.data.Schema.ApkTable.Cols;
|
||||
@ -30,9 +30,6 @@ import java.util.HashSet;
|
||||
import java.util.Locale;
|
||||
import java.util.zip.ZipFile;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* Represents a single package of an application. This represents one particular
|
||||
* package of a given application, for info about the app in general, see
|
||||
|
@ -6,8 +6,9 @@ import android.content.Context;
|
||||
import android.content.UriMatcher;
|
||||
import android.database.Cursor;
|
||||
import android.net.Uri;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import android.util.Log;
|
||||
|
||||
import org.fdroid.fdroid.Utils;
|
||||
import org.fdroid.fdroid.data.Schema.AntiFeatureTable;
|
||||
import org.fdroid.fdroid.data.Schema.ApkAntiFeatureJoinTable;
|
||||
@ -25,9 +26,6 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
public class ApkProvider extends FDroidProvider {
|
||||
|
||||
private static final String TAG = "ApkProvider";
|
||||
|