Add back standalone app

This commit is contained in:
Erfan Abdi 2020-11-19 00:14:05 +03:30 committed by Peter Cai
parent 876181e0d8
commit 1c678b4908
49 changed files with 2275 additions and 1 deletions

111
app/build.gradle Normal file
View File

@ -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
}
}

View File

@ -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>

View File

@ -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();
}
}
}

View File

@ -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 {
}

View File

@ -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();
}
}
}

View File

@ -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();
}
}

View File

@ -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;
}
}
}

View File

@ -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));
}
}
}

View File

@ -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);
}
}
}

View File

@ -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
}
}

View File

@ -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));
}
}
}

View File

@ -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);
}
});
}
}
}

View File

@ -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;
}
}

View File

@ -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);
}
}
}

View File

@ -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;
}
}
}

View File

@ -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);
}
}
}

View File

@ -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();
}
}

View File

@ -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);
}
}

View File

@ -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
}
}

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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" />

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -17,6 +17,6 @@ include ':ui'
//include ':service-app'
//include ':client-app'
//include ':app'
include ':app'
include ':docs:backend-sample'