Add back standalone app
|
@ -0,0 +1,111 @@
|
||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2019, microG Project Team
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
apply plugin: 'com.android.application'
|
||||||
|
apply plugin: 'kotlin-android'
|
||||||
|
apply plugin: 'kotlin-kapt'
|
||||||
|
apply plugin: 'kotlin-android-extensions'
|
||||||
|
apply plugin: 'maven-publish'
|
||||||
|
apply plugin: 'signing'
|
||||||
|
|
||||||
|
String getMyVersionName() {
|
||||||
|
def stdout = new ByteArrayOutputStream()
|
||||||
|
if (rootProject.file("gradlew").exists())
|
||||||
|
exec { commandLine 'git', 'describe', '--tags', '--always', '--dirty'; standardOutput = stdout }
|
||||||
|
else // automatic build system, don't tag dirty
|
||||||
|
exec { commandLine 'git', 'describe', '--tags', '--always'; standardOutput = stdout }
|
||||||
|
return stdout.toString().trim().substring(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
int getMyVersionCode() {
|
||||||
|
def stdout = new ByteArrayOutputStream()
|
||||||
|
exec {
|
||||||
|
commandLine 'git', 'rev-list', '--count', "HEAD"
|
||||||
|
standardOutput = stdout
|
||||||
|
}
|
||||||
|
return Integer.parseInt(stdout.toString().trim())
|
||||||
|
}
|
||||||
|
|
||||||
|
android {
|
||||||
|
compileSdkVersion androidCompileSdk
|
||||||
|
buildToolsVersion "$androidBuildVersionTools"
|
||||||
|
dataBinding {
|
||||||
|
enabled = true
|
||||||
|
}
|
||||||
|
|
||||||
|
defaultConfig {
|
||||||
|
versionName getMyVersionName()
|
||||||
|
versionCode(20000 + getMyVersionCode())
|
||||||
|
minSdkVersion Math.max(androidMinSdk, 14)
|
||||||
|
targetSdkVersion androidTargetSdk
|
||||||
|
}
|
||||||
|
|
||||||
|
sourceSets {
|
||||||
|
main.java.srcDirs += 'src/main/kotlin'
|
||||||
|
}
|
||||||
|
|
||||||
|
flavorDimensions 'default'
|
||||||
|
productFlavors {
|
||||||
|
NetworkLocation {
|
||||||
|
applicationId = 'com.google.android.gms'
|
||||||
|
minSdkVersion 19
|
||||||
|
dimension 'default'
|
||||||
|
}
|
||||||
|
LegacyNetworkLocation {
|
||||||
|
applicationId = 'com.google.android.location'
|
||||||
|
dimension 'default'
|
||||||
|
}
|
||||||
|
UnifiedNlp {
|
||||||
|
applicationId = 'org.microg.nlp'
|
||||||
|
dimension 'default'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
compileOptions {
|
||||||
|
sourceCompatibility = 1.8
|
||||||
|
targetCompatibility = 1.8
|
||||||
|
}
|
||||||
|
|
||||||
|
kotlinOptions {
|
||||||
|
jvmTarget = "1.8"
|
||||||
|
}
|
||||||
|
|
||||||
|
lintOptions {
|
||||||
|
warning "MissingTranslation"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
apply from: "../gradle/androidJars.gradle"
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
implementation project(':api')
|
||||||
|
implementation project(':geocode-v1')
|
||||||
|
implementation project(':location-v2')
|
||||||
|
implementation project(':location-v3')
|
||||||
|
implementation project(':service')
|
||||||
|
api project(':client')
|
||||||
|
api project(':ui')
|
||||||
|
|
||||||
|
// Kotlin
|
||||||
|
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlinVersion"
|
||||||
|
|
||||||
|
// AndroidX UI
|
||||||
|
implementation "androidx.appcompat:appcompat:$appcompatVersion"
|
||||||
|
implementation "androidx.preference:preference:$preferenceVersion"
|
||||||
|
implementation "androidx.lifecycle:lifecycle-service:$lifecycleVersion"
|
||||||
|
|
||||||
|
// Navigation
|
||||||
|
implementation "androidx.navigation:navigation-fragment:$navigationVersion"
|
||||||
|
implementation "androidx.navigation:navigation-ui:$navigationVersion"
|
||||||
|
implementation "androidx.navigation:navigation-fragment-ktx:$navigationVersion"
|
||||||
|
implementation "androidx.navigation:navigation-ui-ktx:$navigationVersion"
|
||||||
|
}
|
||||||
|
|
||||||
|
afterEvaluate {
|
||||||
|
android.applicationVariants.all { variant ->
|
||||||
|
variant.resValue 'string', 'application_id', variant.applicationId
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,54 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?><!--
|
||||||
|
~ Copyright (C) 2013-2017 microG Project Team
|
||||||
|
~
|
||||||
|
~ 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.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
package="org.microg.nlp.app">
|
||||||
|
|
||||||
|
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
|
||||||
|
|
||||||
|
<application
|
||||||
|
android:allowBackup="true"
|
||||||
|
android:icon="@mipmap/ic_nlp_app"
|
||||||
|
android:label="@string/nlp_app_name"
|
||||||
|
android:theme="@style/Theme.AppCompat.DayNight">
|
||||||
|
|
||||||
|
<activity
|
||||||
|
android:name="org.microg.nlp.ui.BackendSettingsActivity"
|
||||||
|
android:process=":ui" />
|
||||||
|
|
||||||
|
<activity
|
||||||
|
android:name="org.microg.nlp.app.SettingsActivity"
|
||||||
|
android:icon="@mipmap/ic_nlp_settings"
|
||||||
|
android:label="@string/nlp_app_name"
|
||||||
|
android:process=":ui">
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.intent.action.MAIN" />
|
||||||
|
<category android:name="android.intent.category.LAUNCHER" />
|
||||||
|
</intent-filter>
|
||||||
|
</activity>
|
||||||
|
|
||||||
|
<activity
|
||||||
|
android:name="org.microg.nlp.app.SelfCheckFragment$AsActivity"
|
||||||
|
android:label="@string/self_check_title"
|
||||||
|
android:process=":ui" />
|
||||||
|
|
||||||
|
<activity
|
||||||
|
android:name="org.microg.nlp.app.AboutFragment$AsActivity"
|
||||||
|
android:label="@string/pref_about_title"
|
||||||
|
android:process=":ui" />
|
||||||
|
</application>
|
||||||
|
</manifest>
|
|
@ -0,0 +1,45 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2013-2017 microG Project Team
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.microg.nlp.app;
|
||||||
|
|
||||||
|
import androidx.fragment.app.Fragment;
|
||||||
|
|
||||||
|
import org.microg.nlp.app.BuildConfig;
|
||||||
|
|
||||||
|
import org.microg.nlp.app.tools.ui.AbstractAboutFragment;
|
||||||
|
import org.microg.nlp.app.tools.ui.AbstractSettingsActivity;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class AboutFragment extends AbstractAboutFragment {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void collectLibraries(List<AbstractAboutFragment.Library> libraries) {
|
||||||
|
libraries.add(new AbstractAboutFragment.Library("org.microg.nlp.service", "UnifiedNlp", "Apache License 2.0, microG Team"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class AsActivity extends AbstractSettingsActivity {
|
||||||
|
public AsActivity() {
|
||||||
|
showHomeAsUp = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Fragment getFragment() {
|
||||||
|
return new AboutFragment();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,22 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2013-2017 microG Project Team
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.microg.nlp.app;
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
|
|
||||||
|
public class LocationSettingsActivity extends Activity {
|
||||||
|
}
|
|
@ -0,0 +1,79 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2013-2017 microG Project Team
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.microg.nlp.app;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.content.pm.PackageManager;
|
||||||
|
import android.content.pm.PermissionGroupInfo;
|
||||||
|
import android.content.pm.PermissionInfo;
|
||||||
|
import android.net.Uri;
|
||||||
|
import android.os.Build;
|
||||||
|
import android.provider.Settings;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.fragment.app.Fragment;
|
||||||
|
|
||||||
|
import org.microg.nlp.app.tools.selfcheck.PermissionCheckGroup;
|
||||||
|
import org.microg.nlp.app.tools.selfcheck.SelfCheckGroup;
|
||||||
|
import org.microg.nlp.app.tools.ui.AbstractSelfCheckFragment;
|
||||||
|
import org.microg.nlp.app.tools.ui.AbstractSettingsActivity;
|
||||||
|
import org.microg.nlp.app.tools.selfcheck.NlpOsCompatChecks;
|
||||||
|
import org.microg.nlp.app.tools.selfcheck.NlpStatusChecks;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import static android.Manifest.permission.ACCESS_COARSE_LOCATION;
|
||||||
|
import static android.os.Build.VERSION.SDK_INT;
|
||||||
|
import static android.os.Build.VERSION_CODES.LOLLIPOP_MR1;
|
||||||
|
|
||||||
|
public class SelfCheckFragment extends AbstractSelfCheckFragment {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void prepareSelfCheckList(List<SelfCheckGroup> checks) {
|
||||||
|
if (SDK_INT > LOLLIPOP_MR1) {
|
||||||
|
checks.add(new PermissionCheckGroup(ACCESS_COARSE_LOCATION));
|
||||||
|
}
|
||||||
|
checks.add(new NlpOsCompatChecks());
|
||||||
|
checks.add(new NlpStatusChecks());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
|
||||||
|
reset(LayoutInflater.from(getContext()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||||
|
reset(LayoutInflater.from(getContext()));
|
||||||
|
super.onActivityResult(requestCode, resultCode, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class AsActivity extends AbstractSettingsActivity {
|
||||||
|
public AsActivity() {
|
||||||
|
showHomeAsUp = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Fragment getFragment() {
|
||||||
|
return new SelfCheckFragment();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,34 @@
|
||||||
|
package org.microg.nlp.app;
|
||||||
|
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.os.Bundle;
|
||||||
|
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
import androidx.appcompat.app.AppCompatActivity;
|
||||||
|
import androidx.navigation.NavController;
|
||||||
|
import androidx.navigation.fragment.NavHostFragment;
|
||||||
|
import androidx.navigation.ui.AppBarConfiguration;
|
||||||
|
import androidx.navigation.ui.NavigationUI;
|
||||||
|
|
||||||
|
public class SettingsActivity extends AppCompatActivity {
|
||||||
|
private AppBarConfiguration appBarConfiguration;
|
||||||
|
|
||||||
|
private NavController getNavController() {
|
||||||
|
return ((NavHostFragment)getSupportFragmentManager().findFragmentById(R.id.navhost)).getNavController();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onCreate(@Nullable Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
|
||||||
|
setContentView(R.layout.settings_root_activity);
|
||||||
|
|
||||||
|
appBarConfiguration = new AppBarConfiguration.Builder(getNavController().getGraph()).build();
|
||||||
|
NavigationUI.setupActionBarWithNavController(this, getNavController(), appBarConfiguration);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onSupportNavigateUp() {
|
||||||
|
return NavigationUI.navigateUp(getNavController(), appBarConfiguration) || super.onSupportNavigateUp();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,112 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2013-2016 microG Project Team
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.microg.nlp.app.tools.selfcheck;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
|
||||||
|
import org.microg.nlp.app.R;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
import static android.os.Build.VERSION.SDK_INT;
|
||||||
|
import static android.os.Build.VERSION_CODES.JELLY_BEAN;
|
||||||
|
import static android.os.Build.VERSION_CODES.JELLY_BEAN_MR1;
|
||||||
|
import static android.os.Build.VERSION_CODES.KITKAT;
|
||||||
|
import static android.os.Build.VERSION_CODES.M;
|
||||||
|
|
||||||
|
public class NlpOsCompatChecks implements SelfCheckGroup {
|
||||||
|
|
||||||
|
public static final String CONFIG_NL_PROVIDER = "config_networkLocationProvider";
|
||||||
|
public static final String CONFIG_NL_PROVIDER_PACKAGE_NAME = "config_networkLocationProviderPackageName";
|
||||||
|
public static final String CONFIG_ENABLE_NL_OVERLAY = "config_enableNetworkLocationOverlay";
|
||||||
|
public static final String CONFIG_NL_PROVIDER_PACKAGE_NAMES = "config_locationProviderPackageNames";
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getGroupName(Context context) {
|
||||||
|
return context.getString(R.string.self_check_cat_nlpcompat);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void doChecks(Context context, ResultCollector collector) {
|
||||||
|
checkSystemIsSupported(context, collector);
|
||||||
|
checkSystemIsConfigured(context, collector);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean checkSystemIsSupported(Context context, ResultCollector collector) {
|
||||||
|
boolean isSupported = (SDK_INT >= KITKAT && SDK_INT <= M);
|
||||||
|
collector.addResult(context.getString(R.string.self_check_name_system_supported),
|
||||||
|
isSupported ? Result.Positive : Result.Unknown, context.getString(R.string.self_check_resolution_system_supported));
|
||||||
|
return isSupported;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean checkSystemIsConfigured(Context context, ResultCollector collector) {
|
||||||
|
// 2.3+ com.android.internal.R.string.config_networkLocationProvider
|
||||||
|
// 4.1+ com.android.internal.R.string.config_networkLocationProviderPackageName
|
||||||
|
// 4.2+ com.android.internal.R.array.config_locationProviderPackageNames
|
||||||
|
// 4.3+ com.android.internal.R.array.config_locationProviderPackageNames /
|
||||||
|
// com.android.internal.R.string.config_networkLocationProviderPackageName /
|
||||||
|
// com.android.internal.R.bool.config_enableNetworkLocationOverlay
|
||||||
|
boolean systemMatchesPackage = false;
|
||||||
|
if (SDK_INT < JELLY_BEAN) {
|
||||||
|
systemMatchesPackage |= context.getPackageName().equals(getResourceString(context, CONFIG_NL_PROVIDER));
|
||||||
|
} else {
|
||||||
|
boolean overlay = getResourceBool(context, CONFIG_ENABLE_NL_OVERLAY);
|
||||||
|
if (SDK_INT < JELLY_BEAN_MR1 || (SDK_INT > JELLY_BEAN_MR1 && !overlay)) {
|
||||||
|
systemMatchesPackage |= context.getPackageName().equals(getResourceString(context, CONFIG_NL_PROVIDER_PACKAGE_NAME));
|
||||||
|
}
|
||||||
|
if (SDK_INT == JELLY_BEAN_MR1 || (SDK_INT > JELLY_BEAN_MR1 && overlay)) {
|
||||||
|
systemMatchesPackage |= Arrays.asList(getResourceArray(context, CONFIG_NL_PROVIDER_PACKAGE_NAMES)).contains(context.getPackageName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
collector.addResult(context.getString(R.string.self_check_name_nlp_package_name),
|
||||||
|
systemMatchesPackage ? Result.Positive : Result.Negative, context.getString(R.string.self_check_resolution_nlp_package_name));
|
||||||
|
return systemMatchesPackage;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String[] getResourceArray(Context context, String identifier) {
|
||||||
|
try {
|
||||||
|
int resId = context.getResources().getIdentifier(identifier, "array", "android");
|
||||||
|
if (resId == 0)
|
||||||
|
resId = context.getResources().getIdentifier(identifier, "array", "com.android.internal");
|
||||||
|
return context.getResources().getStringArray(resId);
|
||||||
|
} catch (Exception e) {
|
||||||
|
return new String[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean getResourceBool(Context context, String identifier) {
|
||||||
|
try {
|
||||||
|
int resId = context.getResources().getIdentifier(identifier, "bool", "android");
|
||||||
|
if (resId == 0)
|
||||||
|
resId = context.getResources().getIdentifier(identifier, "bool", "com.android.internal");
|
||||||
|
return context.getResources().getBoolean(resId);
|
||||||
|
} catch (Exception e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getResourceString(Context context, String identifier) {
|
||||||
|
try {
|
||||||
|
int resId = context.getResources().getIdentifier(identifier, "string", "android");
|
||||||
|
if (resId == 0)
|
||||||
|
resId = context.getResources().getIdentifier(identifier, "string", "com.android.internal");
|
||||||
|
return context.getString(resId);
|
||||||
|
} catch (Exception e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,125 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2013-2016 microG Project Team
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.microg.nlp.app.tools.selfcheck;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.location.Location;
|
||||||
|
import android.location.LocationListener;
|
||||||
|
import android.location.LocationManager;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.text.TextUtils;
|
||||||
|
|
||||||
|
import org.microg.nlp.app.R;
|
||||||
|
import org.microg.nlp.client.UnifiedLocationClient;
|
||||||
|
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
|
||||||
|
import static android.content.Context.LOCATION_SERVICE;
|
||||||
|
import static android.location.LocationManager.NETWORK_PROVIDER;
|
||||||
|
import static org.microg.nlp.api.Constants.LOCATION_EXTRA_BACKEND_COMPONENT;
|
||||||
|
import static org.microg.nlp.app.tools.selfcheck.SelfCheckGroup.Result.Negative;
|
||||||
|
import static org.microg.nlp.app.tools.selfcheck.SelfCheckGroup.Result.Positive;
|
||||||
|
import static org.microg.nlp.app.tools.selfcheck.SelfCheckGroup.Result.Unknown;
|
||||||
|
|
||||||
|
public class NlpStatusChecks implements SelfCheckGroup {
|
||||||
|
@Override
|
||||||
|
public String getGroupName(Context context) {
|
||||||
|
return context.getString(R.string.self_check_cat_nlp_status);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void doChecks(Context context, ResultCollector collector) {
|
||||||
|
providerWasBound(context, collector);
|
||||||
|
if (isNetworkLocationEnabled(context, collector)) {
|
||||||
|
isProvidingLastLocation(context, collector);
|
||||||
|
isProvidingLocation(context, collector);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean providerWasBound(Context context, ResultCollector collector) {
|
||||||
|
collector.addResult(context.getString(R.string.self_check_name_nlp_bound),
|
||||||
|
UnifiedLocationClient.get(context).isAvailable() ? Positive : Negative, context.getString(R.string.self_check_resolution_nlp_bound));
|
||||||
|
return UnifiedLocationClient.get(context).isAvailable();
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isNetworkLocationEnabled(Context context, ResultCollector collector) {
|
||||||
|
LocationManager locationManager = (LocationManager) context.getSystemService(LOCATION_SERVICE);
|
||||||
|
boolean networkEnabled = locationManager.getProviders(true).contains(NETWORK_PROVIDER);
|
||||||
|
collector.addResult(context.getString(R.string.self_check_name_network_enabled),
|
||||||
|
networkEnabled ? Positive : Negative, context.getString(R.string.self_check_resolution_network_enabled));
|
||||||
|
return networkEnabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isProvidingLastLocation(Context context, ResultCollector collector) {
|
||||||
|
LocationManager locationManager = (LocationManager) context.getSystemService(LOCATION_SERVICE);
|
||||||
|
try {
|
||||||
|
Location location = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
|
||||||
|
boolean hasKnown = location != null && location.getExtras() != null &&
|
||||||
|
location.getExtras().containsKey(LOCATION_EXTRA_BACKEND_COMPONENT);
|
||||||
|
collector.addResult(context.getString(R.string.self_check_name_last_location),
|
||||||
|
hasKnown ? Positive : Unknown, context.getString(R.string.self_check_resolution_last_location));
|
||||||
|
return hasKnown;
|
||||||
|
} catch (SecurityException e) {
|
||||||
|
collector.addResult(context.getString(R.string.self_check_name_last_location), Unknown, context.getString(R.string.self_check_loc_perm_missing));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void isProvidingLocation(final Context context, final ResultCollector collector) {
|
||||||
|
final AtomicBoolean result = new AtomicBoolean(false);
|
||||||
|
LocationManager locationManager = (LocationManager) context.getSystemService(LOCATION_SERVICE);
|
||||||
|
new Thread(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
synchronized (result) {
|
||||||
|
try {
|
||||||
|
result.wait(10000);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
}
|
||||||
|
collector.addResult(context.getString(R.string.self_check_name_nlp_is_providing),
|
||||||
|
result.get() ? Positive : Unknown, context.getString(R.string.self_check_resolution_nlp_is_providing));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}).start();
|
||||||
|
try {
|
||||||
|
locationManager.requestSingleUpdate(NETWORK_PROVIDER, new LocationListener() {
|
||||||
|
@Override
|
||||||
|
public void onLocationChanged(Location location) {
|
||||||
|
synchronized (result) {
|
||||||
|
result.set(location != null && location.getExtras() != null &&
|
||||||
|
location.getExtras().containsKey(LOCATION_EXTRA_BACKEND_COMPONENT));
|
||||||
|
result.notifyAll();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onStatusChanged(String provider, int status, Bundle extras) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onProviderEnabled(String provider) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onProviderDisabled(String provider) {
|
||||||
|
}
|
||||||
|
}, null);
|
||||||
|
} catch (SecurityException e) {
|
||||||
|
collector.addResult(context.getString(R.string.self_check_name_last_location), Unknown, context.getString(R.string.self_check_loc_perm_missing));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,69 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2013-2017 microG Project Team
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.microg.nlp.app.tools.selfcheck;
|
||||||
|
|
||||||
|
import android.annotation.TargetApi;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.pm.PackageManager;
|
||||||
|
import android.content.pm.PermissionGroupInfo;
|
||||||
|
import android.content.pm.PermissionInfo;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import androidx.fragment.app.Fragment;
|
||||||
|
|
||||||
|
import org.microg.nlp.app.R;
|
||||||
|
|
||||||
|
import static android.os.Build.VERSION_CODES.M;
|
||||||
|
import static org.microg.nlp.app.tools.selfcheck.SelfCheckGroup.Result.Negative;
|
||||||
|
import static org.microg.nlp.app.tools.selfcheck.SelfCheckGroup.Result.Positive;
|
||||||
|
|
||||||
|
@TargetApi(M)
|
||||||
|
public class PermissionCheckGroup implements SelfCheckGroup {
|
||||||
|
private static final String TAG = "SelfCheckPerms";
|
||||||
|
|
||||||
|
private String[] permissions;
|
||||||
|
|
||||||
|
public PermissionCheckGroup(String... permissions) {
|
||||||
|
this.permissions = permissions;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getGroupName(Context context) {
|
||||||
|
return context.getString(R.string.self_check_cat_permissions);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void doChecks(Context context, ResultCollector collector) {
|
||||||
|
for (String permission : permissions) {
|
||||||
|
doPermissionCheck(context, collector, permission);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void doPermissionCheck(Context context, ResultCollector collector, final String permission) {
|
||||||
|
PackageManager pm = context.getPackageManager();
|
||||||
|
try {
|
||||||
|
PermissionInfo info = pm.getPermissionInfo(permission, 0);
|
||||||
|
CharSequence permLabel = info.loadLabel(pm);
|
||||||
|
collector.addResult(context.getString(R.string.self_check_name_permission, permLabel),
|
||||||
|
context.checkSelfPermission(permission) == PackageManager.PERMISSION_GRANTED ? Positive : Negative,
|
||||||
|
context.getString(R.string.self_check_resolution_permission),
|
||||||
|
fragment -> fragment.requestPermissions(new String[]{permission}, 0));
|
||||||
|
} catch (PackageManager.NameNotFoundException e) {
|
||||||
|
Log.w(TAG, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,41 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2013-2017 microG Project Team
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.microg.nlp.app.tools.selfcheck;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
|
||||||
|
import androidx.fragment.app.Fragment;
|
||||||
|
|
||||||
|
public interface SelfCheckGroup {
|
||||||
|
String getGroupName(Context context);
|
||||||
|
|
||||||
|
void doChecks(Context context, ResultCollector collector);
|
||||||
|
|
||||||
|
interface ResultCollector {
|
||||||
|
void addResult(String name, Result value, String resolution);
|
||||||
|
|
||||||
|
void addResult(String name, Result value, String resolution, CheckResolver resolver);
|
||||||
|
}
|
||||||
|
|
||||||
|
interface CheckResolver {
|
||||||
|
void tryResolve(Fragment fragment);
|
||||||
|
}
|
||||||
|
|
||||||
|
enum Result {
|
||||||
|
Positive, Negative, Unknown
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,151 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2013-2017 microG Project Team
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.microg.nlp.app.tools.ui;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.pm.PackageManager;
|
||||||
|
import android.graphics.drawable.Drawable;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.text.TextUtils;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.ArrayAdapter;
|
||||||
|
import android.widget.ImageView;
|
||||||
|
import android.widget.ListView;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
import androidx.fragment.app.Fragment;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
|
import org.microg.nlp.app.R;
|
||||||
|
|
||||||
|
public abstract class AbstractAboutFragment extends Fragment {
|
||||||
|
|
||||||
|
protected abstract void collectLibraries(List<Library> libraries);
|
||||||
|
|
||||||
|
public static Drawable getIcon(Context context) {
|
||||||
|
try {
|
||||||
|
PackageManager pm = context.getPackageManager();
|
||||||
|
return pm.getPackageInfo(context.getPackageName(), 0).applicationInfo.loadIcon(pm);
|
||||||
|
} catch (PackageManager.NameNotFoundException e) {
|
||||||
|
// Never happens, self package always exists!
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getAppName(Context context) {
|
||||||
|
try {
|
||||||
|
PackageManager pm = context.getPackageManager();
|
||||||
|
CharSequence label = pm.getPackageInfo(context.getPackageName(), 0).applicationInfo.loadLabel(pm);
|
||||||
|
if (TextUtils.isEmpty(label)) return context.getPackageName();
|
||||||
|
return label.toString().trim();
|
||||||
|
} catch (PackageManager.NameNotFoundException e) {
|
||||||
|
// Never happens, self package always exists!
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String getAppName() {
|
||||||
|
return getAppName(getContext());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getLibVersion(String packageName) {
|
||||||
|
try {
|
||||||
|
String versionName = (String) Class.forName(packageName + ".BuildConfig").getField("VERSION_NAME").get(null);
|
||||||
|
if (TextUtils.isEmpty(versionName)) return "";
|
||||||
|
return versionName.trim();
|
||||||
|
} catch (Exception e) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getSelfVersion(Context context) {
|
||||||
|
return getLibVersion(context.getPackageName());
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String getSelfVersion() {
|
||||||
|
return getSelfVersion(getContext());
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String getSummary() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||||
|
View aboutRoot = inflater.inflate(R.layout.about_root, container, false);
|
||||||
|
((ImageView) aboutRoot.findViewById(android.R.id.icon)).setImageDrawable(getIcon(getContext()));
|
||||||
|
((TextView) aboutRoot.findViewById(android.R.id.title)).setText(getAppName());
|
||||||
|
((TextView) aboutRoot.findViewById(R.id.about_version)).setText(getString(R.string.about_version_str, getSelfVersion()));
|
||||||
|
String summary = getSummary();
|
||||||
|
if (summary != null) {
|
||||||
|
((TextView) aboutRoot.findViewById(android.R.id.summary)).setText(summary);
|
||||||
|
aboutRoot.findViewById(android.R.id.summary).setVisibility(View.VISIBLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
List<Library> libraries = new ArrayList<Library>();
|
||||||
|
collectLibraries(libraries);
|
||||||
|
Collections.sort(libraries);
|
||||||
|
((ListView) aboutRoot.findViewById(android.R.id.list)).setAdapter(new LibraryAdapter(getContext(), libraries.toArray(new Library[libraries.size()])));
|
||||||
|
|
||||||
|
return aboutRoot;
|
||||||
|
}
|
||||||
|
|
||||||
|
private class LibraryAdapter extends ArrayAdapter<Library> {
|
||||||
|
|
||||||
|
public LibraryAdapter(Context context, Library[] libraries) {
|
||||||
|
super(context, android.R.layout.simple_list_item_2, android.R.id.text1, libraries);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public View getView(int position, View convertView, ViewGroup parent) {
|
||||||
|
View v = super.getView(position, convertView, parent);
|
||||||
|
((TextView) v.findViewById(android.R.id.text1)).setText(getString(R.string.about_name_version_str, getItem(position).name, getLibVersion(getItem(position).packageName)));
|
||||||
|
((TextView) v.findViewById(android.R.id.text2)).setText(getItem(position).copyright != null ? getItem(position).copyright : getString(R.string.about_default_license));
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static class Library implements Comparable<Library> {
|
||||||
|
private final String packageName;
|
||||||
|
private final String name;
|
||||||
|
private final String copyright;
|
||||||
|
|
||||||
|
public Library(String packageName, String name, String copyright) {
|
||||||
|
this.packageName = packageName;
|
||||||
|
this.name = name;
|
||||||
|
this.copyright = copyright;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return name + ", " + copyright;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int compareTo(Library another) {
|
||||||
|
return name.toLowerCase(Locale.US).compareTo(another.name.toLowerCase(Locale.US));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,130 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2013-2017 microG Project Team
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.microg.nlp.app.tools.ui;
|
||||||
|
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.MotionEvent;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.CheckBox;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
import androidx.fragment.app.Fragment;
|
||||||
|
|
||||||
|
import org.microg.nlp.app.tools.selfcheck.SelfCheckGroup;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import static android.view.View.GONE;
|
||||||
|
import static android.view.View.INVISIBLE;
|
||||||
|
import static org.microg.nlp.app.tools.selfcheck.SelfCheckGroup.Result.Negative;
|
||||||
|
import static org.microg.nlp.app.tools.selfcheck.SelfCheckGroup.Result.Positive;
|
||||||
|
import static org.microg.nlp.app.tools.selfcheck.SelfCheckGroup.Result.Unknown;
|
||||||
|
|
||||||
|
import org.microg.nlp.app.R;
|
||||||
|
|
||||||
|
public abstract class AbstractSelfCheckFragment extends Fragment {
|
||||||
|
private static final String TAG = "SelfCheck";
|
||||||
|
|
||||||
|
private ViewGroup root;
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||||
|
View scrollRoot = inflater.inflate(R.layout.self_check, container, false);
|
||||||
|
root = (ViewGroup) scrollRoot.findViewById(R.id.self_check_root);
|
||||||
|
reset(inflater);
|
||||||
|
return scrollRoot;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract void prepareSelfCheckList(List<SelfCheckGroup> checks);
|
||||||
|
|
||||||
|
protected void reset(LayoutInflater inflater) {
|
||||||
|
List<SelfCheckGroup> selfCheckGroupList = new ArrayList<SelfCheckGroup>();
|
||||||
|
prepareSelfCheckList(selfCheckGroupList);
|
||||||
|
|
||||||
|
root.removeAllViews();
|
||||||
|
for (SelfCheckGroup group : selfCheckGroupList) {
|
||||||
|
View groupView = inflater.inflate(R.layout.self_check_group, root, false);
|
||||||
|
((TextView) groupView.findViewById(android.R.id.title)).setText(group.getGroupName(getContext()));
|
||||||
|
final ViewGroup viewGroup = (ViewGroup) groupView.findViewById(R.id.group_content);
|
||||||
|
final SelfCheckGroup.ResultCollector collector = new GroupResultCollector(viewGroup);
|
||||||
|
try {
|
||||||
|
group.doChecks(getContext(), collector);
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.w(TAG, "Failed during check " + group.getGroupName(getContext()), e);
|
||||||
|
collector.addResult("Self-check failed:", Negative, "An exception occurred during self-check. Please report this issue.");
|
||||||
|
}
|
||||||
|
root.addView(groupView);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class GroupResultCollector implements SelfCheckGroup.ResultCollector {
|
||||||
|
private final ViewGroup viewGroup;
|
||||||
|
|
||||||
|
public GroupResultCollector(ViewGroup viewGroup) {
|
||||||
|
this.viewGroup = viewGroup;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addResult(final String name, final SelfCheckGroup.Result result, final String resolution) {
|
||||||
|
addResult(name, result, resolution, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addResult(final String name, final SelfCheckGroup.Result result, final String resolution,
|
||||||
|
final SelfCheckGroup.CheckResolver resolver) {
|
||||||
|
if (result == null || getActivity() == null) return;
|
||||||
|
getActivity().runOnUiThread(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
View resultEntry = LayoutInflater.from(getContext()).inflate(R.layout.self_check_entry, viewGroup, false);
|
||||||
|
((TextView) resultEntry.findViewById(R.id.self_check_name)).setText(name);
|
||||||
|
resultEntry.findViewById(R.id.self_check_result).setOnTouchListener(new View.OnTouchListener() {
|
||||||
|
@Override
|
||||||
|
public boolean onTouch(View v, MotionEvent event) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (result == Positive) {
|
||||||
|
((CheckBox) resultEntry.findViewById(R.id.self_check_result)).setChecked(true);
|
||||||
|
resultEntry.findViewById(R.id.self_check_resolution).setVisibility(GONE);
|
||||||
|
} else {
|
||||||
|
((TextView) resultEntry.findViewById(R.id.self_check_resolution)).setText(resolution);
|
||||||
|
if (result == Unknown) {
|
||||||
|
resultEntry.findViewById(R.id.self_check_result).setVisibility(INVISIBLE);
|
||||||
|
}
|
||||||
|
if (resolver != null) {
|
||||||
|
resultEntry.setClickable(true);
|
||||||
|
resultEntry.setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
resolver.tryResolve(AbstractSelfCheckFragment.this);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
viewGroup.addView(resultEntry);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,78 @@
|
||||||
|
package org.microg.nlp.app.tools.ui;
|
||||||
|
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.view.MenuItem;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
|
||||||
|
import androidx.appcompat.app.AppCompatActivity;
|
||||||
|
import androidx.fragment.app.Fragment;
|
||||||
|
import androidx.fragment.app.FragmentTransaction;
|
||||||
|
import org.microg.nlp.app.R;
|
||||||
|
|
||||||
|
public abstract class AbstractSettingsActivity extends AppCompatActivity {
|
||||||
|
protected boolean showHomeAsUp = false;
|
||||||
|
protected int preferencesResource = 0;
|
||||||
|
private ViewGroup customBarContainer;
|
||||||
|
protected int customBarLayout = 0;
|
||||||
|
protected SwitchBar switchBar;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
setContentView(R.layout.settings_activity);
|
||||||
|
if (showHomeAsUp) {
|
||||||
|
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
switchBar = (SwitchBar) findViewById(R.id.switch_bar);
|
||||||
|
|
||||||
|
customBarContainer = (ViewGroup) findViewById(R.id.custom_bar);
|
||||||
|
if (customBarLayout != 0) {
|
||||||
|
customBarContainer.addView(getLayoutInflater().inflate(customBarLayout, customBarContainer, false));
|
||||||
|
}
|
||||||
|
|
||||||
|
getSupportFragmentManager().beginTransaction()
|
||||||
|
.replace(R.id.content_wrapper, getFragment())
|
||||||
|
.commit();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCustomBarLayout(int layout) {
|
||||||
|
customBarLayout = layout;
|
||||||
|
if (customBarContainer != null) {
|
||||||
|
customBarContainer.removeAllViews();
|
||||||
|
customBarContainer.addView(getLayoutInflater().inflate(customBarLayout, customBarContainer, false));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public SwitchBar getSwitchBar() {
|
||||||
|
return switchBar;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void replaceFragment(Fragment fragment) {
|
||||||
|
getSupportFragmentManager().beginTransaction()
|
||||||
|
.addToBackStack("root")
|
||||||
|
.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN)
|
||||||
|
.replace(R.id.content_wrapper, fragment)
|
||||||
|
.commit();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onOptionsItemSelected(MenuItem item) {
|
||||||
|
if (item.getItemId() == android.R.id.home) {
|
||||||
|
finish();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return super.onOptionsItemSelected(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Fragment getFragment() {
|
||||||
|
if (preferencesResource == 0) {
|
||||||
|
throw new IllegalStateException("Neither preferencesResource given, nor overriden getFragment()");
|
||||||
|
}
|
||||||
|
ResourceSettingsFragment fragment = new ResourceSettingsFragment();
|
||||||
|
Bundle b = new Bundle();
|
||||||
|
b.putInt(ResourceSettingsFragment.EXTRA_PREFERENCE_RESOURCE, preferencesResource);
|
||||||
|
fragment.setArguments(b);
|
||||||
|
return fragment;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,38 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2013-2017 microG Project Team
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.microg.nlp.app.tools.ui;
|
||||||
|
|
||||||
|
import androidx.fragment.app.DialogFragment;
|
||||||
|
import androidx.preference.Preference;
|
||||||
|
import androidx.preference.PreferenceFragmentCompat;
|
||||||
|
|
||||||
|
public abstract class AbstractSettingsFragment extends PreferenceFragmentCompat {
|
||||||
|
private static final String TAG = AbstractSettingsFragment.class.getSimpleName();
|
||||||
|
|
||||||
|
private static final String DIALOG_FRAGMENT_TAG = "androidx.preference.PreferenceFragment.DIALOG";
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDisplayPreferenceDialog(Preference preference) {
|
||||||
|
if (preference instanceof DialogPreference) {
|
||||||
|
DialogFragment f = DialogPreference.DialogPreferenceCompatDialogFragment.newInstance(preference.getKey());
|
||||||
|
f.setTargetFragment(this, 0);
|
||||||
|
f.show(getFragmentManager(), DIALOG_FRAGMENT_TAG);
|
||||||
|
} else {
|
||||||
|
super.onDisplayPreferenceDialog(preference);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,116 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2013-2017 microG Project Team
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.microg.nlp.app.tools.ui;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.SharedPreferences;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.util.AttributeSet;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.LinearLayout;
|
||||||
|
|
||||||
|
import androidx.fragment.app.DialogFragment;
|
||||||
|
import androidx.preference.Preference;
|
||||||
|
import androidx.preference.PreferenceDialogFragmentCompat;
|
||||||
|
import androidx.preference.PreferenceFragmentCompat;
|
||||||
|
import androidx.preference.PreferenceViewHolder;
|
||||||
|
|
||||||
|
import org.microg.nlp.app.R;
|
||||||
|
|
||||||
|
public class DialogPreference extends androidx.preference.DialogPreference implements PreferenceFragmentCompat.OnPreferenceDisplayDialogCallback {
|
||||||
|
|
||||||
|
private static final String DIALOG_FRAGMENT_TAG =
|
||||||
|
"android.support.v7.preference.PreferenceFragment.DIALOG";
|
||||||
|
|
||||||
|
public DialogPreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
|
||||||
|
super(context, attrs, defStyleAttr, defStyleRes);
|
||||||
|
}
|
||||||
|
|
||||||
|
public DialogPreference(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||||
|
super(context, attrs, defStyleAttr);
|
||||||
|
}
|
||||||
|
|
||||||
|
public DialogPreference(Context context, AttributeSet attrs) {
|
||||||
|
super(context, attrs);
|
||||||
|
}
|
||||||
|
|
||||||
|
public DialogPreference(Context context) {
|
||||||
|
super(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected View onCreateDialogView() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when the dialog is dismissed and should be used to save data to
|
||||||
|
* the {@link SharedPreferences}.
|
||||||
|
*
|
||||||
|
* @param positiveResult Whether the positive button was clicked (true), or
|
||||||
|
* the negative button was clicked or the dialog was canceled (false).
|
||||||
|
*/
|
||||||
|
protected void onDialogClosed(boolean positiveResult) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onPreferenceDisplayDialog(PreferenceFragmentCompat caller, Preference pref) {
|
||||||
|
DialogPreferenceCompatDialogFragment fragment = new DialogPreferenceCompatDialogFragment();
|
||||||
|
fragment.setTargetFragment(caller, 0);
|
||||||
|
fragment.show(caller.getFragmentManager(), DIALOG_FRAGMENT_TAG);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onBindViewHolder(PreferenceViewHolder view) {
|
||||||
|
super.onBindViewHolder(view);
|
||||||
|
|
||||||
|
ViewGroup.LayoutParams layoutParams = view.findViewById(R.id.icon_frame).getLayoutParams();
|
||||||
|
if (layoutParams instanceof LinearLayout.LayoutParams) {
|
||||||
|
if (((LinearLayout.LayoutParams) layoutParams).leftMargin < 0) {
|
||||||
|
((LinearLayout.LayoutParams) layoutParams).leftMargin = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class DialogPreferenceCompatDialogFragment extends PreferenceDialogFragmentCompat {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected View onCreateDialogView(Context context) {
|
||||||
|
if (getPreference() instanceof DialogPreference) {
|
||||||
|
View view = ((DialogPreference) getPreference()).onCreateDialogView();
|
||||||
|
if (view != null) return view;
|
||||||
|
}
|
||||||
|
return super.onCreateDialogView(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDialogClosed(boolean positiveResult) {
|
||||||
|
if (getPreference() instanceof DialogPreference) {
|
||||||
|
((DialogPreference) getPreference()).onDialogClosed(positiveResult);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static DialogFragment newInstance(String key) {
|
||||||
|
final DialogPreferenceCompatDialogFragment fragment = new DialogPreferenceCompatDialogFragment();
|
||||||
|
final Bundle b = new Bundle(1);
|
||||||
|
b.putString(ARG_KEY, key);
|
||||||
|
fragment.setArguments(b);
|
||||||
|
return fragment;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,39 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2017 microG Project Team
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.microg.nlp.app.tools.ui;
|
||||||
|
|
||||||
|
import android.os.Bundle;
|
||||||
|
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
|
public class ResourceSettingsFragment extends AbstractSettingsFragment {
|
||||||
|
|
||||||
|
public static final String EXTRA_PREFERENCE_RESOURCE = "preferencesResource";
|
||||||
|
|
||||||
|
protected int preferencesResource;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCreatePreferences(@Nullable Bundle savedInstanceState, String rootKey) {
|
||||||
|
Bundle b = getArguments();
|
||||||
|
if (b != null) {
|
||||||
|
preferencesResource = b.getInt(EXTRA_PREFERENCE_RESOURCE, preferencesResource);
|
||||||
|
}
|
||||||
|
if (preferencesResource != 0) {
|
||||||
|
addPreferencesFromResource(preferencesResource);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,266 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2014 The Android Open Source Project
|
||||||
|
* Copyright (C) 2014-2017 microG Project Team
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.microg.nlp.app.tools.ui;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.os.Build;
|
||||||
|
import android.os.Parcel;
|
||||||
|
import android.os.Parcelable;
|
||||||
|
import android.text.SpannableStringBuilder;
|
||||||
|
import android.text.TextUtils;
|
||||||
|
import android.text.style.TextAppearanceSpan;
|
||||||
|
import android.util.AttributeSet;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.widget.CompoundButton;
|
||||||
|
import android.widget.LinearLayout;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import androidx.appcompat.widget.SwitchCompat;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
import static android.os.Build.VERSION.SDK_INT;
|
||||||
|
import org.microg.nlp.app.R;
|
||||||
|
|
||||||
|
public class SwitchBar extends LinearLayout implements CompoundButton.OnCheckedChangeListener,
|
||||||
|
View.OnClickListener {
|
||||||
|
|
||||||
|
public static interface OnSwitchChangeListener {
|
||||||
|
/**
|
||||||
|
* Called when the checked state of the Switch has changed.
|
||||||
|
*
|
||||||
|
* @param switchView The Switch view whose state has changed.
|
||||||
|
* @param isChecked The new checked state of switchView.
|
||||||
|
*/
|
||||||
|
void onSwitchChanged(SwitchCompat switchView, boolean isChecked);
|
||||||
|
}
|
||||||
|
|
||||||
|
private final TextAppearanceSpan mSummarySpan;
|
||||||
|
|
||||||
|
private ToggleSwitch mSwitch;
|
||||||
|
private TextView mTextView;
|
||||||
|
private String mLabel;
|
||||||
|
private String mSummary;
|
||||||
|
|
||||||
|
private ArrayList<OnSwitchChangeListener> mSwitchChangeListeners =
|
||||||
|
new ArrayList<OnSwitchChangeListener>();
|
||||||
|
|
||||||
|
public SwitchBar(Context context) {
|
||||||
|
this(context, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public SwitchBar(Context context, AttributeSet attrs) {
|
||||||
|
super(context, attrs);
|
||||||
|
|
||||||
|
LayoutInflater.from(context).inflate(R.layout.switch_bar, this);
|
||||||
|
|
||||||
|
mTextView = (TextView) findViewById(R.id.switch_text);
|
||||||
|
if (SDK_INT > Build.VERSION_CODES.JELLY_BEAN) {
|
||||||
|
mTextView.setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_NO);
|
||||||
|
}
|
||||||
|
mLabel = getResources().getString(R.string.abc_capital_off);
|
||||||
|
mSummarySpan = new TextAppearanceSpan(context, androidx.appcompat.R.style.TextAppearance_AppCompat_Widget_Switch);
|
||||||
|
updateText();
|
||||||
|
|
||||||
|
mSwitch = (ToggleSwitch) findViewById(R.id.switch_widget);
|
||||||
|
// Prevent onSaveInstanceState() to be called as we are managing the state of the Switch
|
||||||
|
// on our own
|
||||||
|
mSwitch.setSaveEnabled(false);
|
||||||
|
if (SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
|
||||||
|
mSwitch.setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_NO);
|
||||||
|
}
|
||||||
|
|
||||||
|
addOnSwitchChangeListener(new OnSwitchChangeListener() {
|
||||||
|
@Override
|
||||||
|
public void onSwitchChanged(SwitchCompat switchView, boolean isChecked) {
|
||||||
|
setTextViewLabel(isChecked);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
setOnClickListener(this);
|
||||||
|
|
||||||
|
// Default is hide
|
||||||
|
setVisibility(View.GONE);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTextViewLabel(boolean isChecked) {
|
||||||
|
mLabel = getResources()
|
||||||
|
.getString(isChecked ? R.string.abc_capital_on : R.string.abc_capital_off);
|
||||||
|
updateText();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSummary(String summary) {
|
||||||
|
mSummary = summary;
|
||||||
|
updateText();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateText() {
|
||||||
|
if (TextUtils.isEmpty(mSummary)) {
|
||||||
|
mTextView.setText(mLabel);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
final SpannableStringBuilder ssb = new SpannableStringBuilder(mLabel).append('\n');
|
||||||
|
final int start = ssb.length();
|
||||||
|
ssb.append(mSummary);
|
||||||
|
ssb.setSpan(mSummarySpan, start, ssb.length(), 0);
|
||||||
|
mTextView.setText(ssb);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setChecked(boolean checked) {
|
||||||
|
setTextViewLabel(checked);
|
||||||
|
mSwitch.setChecked(checked);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCheckedInternal(boolean checked) {
|
||||||
|
setTextViewLabel(checked);
|
||||||
|
mSwitch.setCheckedInternal(checked);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isChecked() {
|
||||||
|
return mSwitch.isChecked();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setEnabled(boolean enabled) {
|
||||||
|
super.setEnabled(enabled);
|
||||||
|
mTextView.setEnabled(enabled);
|
||||||
|
mSwitch.setEnabled(enabled);
|
||||||
|
}
|
||||||
|
|
||||||
|
public final ToggleSwitch getSwitch() {
|
||||||
|
return mSwitch;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void show() {
|
||||||
|
if (!isShowing()) {
|
||||||
|
setVisibility(View.VISIBLE);
|
||||||
|
mSwitch.setOnCheckedChangeListener(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void hide() {
|
||||||
|
if (isShowing()) {
|
||||||
|
setVisibility(View.GONE);
|
||||||
|
mSwitch.setOnCheckedChangeListener(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isShowing() {
|
||||||
|
return (getVisibility() == View.VISIBLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
final boolean isChecked = !mSwitch.isChecked();
|
||||||
|
setChecked(isChecked);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void propagateChecked(boolean isChecked) {
|
||||||
|
final int count = mSwitchChangeListeners.size();
|
||||||
|
for (int n = 0; n < count; n++) {
|
||||||
|
mSwitchChangeListeners.get(n).onSwitchChanged(mSwitch, isChecked);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
|
||||||
|
propagateChecked(isChecked);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addOnSwitchChangeListener(OnSwitchChangeListener listener) {
|
||||||
|
if (mSwitchChangeListeners.contains(listener)) {
|
||||||
|
throw new IllegalStateException("Cannot add twice the same OnSwitchChangeListener");
|
||||||
|
}
|
||||||
|
mSwitchChangeListeners.add(listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeOnSwitchChangeListener(OnSwitchChangeListener listener) {
|
||||||
|
if (!mSwitchChangeListeners.contains(listener)) {
|
||||||
|
throw new IllegalStateException("Cannot remove OnSwitchChangeListener");
|
||||||
|
}
|
||||||
|
mSwitchChangeListeners.remove(listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
static class SavedState extends BaseSavedState {
|
||||||
|
boolean checked;
|
||||||
|
boolean visible;
|
||||||
|
|
||||||
|
SavedState(Parcelable superState) {
|
||||||
|
super(superState);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor called from {@link #CREATOR}
|
||||||
|
*/
|
||||||
|
private SavedState(Parcel in) {
|
||||||
|
super(in);
|
||||||
|
checked = (Boolean) in.readValue(Boolean.class.getClassLoader());
|
||||||
|
visible = (Boolean) in.readValue(Boolean.class.getClassLoader());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void writeToParcel(Parcel out, int flags) {
|
||||||
|
super.writeToParcel(out, flags);
|
||||||
|
out.writeValue(checked);
|
||||||
|
out.writeValue(visible);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "SwitchBar.SavedState{"
|
||||||
|
+ Integer.toHexString(System.identityHashCode(this))
|
||||||
|
+ " checked=" + checked
|
||||||
|
+ " visible=" + visible + "}";
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final Parcelable.Creator<SavedState> CREATOR
|
||||||
|
= new Parcelable.Creator<SavedState>() {
|
||||||
|
public SavedState createFromParcel(Parcel in) {
|
||||||
|
return new SavedState(in);
|
||||||
|
}
|
||||||
|
|
||||||
|
public SavedState[] newArray(int size) {
|
||||||
|
return new SavedState[size];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Parcelable onSaveInstanceState() {
|
||||||
|
Parcelable superState = super.onSaveInstanceState();
|
||||||
|
|
||||||
|
SavedState ss = new SavedState(superState);
|
||||||
|
ss.checked = mSwitch.isChecked();
|
||||||
|
ss.visible = isShowing();
|
||||||
|
return ss;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onRestoreInstanceState(Parcelable state) {
|
||||||
|
SavedState ss = (SavedState) state;
|
||||||
|
|
||||||
|
super.onRestoreInstanceState(ss.getSuperState());
|
||||||
|
|
||||||
|
mSwitch.setCheckedInternal(ss.checked);
|
||||||
|
setTextViewLabel(ss.checked);
|
||||||
|
setVisibility(ss.visible ? View.VISIBLE : View.GONE);
|
||||||
|
mSwitch.setOnCheckedChangeListener(ss.visible ? this : null);
|
||||||
|
|
||||||
|
requestLayout();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,63 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2014 The Android Open Source Project
|
||||||
|
* Copyright (C) 2014-2017 microG Project Team
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.microg.nlp.app.tools.ui;
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.util.AttributeSet;
|
||||||
|
|
||||||
|
import androidx.appcompat.widget.SwitchCompat;
|
||||||
|
|
||||||
|
@SuppressLint("NewApi")
|
||||||
|
public class ToggleSwitch extends SwitchCompat {
|
||||||
|
|
||||||
|
private ToggleSwitch.OnBeforeCheckedChangeListener mOnBeforeListener;
|
||||||
|
|
||||||
|
public interface OnBeforeCheckedChangeListener {
|
||||||
|
boolean onBeforeCheckedChanged(ToggleSwitch toggleSwitch, boolean checked);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ToggleSwitch(Context context) {
|
||||||
|
super(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ToggleSwitch(Context context, AttributeSet attrs) {
|
||||||
|
super(context, attrs);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ToggleSwitch(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||||
|
super(context, attrs, defStyleAttr);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOnBeforeCheckedChangeListener(OnBeforeCheckedChangeListener listener) {
|
||||||
|
mOnBeforeListener = listener;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setChecked(boolean checked) {
|
||||||
|
if (mOnBeforeListener != null
|
||||||
|
&& mOnBeforeListener.onBeforeCheckedChanged(this, checked)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
super.setChecked(checked);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCheckedInternal(boolean checked) {
|
||||||
|
super.setChecked(checked);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,50 @@
|
||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2020, microG Project Team
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.microg.nlp.app
|
||||||
|
|
||||||
|
import android.os.Bundle
|
||||||
|
import androidx.lifecycle.lifecycleScope
|
||||||
|
import androidx.navigation.fragment.findNavController
|
||||||
|
import androidx.preference.Preference
|
||||||
|
import org.microg.nlp.client.UnifiedLocationClient
|
||||||
|
import org.microg.nlp.app.tools.ui.ResourceSettingsFragment
|
||||||
|
import org.microg.nlp.ui.navigate
|
||||||
|
|
||||||
|
class SettingsFragment : ResourceSettingsFragment() {
|
||||||
|
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
|
||||||
|
super.onCreatePreferences(savedInstanceState, rootKey)
|
||||||
|
|
||||||
|
findPreference<Preference>(PREF_UNIFIEDNLP)!!.onPreferenceClickListener = Preference.OnPreferenceClickListener {
|
||||||
|
findNavController().navigate(requireContext(), R.id.openUnifiedNlpSettings)
|
||||||
|
true
|
||||||
|
}
|
||||||
|
findPreference<Preference>(PREF_ABOUT)!!.onPreferenceClickListener = Preference.OnPreferenceClickListener {
|
||||||
|
findNavController().navigate(requireContext(), R.id.openAbout)
|
||||||
|
true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onResume() {
|
||||||
|
super.onResume()
|
||||||
|
lifecycleScope.launchWhenResumed {
|
||||||
|
updateDetails()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private suspend fun updateDetails() {
|
||||||
|
val backendCount = UnifiedLocationClient[requireContext()].getLocationBackends().size + UnifiedLocationClient[requireContext()].getGeocoderBackends().size
|
||||||
|
findPreference<Preference>(PREF_UNIFIEDNLP)!!.summary = resources.getQuantityString(R.plurals.pref_unifiednlp_summary, backendCount, backendCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
const val PREF_ABOUT = "pref_about"
|
||||||
|
const val PREF_UNIFIEDNLP = "pref_unifiednlp"
|
||||||
|
}
|
||||||
|
|
||||||
|
init {
|
||||||
|
preferencesResource = R.xml.preferences_start
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,17 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!--
|
||||||
|
~ SPDX-FileCopyrightText: 2019, The Android Open Source Project
|
||||||
|
~ SPDX-FileCopyrightText: 2020, microG Project Team
|
||||||
|
~ SPDX-License-Identifier: Apache-2.0
|
||||||
|
-->
|
||||||
|
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:tint="?attr/colorAccent"
|
||||||
|
android:viewportWidth="24.0"
|
||||||
|
android:viewportHeight="24.0">
|
||||||
|
<path
|
||||||
|
android:fillColor="#FF000000"
|
||||||
|
android:pathData="M11,17h2v-6h-2v6zM12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM12,20c-4.41,0 -8,-3.59 -8,-8s3.59,-8 8,-8 8,3.59 8,8 -3.59,8 -8,8zM11,9h2L13,7h-2v2z" />
|
||||||
|
</vector>
|
|
@ -0,0 +1,17 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!--
|
||||||
|
~ SPDX-FileCopyrightText: 2019, The Android Open Source Project
|
||||||
|
~ SPDX-FileCopyrightText: 2020, microG Project Team
|
||||||
|
~ SPDX-License-Identifier: Apache-2.0
|
||||||
|
-->
|
||||||
|
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:tint="?attr/colorAccent"
|
||||||
|
android:viewportWidth="24"
|
||||||
|
android:viewportHeight="24">
|
||||||
|
<path
|
||||||
|
android:fillColor="#FF000000"
|
||||||
|
android:pathData="M12,11.5A2.5,2.5 0 0,1 9.5,9A2.5,2.5 0 0,1 12,6.5A2.5,2.5 0 0,1 14.5,9A2.5,2.5 0 0,1 12,11.5M12,2A7,7 0 0,0 5,9C5,14.25 12,22 12,22C12,22 19,14.25 19,9A7,7 0 0,0 12,2Z" />
|
||||||
|
</vector>
|
|
@ -0,0 +1,28 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!--
|
||||||
|
~ Copyright (C) 2013-2017 microG Project Team
|
||||||
|
~
|
||||||
|
~ 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.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:tint="?attr/colorAccent"
|
||||||
|
android:viewportWidth="24"
|
||||||
|
android:viewportHeight="24">
|
||||||
|
|
||||||
|
<path
|
||||||
|
android:fillColor="#FF000000"
|
||||||
|
android:pathData="M14,10H2V12H14V10M14,6H2V8H14V6M2,16H10V14H2V16M21.5,11.5L23,13L16,20L11.5,15.5L13,14L16,17L21.5,11.5Z" />
|
||||||
|
</vector>
|
|
@ -0,0 +1,77 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!--
|
||||||
|
~ Copyright (C) 2013-2017 microG Project Team
|
||||||
|
~
|
||||||
|
~ 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.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<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"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@android:id/icon"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center_horizontal"
|
||||||
|
android:padding="10dp"
|
||||||
|
android:src="@android:drawable/ic_dialog_alert"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@android:id/title"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center_horizontal"
|
||||||
|
android:text="@string/about_root_title"
|
||||||
|
android:textAppearance="@style/TextAppearance.AppCompat.Headline"
|
||||||
|
android:textColor="?attr/colorAccent"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@android:id/summary"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center_horizontal"
|
||||||
|
android:visibility="gone"
|
||||||
|
android:text="@string/about_root_summary"
|
||||||
|
android:textAppearance="@style/TextAppearance.AppCompat.Subhead"
|
||||||
|
android:textColor="?attr/colorAccent"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/about_version"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center_horizontal"
|
||||||
|
android:text="@string/about_root_version"
|
||||||
|
android:textAppearance="@style/TextAppearance.AppCompat.Subhead"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@android:id/title"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginBottom="16dip"
|
||||||
|
android:paddingLeft="?attr/listPreferredItemPaddingLeft"
|
||||||
|
android:paddingRight="?attr/listPreferredItemPaddingRight"
|
||||||
|
android:paddingTop="16dip"
|
||||||
|
android:textAppearance="@style/TextAppearance.AppCompat.Body2"
|
||||||
|
android:text="@string/about_root_libraries"
|
||||||
|
android:textColor="?attr/colorAccent"/>
|
||||||
|
|
||||||
|
<ListView
|
||||||
|
android:id="@android:id/list"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="0dip"
|
||||||
|
android:layout_weight="1"
|
||||||
|
tools:listitem="@android:layout/simple_list_item_2"/>
|
||||||
|
</LinearLayout>
|
|
@ -0,0 +1,20 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!--
|
||||||
|
Copyright (C) 2016 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.
|
||||||
|
-->
|
||||||
|
<Space xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="0dp" />
|
||||||
|
|
|
@ -0,0 +1,30 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!--
|
||||||
|
~ Copyright (C) 2013-2017 microG Project Team
|
||||||
|
~
|
||||||
|
~ 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.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<ScrollView
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/self_check_root"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
</ScrollView>
|
|
@ -0,0 +1,58 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!--
|
||||||
|
~ Copyright (C) 2013-2017 microG Project Team
|
||||||
|
~
|
||||||
|
~ 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.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="?attr/selectableItemBackground"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:paddingBottom="5dp"
|
||||||
|
android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
|
||||||
|
android:paddingLeft="?attr/listPreferredItemPaddingLeft"
|
||||||
|
android:paddingRight="?attr/listPreferredItemPaddingRight"
|
||||||
|
android:paddingStart="?android:attr/listPreferredItemPaddingStart">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="0dip"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/self_check_name"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:textAppearance="?attr/textAppearanceListItem"
|
||||||
|
android:textColor="?android:textColorPrimary"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/self_check_resolution"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:textAppearance="@style/TextAppearance.AppCompat.Body1"
|
||||||
|
android:textColor="?android:textColorSecondary"/>
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<CheckBox
|
||||||
|
android:id="@+id/self_check_result"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:focusable="false"
|
||||||
|
android:gravity="right|center_vertical"
|
||||||
|
android:paddingTop="5dp"/>
|
||||||
|
</LinearLayout>
|
|
@ -0,0 +1,40 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!--
|
||||||
|
~ Copyright (C) 2013-2017 microG Project Team
|
||||||
|
~
|
||||||
|
~ 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.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@android:id/title"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginBottom="16dip"
|
||||||
|
android:paddingLeft="?attr/listPreferredItemPaddingLeft"
|
||||||
|
android:paddingRight="?attr/listPreferredItemPaddingRight"
|
||||||
|
android:paddingTop="16dip"
|
||||||
|
android:textAppearance="@style/TextAppearance.AppCompat.Body2"
|
||||||
|
android:textColor="?attr/colorAccent"/>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/group_content"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical"/>
|
||||||
|
|
||||||
|
</LinearLayout>
|
|
@ -0,0 +1,40 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?><!--
|
||||||
|
~ Copyright (C) 2013-2017 microG Project Team
|
||||||
|
~
|
||||||
|
~ 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.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<org.microg.nlp.app.tools.ui.SwitchBar
|
||||||
|
android:id="@+id/switch_bar"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="?attr/actionBarSize"
|
||||||
|
android:background="@color/switchbar_background_color"
|
||||||
|
android:visibility="gone"/>
|
||||||
|
|
||||||
|
<FrameLayout
|
||||||
|
android:id="@+id/custom_bar"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"/>
|
||||||
|
|
||||||
|
<FrameLayout
|
||||||
|
android:id="@+id/content_wrapper"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="0dp"
|
||||||
|
android:layout_weight="1"/>
|
||||||
|
|
||||||
|
</LinearLayout>
|
|
@ -0,0 +1,19 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!--
|
||||||
|
~ SPDX-FileCopyrightText: 2020, microG Project Team
|
||||||
|
~ SPDX-License-Identifier: Apache-2.0
|
||||||
|
-->
|
||||||
|
<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.fragment.app.FragmentContainerView
|
||||||
|
android:id="@+id/navhost"
|
||||||
|
android:name="androidx.navigation.fragment.NavHostFragment"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
app:defaultNavHost="true"
|
||||||
|
app:navGraph="@navigation/nav_settings" />
|
||||||
|
</LinearLayout>
|
|
@ -0,0 +1,43 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!--
|
||||||
|
~ Copyright (C) 2014 The Android Open Source Project
|
||||||
|
~ Copyright (C) 2014-2017 microG Project Team
|
||||||
|
~
|
||||||
|
~ 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.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<merge xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/switch_text"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="start|center_vertical"
|
||||||
|
android:layout_marginLeft="72dp"
|
||||||
|
android:layout_marginStart="72dp"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:ellipsize="end"
|
||||||
|
android:maxLines="2"
|
||||||
|
android:text="@string/v7_preference_on"
|
||||||
|
android:theme="@style/TextAppearance.AppCompat.Title.Inverse"/>
|
||||||
|
|
||||||
|
<org.microg.nlp.app.tools.ui.ToggleSwitch
|
||||||
|
android:id="@+id/switch_widget"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center_vertical"
|
||||||
|
android:layout_marginEnd="16dp"
|
||||||
|
android:layout_marginRight="16dp"
|
||||||
|
android:background="@null"/>
|
||||||
|
|
||||||
|
</merge>
|
After Width: | Height: | Size: 2.5 KiB |
After Width: | Height: | Size: 4.2 KiB |
After Width: | Height: | Size: 1.7 KiB |
After Width: | Height: | Size: 2.4 KiB |
After Width: | Height: | Size: 3.4 KiB |
After Width: | Height: | Size: 5.9 KiB |
After Width: | Height: | Size: 5.4 KiB |
After Width: | Height: | Size: 9.9 KiB |
After Width: | Height: | Size: 7.9 KiB |
After Width: | Height: | Size: 14 KiB |
|
@ -0,0 +1,34 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<navigation 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"
|
||||||
|
app:startDestination="@id/settingsFragment">
|
||||||
|
|
||||||
|
<fragment
|
||||||
|
android:id="@+id/settingsFragment"
|
||||||
|
android:name="org.microg.nlp.app.SettingsFragment"
|
||||||
|
android:label="@string/nlp_settings_label">
|
||||||
|
<action
|
||||||
|
android:id="@+id/openSelfcheck"
|
||||||
|
app:destination="@id/selfcheckFragment" />
|
||||||
|
<action
|
||||||
|
android:id="@+id/openUnifiedNlpSettings"
|
||||||
|
app:destination="@id/nav_unlp" />
|
||||||
|
<action
|
||||||
|
android:id="@+id/openAbout"
|
||||||
|
app:destination="@id/aboutFragment" />
|
||||||
|
</fragment>
|
||||||
|
|
||||||
|
<fragment
|
||||||
|
android:id="@+id/selfcheckFragment"
|
||||||
|
android:name="org.microg.nlp.app.SelfCheckFragment"
|
||||||
|
android:label="self_check_title" />
|
||||||
|
|
||||||
|
<include app:graph="@navigation/nav_unlp" />
|
||||||
|
|
||||||
|
<fragment
|
||||||
|
android:id="@+id/aboutFragment"
|
||||||
|
android:name="org.microg.nlp.app.AboutFragment"
|
||||||
|
android:label="@string/prefcat_about"
|
||||||
|
tools:layout="@layout/about_root" />
|
||||||
|
</navigation>
|
|
@ -0,0 +1,20 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?><!--
|
||||||
|
~ Copyright 2013-2016 microG Project Team
|
||||||
|
~
|
||||||
|
~ 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.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<resources>
|
||||||
|
<string name="nlp_app_name">UnifiedNlp</string>
|
||||||
|
<string name="nlp_settings_label">Ustawienia UnifiedNlp</string>
|
||||||
|
</resources>
|
|
@ -0,0 +1,20 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?><!--
|
||||||
|
~ Copyright 2013-2016 microG Project Team
|
||||||
|
~
|
||||||
|
~ 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.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<resources>
|
||||||
|
<string name="nlp_app_name">Nlp Unificat</string>
|
||||||
|
<string name="nlp_settings_label">Setări Nlp Unificat</string>
|
||||||
|
</resources>
|
|
@ -0,0 +1,42 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?><!--
|
||||||
|
~ Copyright 2013-2016 microG Project Team
|
||||||
|
~
|
||||||
|
~ 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.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<resources>
|
||||||
|
<string name="nlp_app_name">Обједињени МПЛ</string>
|
||||||
|
<string name="nlp_settings_label">Поставке Обједињеног МПЛ</string>
|
||||||
|
|
||||||
|
<string name="self_check_cat_nlpcompat">Подршка за Мрежне Провајдере Локације</string>
|
||||||
|
<string name="self_check_name_system_supported">Издање Андроида подржано:</string>
|
||||||
|
<string name="self_check_resolution_system_supported">Ваше издање Андроида није службено подржано. Ово нужно не мора да значи ништа.</string>
|
||||||
|
<string name="self_check_name_nlp_package_name">Систем подржава провајдере локације:</string>
|
||||||
|
<string name="self_check_resolution_nlp_package_name">Ваш систем не подржава овај пакет Обједињеног МПЛ. Или инсталирајте одговарајући пакет или Xposed модул за компатибилност.</string>
|
||||||
|
|
||||||
|
<string name="self_check_cat_nlp_status">Стање Обједињеног МПЛ-а</string>
|
||||||
|
<string name="self_check_name_nlp_bound">Обједињени МПЛ је регистрован у систему:</string>
|
||||||
|
<string name="self_check_resolution_nlp_bound">Систем се није повезао са услугом Обједињеног МПЛ-а. Ако сте инсталирали Обједињени МПЛ покушајте са рестартом уређаја.</string>
|
||||||
|
<string name="self_check_name_last_location">Обједињени МПЛ има познату локацију:</string>
|
||||||
|
<string name="self_check_resolution_last_location">Обједињени МПЛ нема последњу познату локацију. Неке апликације ће краховати због овога.</string>
|
||||||
|
<string name="self_check_name_nlp_is_providing">Обједињени МПЛ пружа освежавања локације:</string>
|
||||||
|
<string name="self_check_resolution_nlp_is_providing">Систем није пружио ниједну локацију Обједињеног МПЛ-а у последњих 10 секунди.</string>
|
||||||
|
<string name="self_check_name_network_enabled">Мрежна локација укључена:</string>
|
||||||
|
<string name="self_check_resolution_network_enabled">Или сте искључили мрежну локацију (у поставкама система) или систем није подржан.</string>
|
||||||
|
<string name="self_check_loc_perm_missing">Дозвола за локацију још није одобрена</string>
|
||||||
|
|
||||||
|
<string name="prefcat_about">О програму</string>
|
||||||
|
<string name="pref_about_title">О микроГ Обједињеном МПЛ-у</string>
|
||||||
|
<string name="pref_about_summary">Подаци о издању и коришћеним библиотекама</string>
|
||||||
|
|
||||||
|
</resources>
|
|
@ -0,0 +1,19 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?><!--
|
||||||
|
~ Copyright (C) 2013-2017 microG Project Team
|
||||||
|
~
|
||||||
|
~ 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.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<resources>
|
||||||
|
<color name="switchbar_background_color">#ff37474f</color>
|
||||||
|
</resources>
|
|
@ -0,0 +1,23 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!--
|
||||||
|
~ Copyright (C) 2017 microG Project Team
|
||||||
|
~
|
||||||
|
~ 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.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||||
|
<plurals name="pref_unifiednlp_summary">
|
||||||
|
<item quantity="one"><xliff:g example="1">%1$d</xliff:g> backend configured</item>
|
||||||
|
<item quantity="other"><xliff:g example="3">%1$d</xliff:g> backends configured</item>
|
||||||
|
</plurals>
|
||||||
|
</resources>
|
|
@ -0,0 +1,61 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?><!--
|
||||||
|
~ Copyright (C) 2013-2017 microG Project Team
|
||||||
|
~
|
||||||
|
~ 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.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||||
|
<string name="nlp_app_name">UnifiedNlp</string>
|
||||||
|
<string name="nlp_settings_label">UnifiedNlp Settings</string>
|
||||||
|
|
||||||
|
<!-- Self check -->
|
||||||
|
|
||||||
|
<string name="self_check_title">Self-Check</string>
|
||||||
|
<string name="self_check_desc">Check if the system is correctly set up to use microG.</string>
|
||||||
|
|
||||||
|
<string name="self_check_cat_nlpcompat">Network location provider support</string>
|
||||||
|
<string name="self_check_name_system_supported">Android version supported:</string>
|
||||||
|
<string name="self_check_resolution_system_supported">Your Android version is not officially supported. This does not necessarily mean anything.</string>
|
||||||
|
<string name="self_check_name_nlp_package_name">System supports location provider:</string>
|
||||||
|
<string name="self_check_resolution_nlp_package_name">Your system does not support this UnifiedNlp package. Either install a matching package or a compatibility Xposed module.</string>
|
||||||
|
|
||||||
|
<string name="self_check_cat_nlp_status">UnifiedNlp status</string>
|
||||||
|
<string name="self_check_name_nlp_bound">UnifiedNlp is registered in system:</string>
|
||||||
|
<string name="self_check_resolution_nlp_bound">The system did not bind the UnifiedNlp service. If you just installed UnifiedNlp you should try to reboot this device.</string>
|
||||||
|
<string name="self_check_name_last_location">UnifiedNlp has known location:</string>
|
||||||
|
<string name="self_check_resolution_last_location">UnifiedNlp has no last known location. This will cause some apps to fail.</string>
|
||||||
|
<string name="self_check_name_nlp_is_providing">UnifiedNlp provides location updates:</string>
|
||||||
|
<string name="self_check_resolution_nlp_is_providing">No UnifiedNlp location was provided by the system within 10 seconds.</string>
|
||||||
|
<string name="self_check_name_network_enabled">Network-based location enabled:</string>
|
||||||
|
<string name="self_check_resolution_network_enabled">You either disabled network-based location (in system settings) or the system is not supported.</string>
|
||||||
|
<string name="self_check_loc_perm_missing">Location permission not yet granted</string>
|
||||||
|
|
||||||
|
<string name="self_check_cat_permissions">Permissions granted</string>
|
||||||
|
<string name="self_check_name_permission">Permission to %1$s:</string>
|
||||||
|
<string name="self_check_resolution_permission">Touch here to grant permission. Not granting the permission can result in misbehaving applications.</string>
|
||||||
|
|
||||||
|
<!-- About strings -->
|
||||||
|
<string name="about_version_str">Version %1$s</string>
|
||||||
|
<string name="about_name_version_str">%1$s %2$s</string>
|
||||||
|
<string name="about_default_license">All rights reserved.</string>
|
||||||
|
|
||||||
|
<string name="about_root_title">UnifiedNlp UI Demo</string>
|
||||||
|
<string name="about_root_summary">Summary</string>
|
||||||
|
<string name="about_root_version">Version v0.1.0</string>
|
||||||
|
<string name="about_root_libraries">Included libraries</string>
|
||||||
|
|
||||||
|
<string name="prefcat_about">About</string>
|
||||||
|
<string name="pref_about_title">About microG UnifiedNlp</string>
|
||||||
|
<string name="pref_about_summary">Version information and used libraries</string>
|
||||||
|
|
||||||
|
</resources>
|
|
@ -0,0 +1,43 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?><!--
|
||||||
|
~ Copyright (C) 2013-2017 microG Project Team
|
||||||
|
~
|
||||||
|
~ 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.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||||
|
|
||||||
|
<PreferenceCategory android:layout="@layout/preference_category_no_label">
|
||||||
|
<Preference
|
||||||
|
android:icon="@drawable/self_check"
|
||||||
|
android:summary="@string/self_check_desc"
|
||||||
|
android:title="@string/self_check_title">
|
||||||
|
<intent
|
||||||
|
android:targetClass="org.microg.nlp.app.SelfCheckFragment$AsActivity"
|
||||||
|
android:targetPackage="@string/application_id" />
|
||||||
|
</Preference>
|
||||||
|
</PreferenceCategory>
|
||||||
|
<PreferenceCategory android:layout="@layout/preference_category_no_label">
|
||||||
|
<Preference
|
||||||
|
android:icon="@drawable/ic_map_marker"
|
||||||
|
android:key="pref_unifiednlp"
|
||||||
|
android:title="@string/nlp_backends_title" />
|
||||||
|
</PreferenceCategory>
|
||||||
|
<PreferenceCategory android:layout="@layout/preference_category_no_label">
|
||||||
|
<Preference
|
||||||
|
android:icon="@drawable/ic_info_outline"
|
||||||
|
android:key="pref_about"
|
||||||
|
android:summary="@string/pref_about_summary"
|
||||||
|
android:title="@string/pref_about_title" />
|
||||||
|
</PreferenceCategory>
|
||||||
|
</PreferenceScreen>
|
|
@ -17,6 +17,6 @@ include ':ui'
|
||||||
|
|
||||||
//include ':service-app'
|
//include ':service-app'
|
||||||
//include ':client-app'
|
//include ':client-app'
|
||||||
//include ':app'
|
include ':app'
|
||||||
|
|
||||||
include ':docs:backend-sample'
|
include ':docs:backend-sample'
|
||||||
|
|