Merge branch '1.2.1-polish' into 'master'
1.2.1 polish Closes #577 and #440 See merge request fdroid/fdroidclient!674
This commit is contained in:
commit
9a33a751a1
@ -7,8 +7,6 @@ import android.content.pm.PackageManager;
|
|||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.preference.PreferenceManager;
|
import android.preference.PreferenceManager;
|
||||||
import android.support.annotation.Nullable;
|
import android.support.annotation.Nullable;
|
||||||
import android.text.TextUtils;
|
|
||||||
|
|
||||||
import org.fdroid.fdroid.compat.SupportedArchitectures;
|
import org.fdroid.fdroid.compat.SupportedArchitectures;
|
||||||
import org.fdroid.fdroid.data.Apk;
|
import org.fdroid.fdroid.data.Apk;
|
||||||
|
|
||||||
@ -22,12 +20,11 @@ import java.util.Set;
|
|||||||
// find reasons why an apk may be incompatible with the user's device.
|
// find reasons why an apk may be incompatible with the user's device.
|
||||||
public class CompatibilityChecker {
|
public class CompatibilityChecker {
|
||||||
|
|
||||||
private static final String TAG = "Compatibility";
|
public static final String TAG = "Compatibility";
|
||||||
|
|
||||||
private final Context context;
|
private final Context context;
|
||||||
private final Set<String> features;
|
private final Set<String> features;
|
||||||
private final String[] cpuAbis;
|
private final String[] cpuAbis;
|
||||||
private final String cpuAbisDesc;
|
|
||||||
private final boolean forceTouchApps;
|
private final boolean forceTouchApps;
|
||||||
|
|
||||||
public CompatibilityChecker(Context ctx) {
|
public CompatibilityChecker(Context ctx) {
|
||||||
@ -43,13 +40,6 @@ public class CompatibilityChecker {
|
|||||||
if (pm != null) {
|
if (pm != null) {
|
||||||
final FeatureInfo[] featureArray = pm.getSystemAvailableFeatures();
|
final FeatureInfo[] featureArray = pm.getSystemAvailableFeatures();
|
||||||
if (featureArray != null) {
|
if (featureArray != null) {
|
||||||
if (BuildConfig.DEBUG) {
|
|
||||||
StringBuilder logMsg = new StringBuilder("Available device features:");
|
|
||||||
for (FeatureInfo fi : pm.getSystemAvailableFeatures()) {
|
|
||||||
logMsg.append('\n').append(fi.name);
|
|
||||||
}
|
|
||||||
Utils.debugLog(TAG, logMsg.toString());
|
|
||||||
}
|
|
||||||
for (FeatureInfo fi : pm.getSystemAvailableFeatures()) {
|
for (FeatureInfo fi : pm.getSystemAvailableFeatures()) {
|
||||||
features.add(fi.name);
|
features.add(fi.name);
|
||||||
}
|
}
|
||||||
@ -57,18 +47,6 @@ public class CompatibilityChecker {
|
|||||||
}
|
}
|
||||||
|
|
||||||
cpuAbis = SupportedArchitectures.getAbis();
|
cpuAbis = SupportedArchitectures.getAbis();
|
||||||
|
|
||||||
StringBuilder builder = new StringBuilder();
|
|
||||||
boolean first = true;
|
|
||||||
for (final String abi : cpuAbis) {
|
|
||||||
if (first) {
|
|
||||||
first = false;
|
|
||||||
} else {
|
|
||||||
builder.append(", ");
|
|
||||||
}
|
|
||||||
builder.append(abi);
|
|
||||||
}
|
|
||||||
cpuAbisDesc = builder.toString();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean compatibleApi(@Nullable String[] nativecode) {
|
private boolean compatibleApi(@Nullable String[] nativecode) {
|
||||||
@ -107,16 +85,11 @@ public class CompatibilityChecker {
|
|||||||
}
|
}
|
||||||
if (!features.contains(feat)) {
|
if (!features.contains(feat)) {
|
||||||
Collections.addAll(incompatibleReasons, feat.split(","));
|
Collections.addAll(incompatibleReasons, feat.split(","));
|
||||||
Utils.debugLog(TAG, apk.packageName + " vercode " + apk.versionCode
|
|
||||||
+ " is incompatible based on lack of " + feat);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!compatibleApi(apk.nativecode)) {
|
if (!compatibleApi(apk.nativecode)) {
|
||||||
Collections.addAll(incompatibleReasons, apk.nativecode);
|
Collections.addAll(incompatibleReasons, apk.nativecode);
|
||||||
Utils.debugLog(TAG, apk.packageName + " vercode " + apk.versionCode
|
|
||||||
+ " only supports " + TextUtils.join(", ", apk.nativecode)
|
|
||||||
+ " while your architectures are " + cpuAbisDesc);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return incompatibleReasons;
|
return incompatibleReasons;
|
||||||
|
@ -36,6 +36,7 @@ import android.graphics.Bitmap;
|
|||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.os.Environment;
|
import android.os.Environment;
|
||||||
import android.os.StrictMode;
|
import android.os.StrictMode;
|
||||||
|
import android.support.v4.util.LongSparseArray;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.Display;
|
import android.view.Display;
|
||||||
@ -113,7 +114,9 @@ public class FDroidApp extends Application {
|
|||||||
|
|
||||||
public static volatile int networkState = ConnectivityMonitorService.FLAG_NET_UNAVAILABLE;
|
public static volatile int networkState = ConnectivityMonitorService.FLAG_NET_UNAVAILABLE;
|
||||||
|
|
||||||
private static volatile String lastWorkingMirror = null;
|
public static final SubnetUtils.SubnetInfo UNSET_SUBNET_INFO = new SubnetUtils("0.0.0.0/32").getInfo();
|
||||||
|
|
||||||
|
private static volatile LongSparseArray<String> lastWorkingMirrorArray = new LongSparseArray<>(1);
|
||||||
private static volatile int numTries = Integer.MAX_VALUE;
|
private static volatile int numTries = Integer.MAX_VALUE;
|
||||||
private static volatile int timeout = 10000;
|
private static volatile int timeout = 10000;
|
||||||
|
|
||||||
@ -230,7 +233,7 @@ public class FDroidApp extends Application {
|
|||||||
public static void initWifiSettings() {
|
public static void initWifiSettings() {
|
||||||
port = 8888;
|
port = 8888;
|
||||||
ipAddressString = null;
|
ipAddressString = null;
|
||||||
subnetInfo = new SubnetUtils("0.0.0.0/32").getInfo();
|
subnetInfo = UNSET_SUBNET_INFO;
|
||||||
ssid = "";
|
ssid = "";
|
||||||
bssid = "";
|
bssid = "";
|
||||||
repo = new Repo();
|
repo = new Repo();
|
||||||
@ -242,6 +245,7 @@ public class FDroidApp extends Application {
|
|||||||
|
|
||||||
public static String getMirror(String urlString, Repo repo2) throws IOException {
|
public static String getMirror(String urlString, Repo repo2) throws IOException {
|
||||||
if (repo2.hasMirrors()) {
|
if (repo2.hasMirrors()) {
|
||||||
|
String lastWorkingMirror = lastWorkingMirrorArray.get(repo2.getId());
|
||||||
if (lastWorkingMirror == null) {
|
if (lastWorkingMirror == null) {
|
||||||
lastWorkingMirror = repo2.address;
|
lastWorkingMirror = repo2.address;
|
||||||
}
|
}
|
||||||
@ -264,7 +268,7 @@ public class FDroidApp extends Application {
|
|||||||
String newUrl = urlString.replace(lastWorkingMirror, mirror);
|
String newUrl = urlString.replace(lastWorkingMirror, mirror);
|
||||||
Utils.debugLog(TAG, "Trying mirror " + mirror + " after " + lastWorkingMirror + " failed," +
|
Utils.debugLog(TAG, "Trying mirror " + mirror + " after " + lastWorkingMirror + " failed," +
|
||||||
" timeout=" + timeout / 1000 + "s");
|
" timeout=" + timeout / 1000 + "s");
|
||||||
lastWorkingMirror = mirror;
|
lastWorkingMirrorArray.put(repo2.getId(), mirror);
|
||||||
numTries--;
|
numTries--;
|
||||||
return newUrl;
|
return newUrl;
|
||||||
} else {
|
} else {
|
||||||
@ -278,7 +282,9 @@ public class FDroidApp extends Application {
|
|||||||
|
|
||||||
public static void resetMirrorVars() {
|
public static void resetMirrorVars() {
|
||||||
// Reset last working mirror, numtries, and timeout
|
// Reset last working mirror, numtries, and timeout
|
||||||
lastWorkingMirror = null;
|
for (int i = 0; i < lastWorkingMirrorArray.size(); i++) {
|
||||||
|
lastWorkingMirrorArray.removeAt(i);
|
||||||
|
}
|
||||||
numTries = Integer.MAX_VALUE;
|
numTries = Integer.MAX_VALUE;
|
||||||
timeout = 10000;
|
timeout = 10000;
|
||||||
}
|
}
|
||||||
|
@ -18,6 +18,7 @@ import org.fdroid.fdroid.data.Schema.InstalledAppTable;
|
|||||||
import org.fdroid.fdroid.data.Schema.InstalledAppTable.Cols;
|
import org.fdroid.fdroid.data.Schema.InstalledAppTable.Cols;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
public class InstalledAppProvider extends FDroidProvider {
|
public class InstalledAppProvider extends FDroidProvider {
|
||||||
@ -81,6 +82,20 @@ public class InstalledAppProvider extends FDroidProvider {
|
|||||||
|
|
||||||
private static final UriMatcher MATCHER = new UriMatcher(-1);
|
private static final UriMatcher MATCHER = new UriMatcher(-1);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Built-in apps that are signed by the various Android ROM keys.
|
||||||
|
*
|
||||||
|
* @see <a href="https://source.android.com/devices/tech/ota/sign_builds#certificates-keys">Certificates and private keys</a>
|
||||||
|
*/
|
||||||
|
private static final String[] SYSTEM_PACKAGES = {
|
||||||
|
"android", // platform key
|
||||||
|
"com.android.email", // test/release key
|
||||||
|
"com.android.contacts", // shared key
|
||||||
|
"com.android.providers.downloads", // media key
|
||||||
|
};
|
||||||
|
|
||||||
|
private static String[] systemSignatures;
|
||||||
|
|
||||||
static {
|
static {
|
||||||
MATCHER.addURI(getAuthority(), null, CODE_LIST);
|
MATCHER.addURI(getAuthority(), null, CODE_LIST);
|
||||||
MATCHER.addURI(getAuthority(), PATH_SEARCH + "/*", CODE_SEARCH);
|
MATCHER.addURI(getAuthority(), PATH_SEARCH + "/*", CODE_SEARCH);
|
||||||
@ -117,6 +132,36 @@ public class InstalledAppProvider extends FDroidProvider {
|
|||||||
return packageName; // all else fails, return packageName
|
return packageName; // all else fails, return packageName
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add SQL selection statement to exclude {@link InstalledApp}s that were
|
||||||
|
* signed by the platform/shared/media/testkey keys.
|
||||||
|
*
|
||||||
|
* @see <a href="https://source.android.com/devices/tech/ota/sign_builds#certificates-keys">Certificates and private keys</a>
|
||||||
|
*/
|
||||||
|
private QuerySelection selectNotSystemSignature(QuerySelection selection) {
|
||||||
|
if (systemSignatures == null) {
|
||||||
|
Log.i(TAG, "selectNotSystemSignature: systemSignature == null, querying for it");
|
||||||
|
HashSet<String> signatures = new HashSet<>();
|
||||||
|
for (String packageName : SYSTEM_PACKAGES) {
|
||||||
|
Cursor cursor = query(InstalledAppProvider.getAppUri(packageName), new String[]{Cols.SIGNATURE},
|
||||||
|
null, null, null);
|
||||||
|
if (cursor != null) {
|
||||||
|
if (cursor.moveToFirst()) {
|
||||||
|
signatures.add(cursor.getString(cursor.getColumnIndex(Cols.SIGNATURE)));
|
||||||
|
}
|
||||||
|
cursor.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
systemSignatures = signatures.toArray(new String[signatures.size()]);
|
||||||
|
}
|
||||||
|
|
||||||
|
Log.i(TAG, "excluding InstalledApps signed by system signatures");
|
||||||
|
for (String systemSignature : systemSignatures) {
|
||||||
|
selection = selection.add("NOT " + Cols.SIGNATURE + " IN (?)", new String[]{systemSignature});
|
||||||
|
}
|
||||||
|
return selection;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected String getTableName() {
|
protected String getTableName() {
|
||||||
return InstalledAppTable.NAME;
|
return InstalledAppTable.NAME;
|
||||||
@ -185,6 +230,7 @@ public class InstalledAppProvider extends FDroidProvider {
|
|||||||
QuerySelection selection = new QuerySelection(customSelection, selectionArgs);
|
QuerySelection selection = new QuerySelection(customSelection, selectionArgs);
|
||||||
switch (MATCHER.match(uri)) {
|
switch (MATCHER.match(uri)) {
|
||||||
case CODE_LIST:
|
case CODE_LIST:
|
||||||
|
selection = selectNotSystemSignature(selection);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CODE_SINGLE:
|
case CODE_SINGLE:
|
||||||
|
@ -23,6 +23,8 @@ import rx.subjects.PublishSubject;
|
|||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FilenameFilter;
|
import java.io.FilenameFilter;
|
||||||
import java.security.NoSuchAlgorithmException;
|
import java.security.NoSuchAlgorithmException;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Comparator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
@ -146,7 +148,10 @@ public class InstalledAppProviderService extends IntentService {
|
|||||||
* Make sure that {@link InstalledAppProvider}, our database of installed apps,
|
* Make sure that {@link InstalledAppProvider}, our database of installed apps,
|
||||||
* is in sync with what the {@link PackageManager} tells us is installed. Once
|
* is in sync with what the {@link PackageManager} tells us is installed. Once
|
||||||
* completed, the relevant {@link android.content.ContentProvider}s will be
|
* completed, the relevant {@link android.content.ContentProvider}s will be
|
||||||
* notified of any changes to installed statuses.
|
* notified of any changes to installed statuses. The packages are processed
|
||||||
|
* in alphabetically order so that "{@code android}" is processed first. That
|
||||||
|
* is always present and signed by the system key, so it is the source of the
|
||||||
|
* system key for comparing all packages.
|
||||||
* <p>
|
* <p>
|
||||||
* The installed app cache could get out of sync, e.g. if F-Droid crashed/ or
|
* The installed app cache could get out of sync, e.g. if F-Droid crashed/ or
|
||||||
* ran out of battery half way through responding to {@link Intent#ACTION_PACKAGE_ADDED}.
|
* ran out of battery half way through responding to {@link Intent#ACTION_PACKAGE_ADDED}.
|
||||||
@ -169,6 +174,12 @@ public class InstalledAppProviderService extends IntentService {
|
|||||||
|
|
||||||
List<PackageInfo> packageInfoList = context.getPackageManager()
|
List<PackageInfo> packageInfoList = context.getPackageManager()
|
||||||
.getInstalledPackages(PackageManager.GET_SIGNATURES);
|
.getInstalledPackages(PackageManager.GET_SIGNATURES);
|
||||||
|
Collections.sort(packageInfoList, new Comparator<PackageInfo>() {
|
||||||
|
@Override
|
||||||
|
public int compare(PackageInfo o1, PackageInfo o2) {
|
||||||
|
return o1.packageName.compareTo(o2.packageName);
|
||||||
|
}
|
||||||
|
});
|
||||||
for (PackageInfo packageInfo : packageInfoList) {
|
for (PackageInfo packageInfo : packageInfoList) {
|
||||||
if (cachedInfo.containsKey(packageInfo.packageName)) {
|
if (cachedInfo.containsKey(packageInfo.packageName)) {
|
||||||
if (packageInfo.lastUpdateTime < 1262300400000L // 2010-01-01 00:00
|
if (packageInfo.lastUpdateTime < 1262300400000L // 2010-01-01 00:00
|
||||||
@ -314,6 +325,11 @@ public class InstalledAppProviderService extends IntentService {
|
|||||||
context.getContentResolver().delete(uri, null, null);
|
context.getContentResolver().delete(uri, null, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the fingerprint used to represent an APK signing key in F-Droid.
|
||||||
|
* This is a custom fingerprint algorithm that was kind of accidentally
|
||||||
|
* created, but is still in use.
|
||||||
|
*/
|
||||||
private static String getPackageSig(PackageInfo info) {
|
private static String getPackageSig(PackageInfo info) {
|
||||||
if (info == null || info.signatures == null || info.signatures.length < 1) {
|
if (info == null || info.signatures == null || info.signatures.length < 1) {
|
||||||
return "";
|
return "";
|
||||||
|
@ -481,6 +481,8 @@ public class SwapService extends Service {
|
|||||||
Utils.debugLog(TAG, "Creating swap service.");
|
Utils.debugLog(TAG, "Creating swap service.");
|
||||||
startForeground(NOTIFICATION, createNotification());
|
startForeground(NOTIFICATION, createNotification());
|
||||||
|
|
||||||
|
deleteAllSwapRepos();
|
||||||
|
|
||||||
CacheSwapAppsService.startCaching(this);
|
CacheSwapAppsService.startCaching(this);
|
||||||
|
|
||||||
swapPreferences = getSharedPreferences(SHARED_PREFERENCES, Context.MODE_PRIVATE);
|
swapPreferences = getSharedPreferences(SHARED_PREFERENCES, Context.MODE_PRIVATE);
|
||||||
@ -537,11 +539,11 @@ public class SwapService extends Service {
|
|||||||
Preferences.get().unregisterLocalRepoHttpsListeners(httpsEnabledListener);
|
Preferences.get().unregisterLocalRepoHttpsListeners(httpsEnabledListener);
|
||||||
LocalBroadcastManager.getInstance(this).unregisterReceiver(onWifiChange);
|
LocalBroadcastManager.getInstance(this).unregisterReceiver(onWifiChange);
|
||||||
|
|
||||||
if (!SwapService.wasBluetoothEnabledBeforeSwap()) {
|
if (bluetoothAdapter != null && !wasBluetoothEnabledBeforeSwap()) {
|
||||||
bluetoothAdapter.disable();
|
bluetoothAdapter.disable();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!SwapService.wasWifiEnabledBeforeSwap()) {
|
if (wifiManager != null && !wasWifiEnabledBeforeSwap()) {
|
||||||
wifiManager.setWifiEnabled(false);
|
wifiManager.setWifiEnabled(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -553,6 +555,8 @@ public class SwapService extends Service {
|
|||||||
}
|
}
|
||||||
stopForeground(true);
|
stopForeground(true);
|
||||||
|
|
||||||
|
deleteAllSwapRepos();
|
||||||
|
|
||||||
super.onDestroy();
|
super.onDestroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -568,7 +572,26 @@ public class SwapService extends Service {
|
|||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For now, swap repos are only trusted as long as swapping is active. They
|
||||||
|
* should have a long lived trust based on the signing key, but that requires
|
||||||
|
* that the repos are stored in the database by fingerprint, not by URL address.
|
||||||
|
*
|
||||||
|
* @see <a href="https://gitlab.com/fdroid/fdroidclient/issues/295">TOFU in swap</a>
|
||||||
|
* @see <a href="https://gitlab.com/fdroid/fdroidclient/issues/703">
|
||||||
|
* signing key fingerprint should be sole ID for repos in the database</a>
|
||||||
|
*/
|
||||||
|
private void deleteAllSwapRepos() {
|
||||||
|
for (Repo repo : RepoProvider.Helper.all(this)) {
|
||||||
|
if (repo.isSwap) {
|
||||||
|
Utils.debugLog(TAG, "Removing stale swap repo: " + repo.address + " - " + repo.fingerprint);
|
||||||
|
RepoProvider.Helper.remove(this, repo.getId());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void initTimer() {
|
private void initTimer() {
|
||||||
|
// TODO replace by Android scheduler
|
||||||
if (timer != null) {
|
if (timer != null) {
|
||||||
Utils.debugLog(TAG, "Cancelling existing timeout timer so timeout can be reset.");
|
Utils.debugLog(TAG, "Cancelling existing timeout timer so timeout can be reset.");
|
||||||
timer.cancel();
|
timer.cancel();
|
||||||
|
@ -41,6 +41,10 @@ import java.util.Locale;
|
|||||||
* the current state because it means that something about the wifi has
|
* the current state because it means that something about the wifi has
|
||||||
* changed. Having the {@code Thread} also makes it easy to kill work
|
* changed. Having the {@code Thread} also makes it easy to kill work
|
||||||
* that is in progress.
|
* that is in progress.
|
||||||
|
* <p>
|
||||||
|
* Some devices send multiple copies of given events, like a Moto G often
|
||||||
|
* sends three {@code CONNECTED} events. So they have to be debounced to
|
||||||
|
* keep the {@link #BROADCAST} useful.
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("LineLength")
|
@SuppressWarnings("LineLength")
|
||||||
public class WifiStateChangeService extends IntentService {
|
public class WifiStateChangeService extends IntentService {
|
||||||
@ -50,6 +54,7 @@ public class WifiStateChangeService extends IntentService {
|
|||||||
|
|
||||||
private WifiManager wifiManager;
|
private WifiManager wifiManager;
|
||||||
private static WifiInfoThread wifiInfoThread;
|
private static WifiInfoThread wifiInfoThread;
|
||||||
|
private static int previousWifiState = Integer.MIN_VALUE;
|
||||||
|
|
||||||
public WifiStateChangeService() {
|
public WifiStateChangeService() {
|
||||||
super("WifiStateChangeService");
|
super("WifiStateChangeService");
|
||||||
@ -70,16 +75,17 @@ public class WifiStateChangeService extends IntentService {
|
|||||||
Utils.debugLog(TAG, "received null Intent, ignoring");
|
Utils.debugLog(TAG, "received null Intent, ignoring");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Utils.debugLog(TAG, "WiFi change service started, clearing info about wifi state until we have figured it out again.");
|
Utils.debugLog(TAG, "WiFi change service started.");
|
||||||
NetworkInfo ni = intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);
|
NetworkInfo ni = intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);
|
||||||
wifiManager = (WifiManager) getApplicationContext().getSystemService(WIFI_SERVICE);
|
wifiManager = (WifiManager) getApplicationContext().getSystemService(WIFI_SERVICE);
|
||||||
int wifiState = wifiManager.getWifiState();
|
int wifiState = wifiManager.getWifiState();
|
||||||
if (ni == null || ni.isConnected()) {
|
if (ni == null || ni.isConnected()) {
|
||||||
Utils.debugLog(TAG, "ni == " + ni + " wifiState == " + printWifiState(wifiState));
|
Utils.debugLog(TAG, "ni == " + ni + " wifiState == " + printWifiState(wifiState));
|
||||||
if (wifiState == WifiManager.WIFI_STATE_ENABLED
|
if (previousWifiState != wifiState &&
|
||||||
|| wifiState == WifiManager.WIFI_STATE_DISABLING // might be switching to hotspot
|
(wifiState == WifiManager.WIFI_STATE_ENABLED
|
||||||
|| wifiState == WifiManager.WIFI_STATE_DISABLED // might be hotspot
|
|| wifiState == WifiManager.WIFI_STATE_DISABLING // might be switching to hotspot
|
||||||
|| wifiState == WifiManager.WIFI_STATE_UNKNOWN) { // might be hotspot
|
|| wifiState == WifiManager.WIFI_STATE_DISABLED // might be hotspot
|
||||||
|
|| wifiState == WifiManager.WIFI_STATE_UNKNOWN)) { // might be hotspot
|
||||||
if (wifiInfoThread != null) {
|
if (wifiInfoThread != null) {
|
||||||
wifiInfoThread.interrupt();
|
wifiInfoThread.interrupt();
|
||||||
}
|
}
|
||||||
@ -121,6 +127,10 @@ public class WifiStateChangeService extends IntentService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (FDroidApp.ipAddressString == null
|
||||||
|
|| FDroidApp.subnetInfo == FDroidApp.UNSET_SUBNET_INFO) {
|
||||||
|
setIpInfoFromNetworkInterface();
|
||||||
|
}
|
||||||
} else if (wifiState == WifiManager.WIFI_STATE_DISABLED
|
} else if (wifiState == WifiManager.WIFI_STATE_DISABLED
|
||||||
|| wifiState == WifiManager.WIFI_STATE_DISABLING) {
|
|| wifiState == WifiManager.WIFI_STATE_DISABLING) {
|
||||||
// try once to see if its a hotspot
|
// try once to see if its a hotspot
|
||||||
@ -210,6 +220,16 @@ public class WifiStateChangeService extends IntentService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Search for known Wi-Fi, Hotspot, and local network interfaces and get
|
||||||
|
* the IP Address info from it. This is necessary because network
|
||||||
|
* interfaces in Hotspot/AP mode do not show up in the regular
|
||||||
|
* {@link WifiManager} queries, and also on
|
||||||
|
* {@link android.os.Build.VERSION_CODES#LOLLIPOP Android 5.0} and newer,
|
||||||
|
* {@link WifiManager#getDhcpInfo()} returns an invalid netmask.
|
||||||
|
*
|
||||||
|
* @see <a href="https://issuetracker.google.com/issues/37015180">netmask of WifiManager.getDhcpInfo() is always zero on Android 5.0</a>
|
||||||
|
*/
|
||||||
private void setIpInfoFromNetworkInterface() {
|
private void setIpInfoFromNetworkInterface() {
|
||||||
try {
|
try {
|
||||||
Enumeration<NetworkInterface> networkInterfaces = NetworkInterface.getNetworkInterfaces();
|
Enumeration<NetworkInterface> networkInterfaces = NetworkInterface.getNetworkInterfaces();
|
||||||
@ -273,7 +293,10 @@ public class WifiStateChangeService extends IntentService {
|
|||||||
return "WIFI_STATE_ENABLED";
|
return "WIFI_STATE_ENABLED";
|
||||||
case WifiManager.WIFI_STATE_UNKNOWN:
|
case WifiManager.WIFI_STATE_UNKNOWN:
|
||||||
return "WIFI_STATE_UNKNOWN";
|
return "WIFI_STATE_UNKNOWN";
|
||||||
|
case Integer.MIN_VALUE:
|
||||||
|
return "previous value unset";
|
||||||
|
default:
|
||||||
|
return "~not mapped~";
|
||||||
}
|
}
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -425,7 +425,7 @@ public class SwapWorkflowActivity extends AppCompatActivity {
|
|||||||
})
|
})
|
||||||
.create().show();
|
.create().show();
|
||||||
} else {
|
} else {
|
||||||
showSelectApps();
|
showWifiQr();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user