mirror of
https://gitlab.futo.org/keyboard/latinime.git
synced 2024-09-19 23:28:31 +01:00
Remove some unneeded code and permissions
This commit is contained in:
parent
76231dc7a7
commit
ecafe8f86a
@ -125,6 +125,7 @@ android {
|
||||
dimension "buildType"
|
||||
buildConfigField "boolean", "IS_PLAYSTORE_BUILD", "false"
|
||||
buildConfigField "boolean", "UPDATE_CHECKING", "true"
|
||||
getIsDefault().set(true)
|
||||
}
|
||||
playstore {
|
||||
dimension "buildType"
|
||||
@ -205,9 +206,9 @@ dependencies {
|
||||
implementation 'androidx.datastore:datastore-preferences:1.0.0'
|
||||
implementation 'androidx.autofill:autofill:1.1.0'
|
||||
|
||||
implementation 'ch.acra:acra-http:5.11.1' // TODO: Remove upon release
|
||||
implementation 'ch.acra:acra-mail:5.11.1'
|
||||
implementation 'ch.acra:acra-dialog:5.11.1'
|
||||
stableImplementation 'ch.acra:acra-http:5.11.1' // TODO: Remove upon release
|
||||
stableImplementation 'ch.acra:acra-mail:5.11.1'
|
||||
stableImplementation 'ch.acra:acra-dialog:5.11.1'
|
||||
|
||||
implementation 'com.squareup.okhttp3:okhttp:4.11.0'
|
||||
implementation 'org.jetbrains.kotlinx:kotlinx-serialization-json:1.5.1'
|
||||
|
@ -16,27 +16,16 @@
|
||||
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
|
||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
|
||||
<uses-permission android:name="android.permission.DOWNLOAD_WITHOUT_NOTIFICATION"/>
|
||||
<uses-permission android:name="android.permission.GET_ACCOUNTS"/>
|
||||
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
|
||||
<uses-permission android:name="android.permission.READ_CONTACTS"/>
|
||||
<uses-permission android:name="android.permission.READ_PROFILE"/>
|
||||
<uses-permission android:name="android.permission.READ_SYNC_SETTINGS"/>
|
||||
<uses-permission android:name="android.permission.READ_SYNC_STATS"/>
|
||||
<!--<uses-permission android:name="android.permission.READ_PROFILE"/>--> <!-- ? -->
|
||||
<uses-permission android:name="android.permission.READ_USER_DICTIONARY"/>
|
||||
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
|
||||
<uses-permission android:name="android.permission.USE_CREDENTIALS"/>
|
||||
<uses-permission android:name="android.permission.VIBRATE"/>
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
|
||||
<uses-permission android:name="android.permission.WRITE_SYNC_SETTINGS"/>
|
||||
<uses-permission android:name="android.permission.WRITE_USER_DICTIONARY"/>
|
||||
<uses-permission android:name="android.permission.RECORD_AUDIO"/>
|
||||
<uses-permission android:name="android.permission.WAKE_LOCK"/>
|
||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
|
||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_SPECIAL_USE"/>
|
||||
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
|
||||
|
||||
<!-- A signature-protected permission to ask AOSP Keyboard to close the software keyboard.
|
||||
To use this, add the following line into calling application's AndroidManifest.xml
|
||||
@ -77,12 +66,6 @@
|
||||
android:resource="@xml/method"/>
|
||||
</service>
|
||||
|
||||
<service
|
||||
android:name="org.futo.inputmethod.updates.UpdateCheckingService"
|
||||
android:label="@string/update_checking_service"
|
||||
android:permission="android.permission.BIND_JOB_SERVICE" >
|
||||
</service>
|
||||
|
||||
<service android:name=".spellcheck.AndroidSpellCheckerService"
|
||||
android:label="@string/spell_checker_service_name"
|
||||
android:permission="android.permission.BIND_TEXT_SERVICE"
|
||||
@ -177,16 +160,6 @@
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
|
||||
<!-- Broadcast receiver for AccountManager#LOGIN_ACCOUNTS_CHANGED_ACTION. -->
|
||||
<receiver android:name=".accounts.AccountsChangedReceiver"
|
||||
android:exported="true">
|
||||
<intent-filter>
|
||||
<action android:name="android.accounts.LOGIN_ACCOUNTS_CHANGED"/>
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
|
||||
<receiver android:name="org.futo.inputmethod.updates.InstallReceiver" />
|
||||
|
||||
<service
|
||||
android:name="androidx.work.impl.foreground.SystemForegroundService"
|
||||
android:foregroundServiceType="specialUse"
|
||||
|
@ -1,36 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2013 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.
|
||||
*/
|
||||
|
||||
package org.futo.inputmethod.compat;
|
||||
|
||||
import android.net.ConnectivityManager;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
public final class ConnectivityManagerCompatUtils {
|
||||
// ConnectivityManager#isActiveNetworkMetered() has been introduced
|
||||
// in API level 16 (Build.VERSION_CODES.JELLY_BEAN).
|
||||
private static final Method METHOD_isActiveNetworkMetered = CompatUtils.getMethod(
|
||||
ConnectivityManager.class, "isActiveNetworkMetered");
|
||||
|
||||
public static boolean isActiveNetworkMetered(final ConnectivityManager manager) {
|
||||
return (Boolean)CompatUtils.invoke(manager,
|
||||
// If the API telling whether the network is metered or not is not available,
|
||||
// then the closest thing is "if it's a mobile connection".
|
||||
manager.getActiveNetworkInfo().getType() == ConnectivityManager.TYPE_MOBILE,
|
||||
METHOD_isActiveNetworkMetered);
|
||||
}
|
||||
}
|
@ -1,36 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2013 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.
|
||||
*/
|
||||
|
||||
package org.futo.inputmethod.dictionarypack;
|
||||
|
||||
import android.app.DownloadManager;
|
||||
|
||||
/**
|
||||
* Struct class to encapsulate the result of a completed download.
|
||||
*/
|
||||
public class CompletedDownloadInfo {
|
||||
final String mUri;
|
||||
final long mDownloadId;
|
||||
final int mStatus;
|
||||
public CompletedDownloadInfo(final String uri, final long downloadId, final int status) {
|
||||
mUri = uri;
|
||||
mDownloadId = downloadId;
|
||||
mStatus = status;
|
||||
}
|
||||
public boolean wasSuccessful() {
|
||||
return DownloadManager.STATUS_SUCCESSFUL == mStatus;
|
||||
}
|
||||
}
|
@ -1,179 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2012 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.
|
||||
*/
|
||||
|
||||
package org.futo.inputmethod.latin;
|
||||
|
||||
import android.Manifest;
|
||||
import android.content.Context;
|
||||
import android.net.Uri;
|
||||
import android.provider.ContactsContract;
|
||||
import android.provider.ContactsContract.Contacts;
|
||||
import android.util.Log;
|
||||
|
||||
import org.futo.inputmethod.annotations.ExternallyReferenced;
|
||||
import org.futo.inputmethod.latin.ContactsManager.ContactsChangedListener;
|
||||
import org.futo.inputmethod.latin.common.StringUtils;
|
||||
import org.futo.inputmethod.latin.permissions.PermissionsUtil;
|
||||
import org.futo.inputmethod.latin.personalization.AccountUtils;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public class ContactsBinaryDictionary extends ExpandableBinaryDictionary
|
||||
implements ContactsChangedListener {
|
||||
private static final String TAG = ContactsBinaryDictionary.class.getSimpleName();
|
||||
private static final String NAME = "contacts";
|
||||
|
||||
private static final boolean DEBUG = false;
|
||||
private static final boolean DEBUG_DUMP = false;
|
||||
|
||||
/**
|
||||
* Whether to use "firstname lastname" in bigram predictions.
|
||||
*/
|
||||
private final boolean mUseFirstLastBigrams;
|
||||
private final ContactsManager mContactsManager;
|
||||
|
||||
protected ContactsBinaryDictionary(final Context context, final Locale locale,
|
||||
final File dictFile, final String name) {
|
||||
super(context, getDictName(name, locale, dictFile), locale, Dictionary.TYPE_CONTACTS,
|
||||
dictFile);
|
||||
mUseFirstLastBigrams = ContactsDictionaryUtils.useFirstLastBigramsForLocale(locale);
|
||||
mContactsManager = new ContactsManager(context);
|
||||
mContactsManager.registerForUpdates(this /* listener */);
|
||||
reloadDictionaryIfRequired();
|
||||
}
|
||||
|
||||
// Note: This method is called by {@link DictionaryFacilitator} using Java reflection.
|
||||
@ExternallyReferenced
|
||||
public static ContactsBinaryDictionary getDictionary(final Context context, final Locale locale,
|
||||
final File dictFile, final String dictNamePrefix, @Nullable final String account) {
|
||||
return new ContactsBinaryDictionary(context, locale, dictFile, dictNamePrefix + NAME);
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void close() {
|
||||
mContactsManager.close();
|
||||
super.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Typically called whenever the dictionary is created for the first time or
|
||||
* recreated when we think that there are updates to the dictionary.
|
||||
* This is called asynchronously.
|
||||
*/
|
||||
@Override
|
||||
public void loadInitialContentsLocked() {
|
||||
loadDeviceAccountsEmailAddressesLocked();
|
||||
loadDictionaryForUriLocked(ContactsContract.Profile.CONTENT_URI);
|
||||
// TODO: Switch this URL to the newer ContactsContract too
|
||||
loadDictionaryForUriLocked(Contacts.CONTENT_URI);
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads device accounts to the dictionary.
|
||||
*/
|
||||
private void loadDeviceAccountsEmailAddressesLocked() {
|
||||
final List<String> accountVocabulary =
|
||||
AccountUtils.getDeviceAccountsEmailAddresses(mContext);
|
||||
if (accountVocabulary == null || accountVocabulary.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
for (String word : accountVocabulary) {
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "loadAccountVocabulary: " + word);
|
||||
}
|
||||
runGCIfRequiredLocked(true /* mindsBlockByGC */);
|
||||
addUnigramLocked(word, ContactsDictionaryConstants.FREQUENCY_FOR_CONTACTS,
|
||||
null, 0,
|
||||
false /* isNotAWord */, false /* isPossiblyOffensive */,
|
||||
BinaryDictionary.NOT_A_VALID_TIMESTAMP);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads data within content providers to the dictionary.
|
||||
*/
|
||||
private void loadDictionaryForUriLocked(final Uri uri) {
|
||||
if (!PermissionsUtil.checkAllPermissionsGranted(
|
||||
mContext, Manifest.permission.READ_CONTACTS)) {
|
||||
Log.i(TAG, "No permission to read contacts. Not loading the Dictionary.");
|
||||
}
|
||||
|
||||
final ArrayList<String> validNames = mContactsManager.getValidNames(uri);
|
||||
for (final String name : validNames) {
|
||||
addNameLocked(name);
|
||||
}
|
||||
if (uri.equals(Contacts.CONTENT_URI)) {
|
||||
// Since we were able to add content successfully, update the local
|
||||
// state of the manager.
|
||||
mContactsManager.updateLocalState(validNames);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the words in a name (e.g., firstname/lastname) to the binary dictionary along with their
|
||||
* bigrams depending on locale.
|
||||
*/
|
||||
private void addNameLocked(final String name) {
|
||||
int len = StringUtils.codePointCount(name);
|
||||
NgramContext ngramContext = NgramContext.getEmptyPrevWordsContext(
|
||||
BinaryDictionary.MAX_PREV_WORD_COUNT_FOR_N_GRAM);
|
||||
// TODO: Better tokenization for non-Latin writing systems
|
||||
for (int i = 0; i < len; i++) {
|
||||
if (Character.isLetter(name.codePointAt(i))) {
|
||||
int end = ContactsDictionaryUtils.getWordEndPosition(name, len, i);
|
||||
String word = name.substring(i, end);
|
||||
if (DEBUG_DUMP) {
|
||||
Log.d(TAG, "addName word = " + word);
|
||||
}
|
||||
i = end - 1;
|
||||
// Don't add single letter words, possibly confuses
|
||||
// capitalization of i.
|
||||
final int wordLen = StringUtils.codePointCount(word);
|
||||
if (wordLen <= MAX_WORD_LENGTH && wordLen > 1) {
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "addName " + name + ", " + word + ", " + ngramContext);
|
||||
}
|
||||
runGCIfRequiredLocked(true /* mindsBlockByGC */);
|
||||
addUnigramLocked(word,
|
||||
ContactsDictionaryConstants.FREQUENCY_FOR_CONTACTS,
|
||||
null, 0,
|
||||
false /* isNotAWord */,
|
||||
false /* isPossiblyOffensive */,
|
||||
BinaryDictionary.NOT_A_VALID_TIMESTAMP);
|
||||
if (ngramContext.isValid() && mUseFirstLastBigrams) {
|
||||
runGCIfRequiredLocked(true /* mindsBlockByGC */);
|
||||
addNgramEntryLocked(ngramContext,
|
||||
word,
|
||||
ContactsDictionaryConstants.FREQUENCY_FOR_CONTACTS_BIGRAM,
|
||||
BinaryDictionary.NOT_A_VALID_TIMESTAMP);
|
||||
}
|
||||
ngramContext = ngramContext.getNextNgramContext(
|
||||
new NgramContext.WordInfo(word));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onContactsChange() {
|
||||
setNeedsToRecreate();
|
||||
}
|
||||
}
|
@ -80,7 +80,6 @@ public class DictionaryFacilitatorImpl implements DictionaryFacilitator {
|
||||
static {
|
||||
DICT_TYPE_TO_CLASS.put(Dictionary.TYPE_USER_HISTORY, UserHistoryDictionary.class);
|
||||
DICT_TYPE_TO_CLASS.put(Dictionary.TYPE_USER, UserBinaryDictionary.class);
|
||||
DICT_TYPE_TO_CLASS.put(Dictionary.TYPE_CONTACTS, ContactsBinaryDictionary.class);
|
||||
}
|
||||
|
||||
private static final String DICT_FACTORY_METHOD_NAME = "getDictionary";
|
||||
|
@ -1,81 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2014 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.
|
||||
*/
|
||||
|
||||
package org.futo.inputmethod.latin.accounts;
|
||||
|
||||
import android.accounts.AccountManager;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
|
||||
import org.futo.inputmethod.annotations.UsedForTesting;
|
||||
import org.futo.inputmethod.latin.settings.LocalSettingsConstants;
|
||||
|
||||
/**
|
||||
* {@link BroadcastReceiver} for {@link AccountManager#LOGIN_ACCOUNTS_CHANGED_ACTION}.
|
||||
*/
|
||||
public class AccountsChangedReceiver extends BroadcastReceiver {
|
||||
static final String TAG = "AccountsChangedReceiver";
|
||||
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
if (!AccountManager.LOGIN_ACCOUNTS_CHANGED_ACTION.equals(intent.getAction())) {
|
||||
Log.w(TAG, "Received unknown broadcast: " + intent);
|
||||
return;
|
||||
}
|
||||
|
||||
// Ideally the account preference could live in a different preferences file
|
||||
// that wasn't being backed up and restored, however the preference fragments
|
||||
// currently only deal with the default shared preferences which is why
|
||||
// separating this out into a different file is not trivial currently.
|
||||
final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
final String currentAccount = prefs.getString(
|
||||
LocalSettingsConstants.PREF_ACCOUNT_NAME, null);
|
||||
removeUnknownAccountFromPreference(prefs, getAccountsForLogin(context), currentAccount);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to help test this receiver.
|
||||
*/
|
||||
@UsedForTesting
|
||||
protected String[] getAccountsForLogin(Context context) {
|
||||
return LoginAccountUtils.getAccountsForLogin(context);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the currentAccount from preferences if it's not found
|
||||
* in the list of current accounts.
|
||||
*/
|
||||
private static void removeUnknownAccountFromPreference(final SharedPreferences prefs,
|
||||
final String[] accounts, final String currentAccount) {
|
||||
if (currentAccount == null) {
|
||||
return;
|
||||
}
|
||||
for (final String account : accounts) {
|
||||
if (TextUtils.equals(currentAccount, account)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
Log.i(TAG, "The current account was removed from the system: " + currentAccount);
|
||||
prefs.edit()
|
||||
.remove(LocalSettingsConstants.PREF_ACCOUNT_NAME)
|
||||
.apply();
|
||||
}
|
||||
}
|
@ -1,67 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2014 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.
|
||||
*/
|
||||
|
||||
package org.futo.inputmethod.latin.accounts;
|
||||
|
||||
import android.accounts.Account;
|
||||
import android.accounts.AccountManager;
|
||||
import android.accounts.AccountManagerCallback;
|
||||
import android.accounts.AccountManagerFuture;
|
||||
import android.accounts.AuthenticatorException;
|
||||
import android.accounts.OperationCanceledException;
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Utility class that handles generation/invalidation of auth tokens in the app.
|
||||
*/
|
||||
public class AuthUtils {
|
||||
private final AccountManager mAccountManager;
|
||||
|
||||
public AuthUtils(Context context) {
|
||||
mAccountManager = AccountManager.get(context);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see AccountManager#invalidateAuthToken(String, String)
|
||||
*/
|
||||
public void invalidateAuthToken(final String accountType, final String authToken) {
|
||||
mAccountManager.invalidateAuthToken(accountType, authToken);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see AccountManager#getAuthToken(
|
||||
* Account, String, Bundle, boolean, AccountManagerCallback, Handler)
|
||||
*/
|
||||
public AccountManagerFuture<Bundle> getAuthToken(final Account account,
|
||||
final String authTokenType, final Bundle options, final boolean notifyAuthFailure,
|
||||
final AccountManagerCallback<Bundle> callback, final Handler handler) {
|
||||
return mAccountManager.getAuthToken(account, authTokenType, options, notifyAuthFailure,
|
||||
callback, handler);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see AccountManager#blockingGetAuthToken(Account, String, boolean)
|
||||
*/
|
||||
public String blockingGetAuthToken(final Account account, final String authTokenType,
|
||||
final boolean notifyAuthFailure) throws OperationCanceledException,
|
||||
AuthenticatorException, IOException {
|
||||
return mAccountManager.blockingGetAuthToken(account, authTokenType, notifyAuthFailure);
|
||||
}
|
||||
}
|
@ -1,47 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2014 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.
|
||||
*/
|
||||
|
||||
package org.futo.inputmethod.latin.accounts;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
/**
|
||||
* Utility class for retrieving accounts that may be used for login.
|
||||
*/
|
||||
public class LoginAccountUtils {
|
||||
/**
|
||||
* This defines the type of account this class deals with.
|
||||
* This account type is used when listing the accounts available on the device for login.
|
||||
*/
|
||||
public static final String ACCOUNT_TYPE = "";
|
||||
|
||||
private LoginAccountUtils() {
|
||||
// This utility class is not publicly instantiable.
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the accounts available for login.
|
||||
*
|
||||
* @return an array of accounts. Empty (never null) if no accounts are available for login.
|
||||
*/
|
||||
@Nonnull
|
||||
@SuppressWarnings("unused")
|
||||
public static String[] getAccountsForLogin(final Context context) {
|
||||
return new String[0];
|
||||
}
|
||||
}
|
@ -1,66 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2013 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.
|
||||
*/
|
||||
|
||||
package org.futo.inputmethod.latin.personalization;
|
||||
|
||||
import android.accounts.Account;
|
||||
import android.accounts.AccountManager;
|
||||
import android.content.Context;
|
||||
import android.util.Patterns;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
public class AccountUtils {
|
||||
private AccountUtils() {
|
||||
// This utility class is not publicly instantiable.
|
||||
}
|
||||
|
||||
private static Account[] getAccounts(final Context context) {
|
||||
return AccountManager.get(context).getAccounts();
|
||||
}
|
||||
|
||||
public static List<String> getDeviceAccountsEmailAddresses(final Context context) {
|
||||
final ArrayList<String> retval = new ArrayList<>();
|
||||
for (final Account account : getAccounts(context)) {
|
||||
final String name = account.name;
|
||||
if (Patterns.EMAIL_ADDRESS.matcher(name).matches()) {
|
||||
retval.add(name);
|
||||
retval.add(name.split("@")[0]);
|
||||
}
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all device accounts having specified domain name.
|
||||
* @param context application context
|
||||
* @param domain domain name used for filtering
|
||||
* @return List of account names that contain the specified domain name
|
||||
*/
|
||||
public static List<String> getDeviceAccountsWithDomain(
|
||||
final Context context, final String domain) {
|
||||
final ArrayList<String> retval = new ArrayList<>();
|
||||
final String atDomain = "@" + domain.toLowerCase(Locale.ROOT);
|
||||
for (final Account account : getAccounts(context)) {
|
||||
if (account.name.toLowerCase(Locale.ROOT).endsWith(atDomain)) {
|
||||
retval.add(account.name);
|
||||
}
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
}
|
4
src/playstore/AndroidManifest.xml
Normal file
4
src/playstore/AndroidManifest.xml
Normal file
@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
</manifest>
|
@ -0,0 +1,7 @@
|
||||
package org.futo.inputmethod.latin
|
||||
|
||||
import android.app.Application
|
||||
|
||||
class CrashLoggingApplication : Application() {
|
||||
|
||||
}
|
17
src/stable/AndroidManifest.xml
Normal file
17
src/stable/AndroidManifest.xml
Normal file
@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
|
||||
<application>
|
||||
<service
|
||||
android:name="org.futo.inputmethod.updates.UpdateCheckingService"
|
||||
android:label="@string/update_checking_service"
|
||||
android:permission="android.permission.BIND_JOB_SERVICE" >
|
||||
</service>
|
||||
|
||||
<receiver android:name="org.futo.inputmethod.updates.InstallReceiver" />
|
||||
|
||||
</application>
|
||||
</manifest>
|
@ -1,130 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2014 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.
|
||||
*/
|
||||
|
||||
package org.futo.inputmethod.latin.accounts;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import android.accounts.AccountManager;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.preference.PreferenceManager;
|
||||
|
||||
import androidx.test.InstrumentationRegistry;
|
||||
import androidx.test.filters.SmallTest;
|
||||
import androidx.test.runner.AndroidJUnit4;
|
||||
|
||||
import org.futo.inputmethod.latin.settings.LocalSettingsConstants;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
/**
|
||||
* Tests for {@link AccountsChangedReceiver}.
|
||||
*/
|
||||
@SmallTest
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class AccountsChangedReceiverTests {
|
||||
private static final String ACCOUNT_1 = "account1@example.com";
|
||||
private static final String ACCOUNT_2 = "account2@example.com";
|
||||
|
||||
private SharedPreferences mPrefs;
|
||||
private String mLastKnownAccount = null;
|
||||
|
||||
private Context getContext() {
|
||||
return InstrumentationRegistry.getTargetContext();
|
||||
}
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
mPrefs = PreferenceManager.getDefaultSharedPreferences(getContext());
|
||||
// Keep track of the current account so that we restore it when the test finishes.
|
||||
mLastKnownAccount = mPrefs.getString(LocalSettingsConstants.PREF_ACCOUNT_NAME, null);
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() throws Exception {
|
||||
// Restore the account that was present before running the test.
|
||||
updateAccountName(mLastKnownAccount);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUnknownIntent() {
|
||||
updateAccountName(ACCOUNT_1);
|
||||
AccountsChangedReceiver reciever = new AccountsChangedReceiver();
|
||||
reciever.onReceive(getContext(), new Intent("some-random-action"));
|
||||
// Account should *not* be removed from preferences.
|
||||
assertAccountName(ACCOUNT_1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAccountRemoved() {
|
||||
updateAccountName(ACCOUNT_1);
|
||||
AccountsChangedReceiver reciever = new AccountsChangedReceiver() {
|
||||
@Override
|
||||
protected String[] getAccountsForLogin(Context context) {
|
||||
return new String[] {ACCOUNT_2};
|
||||
}
|
||||
};
|
||||
reciever.onReceive(getContext(), new Intent(AccountManager.LOGIN_ACCOUNTS_CHANGED_ACTION));
|
||||
// Account should be removed from preferences.
|
||||
assertAccountName(null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAccountRemoved_noAccounts() {
|
||||
updateAccountName(ACCOUNT_2);
|
||||
AccountsChangedReceiver reciever = new AccountsChangedReceiver() {
|
||||
@Override
|
||||
protected String[] getAccountsForLogin(Context context) {
|
||||
return new String[0];
|
||||
}
|
||||
};
|
||||
reciever.onReceive(getContext(), new Intent(AccountManager.LOGIN_ACCOUNTS_CHANGED_ACTION));
|
||||
// Account should be removed from preferences.
|
||||
assertAccountName(null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAccountNotRemoved() {
|
||||
updateAccountName(ACCOUNT_2);
|
||||
AccountsChangedReceiver reciever = new AccountsChangedReceiver() {
|
||||
@Override
|
||||
protected String[] getAccountsForLogin(Context context) {
|
||||
return new String[] {ACCOUNT_1, ACCOUNT_2};
|
||||
}
|
||||
};
|
||||
reciever.onReceive(getContext(), new Intent(AccountManager.LOGIN_ACCOUNTS_CHANGED_ACTION));
|
||||
// Account should *not* be removed from preferences.
|
||||
assertAccountName(ACCOUNT_2);
|
||||
}
|
||||
|
||||
private void updateAccountName(String accountName) {
|
||||
if (accountName == null) {
|
||||
mPrefs.edit().remove(LocalSettingsConstants.PREF_ACCOUNT_NAME).apply();
|
||||
} else {
|
||||
mPrefs.edit().putString(LocalSettingsConstants.PREF_ACCOUNT_NAME, accountName).apply();
|
||||
}
|
||||
}
|
||||
|
||||
private void assertAccountName(String expectedAccountName) {
|
||||
assertEquals(expectedAccountName,
|
||||
mPrefs.getString(LocalSettingsConstants.PREF_ACCOUNT_NAME, null));
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user