mirror of
https://github.com/TeamVanced/VancedMicroG
synced 2024-11-19 02:29:25 +01:00
Squashed commit
- Update all submodules, used sdk version, etc - Settings UI rebuild - Some GCM features and fixes - Fix newest Cast Framework for some apps (tested with "ZDF Mediathek") Fixes #224, #223, #145
This commit is contained in:
parent
8b61ba7e44
commit
5316e0220a
@ -12,10 +12,9 @@ script:
|
||||
- ./gradlew assemble
|
||||
android:
|
||||
components:
|
||||
- platform-tools
|
||||
- tools
|
||||
- build-tools-24.0.2
|
||||
- android-23
|
||||
- platform-tools
|
||||
- build-tools-24.0.3
|
||||
- android-24
|
||||
- extra-android-m2repository
|
||||
before_cache:
|
||||
|
@ -19,14 +19,14 @@ buildscript {
|
||||
jcenter()
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:2.2.0'
|
||||
classpath 'com.android.tools.build:gradle:2.2.2'
|
||||
classpath 'com.github.dcendents:android-maven-gradle-plugin:1.4.1'
|
||||
}
|
||||
}
|
||||
|
||||
allprojects {
|
||||
apply plugin: 'idea'
|
||||
ext.androidBuildVersionTools = "24.0.2"
|
||||
ext.androidBuildVersionTools = "24.0.3"
|
||||
ext.isReleaseVersion = false
|
||||
}
|
||||
|
||||
@ -34,7 +34,7 @@ def androidCompileSdk() { return 24 }
|
||||
|
||||
def androidTargetSdk() { return 24 }
|
||||
|
||||
def androidMinSdk() { return 10 }
|
||||
def androidMinSdk() { return 9 }
|
||||
|
||||
def versionCode() {
|
||||
def stdout = new ByteArrayOutputStream()
|
||||
|
2
extern/GmsApi
vendored
2
extern/GmsApi
vendored
@ -1 +1 @@
|
||||
Subproject commit 9ff42ae73a02ea971dc557f657b612113dfa6e24
|
||||
Subproject commit 0b4f43c6a6a091dbdeb0ec544d533373a83ea319
|
2
extern/GmsLib
vendored
2
extern/GmsLib
vendored
@ -1 +1 @@
|
||||
Subproject commit 4bffa5799a9ce406a268941e26fbb4a637d42446
|
||||
Subproject commit a0300494f6cf65334c1d2f969571ef6069579bca
|
2
extern/UnifiedNlp
vendored
2
extern/UnifiedNlp
vendored
@ -1 +1 @@
|
||||
Subproject commit d9923a0d10edded17ad96d61e1e247f557bad652
|
||||
Subproject commit 2f810b14fde67cb690b440b3249f1887435c2e92
|
1
play-services-cast-framework-api
Symbolic link
1
play-services-cast-framework-api
Symbolic link
@ -0,0 +1 @@
|
||||
extern/GmsApi/play-services-cast-framework-api
|
@ -64,6 +64,9 @@ android {
|
||||
// We are not allowed to freely choose the hundreds column as it defines the device type
|
||||
versionCode(10084400 + x % 100 + ((int) (x / 100)) * 1000)
|
||||
|
||||
minSdkVersion androidMinSdk()
|
||||
targetSdkVersion androidTargetSdk()
|
||||
|
||||
ndk {
|
||||
abiFilters "armeabi", "armeabi-v7a", "arm64-v8a", "x86"
|
||||
}
|
||||
|
@ -17,10 +17,6 @@
|
||||
<manifest package="com.google.android.gms"
|
||||
xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<uses-sdk
|
||||
android:minSdkVersion="14"
|
||||
android:targetSdkVersion="23"/>
|
||||
|
||||
<permission
|
||||
android:name="com.google.android.c2dm.permission.RECEIVE"
|
||||
android:label="@string/perm_c2dm_receive_label"
|
||||
@ -224,6 +220,12 @@
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
|
||||
<receiver android:name="org.microg.gms.gcm.UnregisterReceiver">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.PACKAGE_REMOVED"/>
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
|
||||
<!-- Map -->
|
||||
<provider
|
||||
android:name="org.microg.gms.maps.data.SharedTileProvider"
|
||||
@ -359,12 +361,59 @@
|
||||
android:name="org.microg.gms.ui.SettingsActivity"
|
||||
android:icon="@mipmap/ic_microg_settings"
|
||||
android:label="@string/gms_settings_name"
|
||||
android:theme="@style/SettingsTheme">
|
||||
android:theme="@style/Theme.AppCompat.Settings.Dashboard">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN"/>
|
||||
|
||||
<category android:name="android.intent.category.LAUNCHER"/>
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:name="org.microg.gms.ui.AskPushPermission"
|
||||
android:excludeFromRecents="true"
|
||||
android:theme="@style/Theme.AppCompat.Light.Dialog.Alert"/>
|
||||
|
||||
<activity
|
||||
android:name="org.microg.gms.ui.AboutFragment$AsActivity"
|
||||
android:label="@string/pref_about_title"
|
||||
android:theme="@style/Theme.AppCompat.Settings"/>
|
||||
|
||||
<activity
|
||||
android:name="org.microg.gms.ui.GcmFragment$AsActivity"
|
||||
android:label="@string/service_name_mcs"
|
||||
android:theme="@style/Theme.AppCompat.Settings"/>
|
||||
|
||||
<activity
|
||||
android:name="org.microg.gms.ui.GcmFragment$AdvancedAsActivity"
|
||||
android:label="@string/service_name_mcs"
|
||||
android:theme="@style/Theme.AppCompat.Settings"/>
|
||||
|
||||
<activity
|
||||
android:name="org.microg.gms.ui.GcmAppFragment$AsActivity"
|
||||
android:label="@string/service_name_mcs"
|
||||
android:theme="@style/Theme.AppCompat.Settings"/>
|
||||
|
||||
<activity
|
||||
android:name="org.microg.gms.ui.SelfCheckFragment$AsActivity"
|
||||
android:label="@string/self_check_title"
|
||||
android:theme="@style/Theme.AppCompat.Settings"/>
|
||||
|
||||
<activity
|
||||
android:name="org.microg.gms.ui.AccountSettingsActivity"
|
||||
android:theme="@style/Theme.AppCompat.Settings">
|
||||
<intent-filter>
|
||||
<action android:name="com.google.android.gms.accountsettings.ACCOUNT_PREFERENCES_SETTINGS"/>
|
||||
<action android:name="com.google.android.gms.accountsettings.PRIVACY_SETTINGS"/>
|
||||
<action android:name="com.google.android.gms.accountsettings.SECURITY_SETTINGS"/>
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT"/>
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:name="org.microg.gms.ui.LocationSettingsActivity"
|
||||
android:theme="@style/Theme.AppCompat.Settings">
|
||||
<intent-filter>
|
||||
<action android:name="com.google.android.gms.location.settings.LOCATION_HISTORY"/>
|
||||
<action android:name="com.google.android.location.settings.LOCATION_REPORTING_SETTINGS"/>
|
||||
|
@ -59,7 +59,7 @@ public class AccountContentProvider extends ContentProvider {
|
||||
if (getContext().checkCallingPermission(Manifest.permission.GET_ACCOUNTS) != PackageManager.PERMISSION_GRANTED)
|
||||
throw new SecurityException("Access denied, missing GET_ACCOUNTS or EXTENDED_ACCESS permission");
|
||||
}
|
||||
if (PROVIDER_METHOD_GET_ACCOUNTS.equals(method) && getContext().getString(R.string.google_account_type).equals(arg)) {
|
||||
if (PROVIDER_METHOD_GET_ACCOUNTS.equals(method) && AuthConstants.DEFAULT_ACCOUNT_TYPE.equals(arg)) {
|
||||
Bundle result = new Bundle();
|
||||
result.putParcelableArray(PROVIDER_EXTRA_ACCOUNTS, AccountManager.get(getContext()).getAccountsByType(arg));
|
||||
return result;
|
||||
|
@ -56,7 +56,7 @@ public class AuthManager {
|
||||
|
||||
public String getAccountType() {
|
||||
if (accountType == null)
|
||||
accountType = context.getString(R.string.google_account_type);
|
||||
accountType = AuthConstants.DEFAULT_ACCOUNT_TYPE;
|
||||
return accountType;
|
||||
}
|
||||
|
||||
|
@ -44,6 +44,7 @@ import android.widget.TextView;
|
||||
import com.google.android.gms.R;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.microg.gms.auth.AuthConstants;
|
||||
import org.microg.gms.auth.AuthManager;
|
||||
import org.microg.gms.auth.AuthRequest;
|
||||
import org.microg.gms.auth.AuthResponse;
|
||||
@ -90,7 +91,7 @@ public class LoginActivity extends AssistantActivity {
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
accountType = getString(R.string.google_account_type);
|
||||
accountType = AuthConstants.DEFAULT_ACCOUNT_TYPE;
|
||||
accountManager = AccountManager.get(LoginActivity.this);
|
||||
inputMethodManager = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE);
|
||||
webView = createWebView(this);
|
||||
|
@ -30,6 +30,7 @@ import android.util.Log;
|
||||
import com.google.android.gms.R;
|
||||
|
||||
import org.microg.gms.auth.AskPermissionActivity;
|
||||
import org.microg.gms.auth.AuthConstants;
|
||||
import org.microg.gms.auth.AuthManager;
|
||||
import org.microg.gms.auth.AuthResponse;
|
||||
import org.microg.gms.auth.login.LoginActivity;
|
||||
@ -55,7 +56,7 @@ class AccountAuthenticator extends AbstractAccountAuthenticator {
|
||||
public AccountAuthenticator(Context context) {
|
||||
super(context);
|
||||
this.context = context;
|
||||
this.accountType = context.getString(R.string.google_account_type);
|
||||
this.accountType = AuthConstants.DEFAULT_ACCOUNT_TYPE;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -23,6 +23,7 @@ import android.content.Context;
|
||||
|
||||
import com.google.android.gms.R;
|
||||
|
||||
import org.microg.gms.auth.AuthConstants;
|
||||
import org.microg.gms.auth.AuthRequest;
|
||||
import org.microg.gms.common.Constants;
|
||||
import org.microg.gms.common.DeviceConfiguration;
|
||||
@ -43,7 +44,7 @@ public class CheckinManager {
|
||||
return null;
|
||||
List<CheckinClient.Account> accounts = new ArrayList<CheckinClient.Account>();
|
||||
AccountManager accountManager = AccountManager.get(context);
|
||||
String accountType = context.getString(R.string.google_account_type);
|
||||
String accountType = AuthConstants.DEFAULT_ACCOUNT_TYPE;
|
||||
for (Account account : accountManager.getAccountsByType(accountType)) {
|
||||
String token = new AuthRequest()
|
||||
.email(account.name).token(accountManager.getPassword(account))
|
||||
|
@ -28,6 +28,7 @@ import android.util.Log;
|
||||
import com.google.android.gms.R;
|
||||
import com.google.android.gms.checkin.internal.ICheckinService;
|
||||
|
||||
import org.microg.gms.auth.AuthConstants;
|
||||
import org.microg.gms.gcm.McsService;
|
||||
import org.microg.gms.people.PeopleManager;
|
||||
|
||||
@ -55,7 +56,7 @@ public class CheckinService extends IntentService {
|
||||
LastCheckinInfo info = CheckinManager.checkin(this, intent.getBooleanExtra(EXTRA_FORCE_CHECKIN, false));
|
||||
if (info != null) {
|
||||
Log.d(TAG, "Checked in as " + Long.toHexString(info.androidId));
|
||||
String accountType = getString(R.string.google_account_type);
|
||||
String accountType = AuthConstants.DEFAULT_ACCOUNT_TYPE;
|
||||
for (Account account : AccountManager.get(this).getAccountsByType(accountType)) {
|
||||
PeopleManager.loadUserInfo(this, account);
|
||||
}
|
||||
|
@ -55,6 +55,6 @@ public class LastCheckinInfo {
|
||||
.putLong(PREF_SECURITY_TOKEN, securityToken)
|
||||
.putString(PREF_VERSION_INFO, versionInfo)
|
||||
.putString(PREF_DEVICE_DATA_VERSION_INFO, deviceDataVersionInfo)
|
||||
.commit();
|
||||
.apply();
|
||||
}
|
||||
}
|
||||
|
@ -86,7 +86,7 @@ public class HttpFormClient {
|
||||
|
||||
String result = new String(Utils.readStreamToEnd(connection.getInputStream()));
|
||||
Log.d(TAG, "-- Response --\n" + result);
|
||||
return parseResponse(tClass, connection.getHeaderFields(), result);
|
||||
return parseResponse(tClass, connection, result);
|
||||
}
|
||||
|
||||
private static String valueFromBoolVal(String value, Boolean boolVal, boolean truePresent, boolean falsePresent) {
|
||||
@ -103,7 +103,8 @@ public class HttpFormClient {
|
||||
}
|
||||
}
|
||||
|
||||
private static <T> T parseResponse(Class<T> tClass, Map<String, List<String>> headerFields, String result) {
|
||||
private static <T> T parseResponse(Class<T> tClass, HttpURLConnection connection, String result) throws IOException {
|
||||
Map<String, List<String>> headerFields = connection.getHeaderFields();
|
||||
T response;
|
||||
try {
|
||||
response = tClass.getConstructor().newInstance();
|
||||
@ -153,6 +154,20 @@ public class HttpFormClient {
|
||||
Log.w(TAG, e);
|
||||
}
|
||||
}
|
||||
if (field.isAnnotationPresent(ResponseStatusCode.class) && field.getType() == int.class) {
|
||||
try {
|
||||
field.setInt(response, connection.getResponseCode());
|
||||
} catch (IllegalAccessException e) {
|
||||
Log.w(TAG, e);
|
||||
}
|
||||
}
|
||||
if (field.isAnnotationPresent(ResponseStatusText.class) && field.getType() == String.class) {
|
||||
try {
|
||||
field.set(response, connection.getResponseMessage());
|
||||
} catch (IllegalAccessException e) {
|
||||
Log.w(TAG, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
return response;
|
||||
}
|
||||
@ -217,4 +232,14 @@ public class HttpFormClient {
|
||||
public @interface ResponseHeader {
|
||||
public String value();
|
||||
}
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.FIELD)
|
||||
public @interface ResponseStatusCode {
|
||||
}
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.FIELD)
|
||||
public @interface ResponseStatusText {
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,323 @@
|
||||
/*
|
||||
* Copyright (C) 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.gms.gcm;
|
||||
|
||||
import android.content.ContentValues;
|
||||
import android.content.Context;
|
||||
import android.database.Cursor;
|
||||
import android.database.sqlite.SQLiteDatabase;
|
||||
import android.database.sqlite.SQLiteOpenHelper;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
public class GcmDatabase extends SQLiteOpenHelper {
|
||||
private static final String TAG = GcmDatabase.class.getSimpleName();
|
||||
public static final String DB_NAME = "gcmstatus";
|
||||
private static int DB_VERSION = 1;
|
||||
private static final String CREATE_TABLE_APPS = "CREATE TABLE apps (" +
|
||||
"package_name TEXT," +
|
||||
"last_error TEXT DEFAULT ''," +
|
||||
"last_message_timestamp INTEGER," +
|
||||
"total_message_count INTEGER," +
|
||||
"total_message_bytes INTEGER," +
|
||||
"allow_register INTEGER DEFAULT 1," +
|
||||
"wake_for_delivery INTEGER DEFAULT 1," +
|
||||
"PRIMARY KEY (package_name));";
|
||||
private static final String TABLE_APPS = "apps";
|
||||
private static final String FIELD_PACKAGE_NAME = "package_name";
|
||||
private static final String FIELD_LAST_ERROR = "last_error";
|
||||
private static final String FIELD_LAST_MESSAGE_TIMESTAMP = "last_message_timestamp";
|
||||
private static final String FIELD_TOTAL_MESSAGE_COUNT = "total_message_count";
|
||||
private static final String FIELD_TOTAL_MESSAGE_BYTES = "total_message_bytes";
|
||||
private static final String FIELD_ALLOW_REGISTER = "allow_register";
|
||||
private static final String FIELD_WAKE_FOR_DELIVERY = "wake_for_delivery";
|
||||
|
||||
private static final String CREATE_TABLE_REGISTRATIONS = "CREATE TABLE registrations (" +
|
||||
"package_name TEXT," +
|
||||
"signature TEXT," +
|
||||
"timestamp INTEGER," +
|
||||
"register_id TEXT," +
|
||||
"PRIMARY KEY (package_name, signature));";
|
||||
private static final String TABLE_REGISTRATIONS = "registrations";
|
||||
private static final String FIELD_SIGNATURE = "signature";
|
||||
private static final String FIELD_TIMESTAMP = "timestamp";
|
||||
private static final String FIELD_REGISTER_ID = "register_id";
|
||||
|
||||
private Context context;
|
||||
|
||||
public GcmDatabase(Context context) {
|
||||
super(context, DB_NAME, null, DB_VERSION);
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
public static class App {
|
||||
public final String packageName;
|
||||
public final String lastError;
|
||||
public final long lastMessageTimestamp;
|
||||
public final long totalMessageCount;
|
||||
public final long totalMessageBytes;
|
||||
public final boolean allowRegister;
|
||||
public final boolean wakeForDelivery;
|
||||
|
||||
private App(Cursor cursor) {
|
||||
packageName = cursor.getString(cursor.getColumnIndex(FIELD_PACKAGE_NAME));
|
||||
lastError = cursor.getString(cursor.getColumnIndex(FIELD_LAST_ERROR));
|
||||
lastMessageTimestamp = cursor.getLong(cursor.getColumnIndex(FIELD_LAST_MESSAGE_TIMESTAMP));
|
||||
totalMessageCount = cursor.getLong(cursor.getColumnIndex(FIELD_TOTAL_MESSAGE_COUNT));
|
||||
totalMessageBytes = cursor.getLong(cursor.getColumnIndex(FIELD_TOTAL_MESSAGE_BYTES));
|
||||
allowRegister = cursor.getLong(cursor.getColumnIndex(FIELD_ALLOW_REGISTER)) == 1;
|
||||
wakeForDelivery = cursor.getLong(cursor.getColumnIndex(FIELD_WAKE_FOR_DELIVERY)) == 1;
|
||||
}
|
||||
|
||||
public boolean hasError() {
|
||||
return !TextUtils.isEmpty(lastError);
|
||||
}
|
||||
}
|
||||
|
||||
public static class Registration {
|
||||
public final String packageName;
|
||||
public final String signature;
|
||||
public final long timestamp;
|
||||
public final String registerId;
|
||||
|
||||
public Registration(Cursor cursor) {
|
||||
packageName = cursor.getString(cursor.getColumnIndex(FIELD_PACKAGE_NAME));
|
||||
signature = cursor.getString(cursor.getColumnIndex(FIELD_SIGNATURE));
|
||||
timestamp = cursor.getLong(cursor.getColumnIndex(FIELD_TIMESTAMP));
|
||||
registerId = cursor.getString(cursor.getColumnIndex(FIELD_REGISTER_ID));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(SQLiteDatabase db) {
|
||||
db.execSQL(CREATE_TABLE_APPS);
|
||||
db.execSQL(CREATE_TABLE_REGISTRATIONS);
|
||||
importLegacyData(db);
|
||||
}
|
||||
|
||||
public synchronized List<App> getAppList() {
|
||||
SQLiteDatabase db = getReadableDatabase();
|
||||
Cursor cursor = db.query(TABLE_APPS, null, null, null, null, null, null);
|
||||
if (cursor != null) {
|
||||
List<App> result = new ArrayList<>();
|
||||
while (cursor.moveToNext()) {
|
||||
result.add(new App(cursor));
|
||||
}
|
||||
cursor.close();
|
||||
return result;
|
||||
}
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
public synchronized List<Registration> getRegistrationList() {
|
||||
SQLiteDatabase db = getReadableDatabase();
|
||||
Cursor cursor = db.query(TABLE_REGISTRATIONS, null, null, null, null, null, null);
|
||||
if (cursor != null) {
|
||||
List<Registration> result = new ArrayList<>();
|
||||
while (cursor.moveToNext()) {
|
||||
result.add(new Registration(cursor));
|
||||
}
|
||||
cursor.close();
|
||||
return result;
|
||||
}
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
|
||||
public synchronized List<Registration> getRegistrationsByApp(String packageName) {
|
||||
SQLiteDatabase db = getReadableDatabase();
|
||||
Cursor cursor = db.query(TABLE_REGISTRATIONS, null, FIELD_PACKAGE_NAME + " LIKE ?", new String[]{packageName}, null, null, null);
|
||||
if (cursor != null) {
|
||||
List<Registration> result = new ArrayList<>();
|
||||
while (cursor.moveToNext()) {
|
||||
result.add(new Registration(cursor));
|
||||
}
|
||||
cursor.close();
|
||||
return result;
|
||||
}
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
public synchronized void setAppAllowRegister(String packageName, boolean allowRegister) {
|
||||
SQLiteDatabase db = getWritableDatabase();
|
||||
ContentValues cv = new ContentValues();
|
||||
cv.put(FIELD_ALLOW_REGISTER, allowRegister ? 1 : 0);
|
||||
db.update(TABLE_APPS, cv, FIELD_PACKAGE_NAME + " LIKE ?", new String[]{packageName});
|
||||
}
|
||||
|
||||
public synchronized void setAppWakeForDelivery(String packageName, boolean wakeForDelivery) {
|
||||
SQLiteDatabase db = getWritableDatabase();
|
||||
ContentValues cv = new ContentValues();
|
||||
cv.put(FIELD_WAKE_FOR_DELIVERY, wakeForDelivery ? 1 : 0);
|
||||
db.update(TABLE_APPS, cv, FIELD_PACKAGE_NAME + " LIKE ?", new String[]{packageName});
|
||||
}
|
||||
|
||||
|
||||
public synchronized void removeApp(String packageName) {
|
||||
SQLiteDatabase db = getWritableDatabase();
|
||||
db.delete(TABLE_REGISTRATIONS, FIELD_PACKAGE_NAME + " LIKE ?", new String[]{packageName});
|
||||
db.delete(TABLE_APPS, FIELD_PACKAGE_NAME + " LIKE ?", new String[]{packageName});
|
||||
}
|
||||
|
||||
public synchronized void noteAppRegistrationError(String packageName, String error) {
|
||||
SQLiteDatabase db = getWritableDatabase();
|
||||
ContentValues cv = new ContentValues();
|
||||
cv.put(FIELD_LAST_ERROR, error);
|
||||
db.update(TABLE_APPS, cv, FIELD_PACKAGE_NAME + " LIKE ?", new String[]{packageName});
|
||||
}
|
||||
|
||||
public synchronized void noteAppKnown(String packageName, boolean allowRegister) {
|
||||
SQLiteDatabase db = getWritableDatabase();
|
||||
db.beginTransaction();
|
||||
|
||||
App app = getApp(db, packageName);
|
||||
ContentValues cv = new ContentValues();
|
||||
cv.put(FIELD_ALLOW_REGISTER, allowRegister);
|
||||
if (app == null) {
|
||||
cv.put(FIELD_PACKAGE_NAME, packageName);
|
||||
db.insert(TABLE_APPS, null, cv);
|
||||
} else {
|
||||
db.update(TABLE_APPS, cv, FIELD_PACKAGE_NAME + " LIKE ?", new String[]{packageName});
|
||||
}
|
||||
|
||||
db.setTransactionSuccessful();
|
||||
db.endTransaction();
|
||||
}
|
||||
|
||||
public synchronized void noteAppMessage(String packageName, int numBytes) {
|
||||
SQLiteDatabase db = getWritableDatabase();
|
||||
db.beginTransaction();
|
||||
|
||||
App app = getApp(db, packageName);
|
||||
ContentValues cv = new ContentValues();
|
||||
cv.put(FIELD_LAST_MESSAGE_TIMESTAMP, System.currentTimeMillis());
|
||||
if (app == null) {
|
||||
cv.put(FIELD_PACKAGE_NAME, packageName);
|
||||
cv.put(FIELD_TOTAL_MESSAGE_COUNT, 1);
|
||||
cv.put(FIELD_TOTAL_MESSAGE_BYTES, numBytes);
|
||||
db.insert(TABLE_APPS, null, cv);
|
||||
} else {
|
||||
cv.put(FIELD_TOTAL_MESSAGE_COUNT, app.totalMessageCount + 1);
|
||||
cv.put(FIELD_TOTAL_MESSAGE_BYTES, app.totalMessageBytes + numBytes);
|
||||
db.update(TABLE_APPS, cv, FIELD_PACKAGE_NAME + " LIKE ?", new String[]{packageName});
|
||||
}
|
||||
|
||||
db.setTransactionSuccessful();
|
||||
db.endTransaction();
|
||||
}
|
||||
|
||||
public synchronized void noteAppRegistered(String packageName, String signature, String registrationId) {
|
||||
SQLiteDatabase db = getWritableDatabase();
|
||||
db.beginTransaction();
|
||||
|
||||
App app = getApp(db, packageName);
|
||||
if (app == null) {
|
||||
ContentValues cv = new ContentValues();
|
||||
cv.put(FIELD_PACKAGE_NAME, packageName);
|
||||
db.insert(TABLE_APPS, null, cv);
|
||||
} else {
|
||||
ContentValues cv = new ContentValues();
|
||||
cv.put(FIELD_LAST_ERROR, "");
|
||||
db.update(TABLE_APPS, cv, FIELD_PACKAGE_NAME + " LIKE ?", new String[]{packageName});
|
||||
}
|
||||
|
||||
ContentValues cv = new ContentValues();
|
||||
cv.put(FIELD_PACKAGE_NAME, packageName);
|
||||
cv.put(FIELD_SIGNATURE, signature);
|
||||
cv.put(FIELD_REGISTER_ID, registrationId);
|
||||
cv.put(FIELD_TIMESTAMP, System.currentTimeMillis());
|
||||
db.insertWithOnConflict(TABLE_REGISTRATIONS, null, cv, SQLiteDatabase.CONFLICT_REPLACE);
|
||||
|
||||
db.setTransactionSuccessful();
|
||||
db.endTransaction();
|
||||
}
|
||||
|
||||
public synchronized void noteAppUnregistered(String packageName, String signature) {
|
||||
SQLiteDatabase db = getWritableDatabase();
|
||||
db.delete(TABLE_REGISTRATIONS, FIELD_PACKAGE_NAME + " LIKE ? AND " + FIELD_SIGNATURE + " LIKE ?", new String[]{packageName, signature});
|
||||
}
|
||||
|
||||
public App getApp(String packageName) {
|
||||
return getApp(getReadableDatabase(), packageName);
|
||||
}
|
||||
|
||||
private App getApp(SQLiteDatabase db, String packageName) {
|
||||
Cursor cursor = db.query(TABLE_APPS, null, FIELD_PACKAGE_NAME + " LIKE ?", new String[]{packageName}, null, null, null, "1");
|
||||
if (cursor != null) {
|
||||
try {
|
||||
if (cursor.moveToNext()) {
|
||||
return new App(cursor);
|
||||
}
|
||||
} finally {
|
||||
cursor.close();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public Registration getRegistration(String packageName, String signature) {
|
||||
return getRegistration(getReadableDatabase(), packageName, signature);
|
||||
}
|
||||
|
||||
private Registration getRegistration(SQLiteDatabase db, String packageName, String signature) {
|
||||
Cursor cursor = db.query(TABLE_REGISTRATIONS, null, FIELD_PACKAGE_NAME + " LIKE ? AND " + FIELD_SIGNATURE + " LIKE ?", new String[]{packageName, signature}, null, null, null, "1");
|
||||
if (cursor != null) {
|
||||
try {
|
||||
if (cursor.moveToNext()) {
|
||||
return new Registration(cursor);
|
||||
}
|
||||
} finally {
|
||||
cursor.close();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
private void importLegacyData(SQLiteDatabase db) {
|
||||
db.beginTransaction();
|
||||
|
||||
GcmLegacyData legacyData = new GcmLegacyData(context);
|
||||
for (GcmLegacyData.LegacyAppInfo appInfo : legacyData.getAppsInfo()) {
|
||||
ContentValues cv = new ContentValues();
|
||||
cv.put(FIELD_PACKAGE_NAME, appInfo.app);
|
||||
cv.put(FIELD_TOTAL_MESSAGE_COUNT, legacyData.getAppMessageCount(appInfo.app));
|
||||
cv.put(FIELD_LAST_ERROR, appInfo.hasUnregistrationError() ? "Unregistration error" : null);
|
||||
db.insert(TABLE_APPS, null, cv);
|
||||
cv.clear();
|
||||
if (appInfo.isRegistered()) {
|
||||
cv.put(FIELD_PACKAGE_NAME, appInfo.app);
|
||||
cv.put(FIELD_SIGNATURE, appInfo.appSignature);
|
||||
cv.put(FIELD_REGISTER_ID, appInfo.registerID);
|
||||
db.insert(TABLE_REGISTRATIONS, null, cv);
|
||||
}
|
||||
}
|
||||
|
||||
db.setTransactionSuccessful();
|
||||
db.endTransaction();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
|
||||
throw new IllegalStateException("Upgrades not supported");
|
||||
}
|
||||
|
||||
}
|
@ -23,20 +23,22 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
public class GcmData {
|
||||
@Deprecated
|
||||
public class GcmLegacyData {
|
||||
private static final String GCM_REGISTRATION_PREF = "gcm_registrations";
|
||||
private static final String GCM_MESSAGES_PREF = "gcm_messages";
|
||||
|
||||
private static final String REMOVED = "%%REMOVED%%";
|
||||
private static final String ERROR = "%%ERROR%%";
|
||||
static final String REMOVED = "%%REMOVED%%";
|
||||
static final String ERROR = "%%ERROR%%";
|
||||
|
||||
private Context context;
|
||||
|
||||
public GcmData(Context context) {
|
||||
public GcmLegacyData(Context context) {
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
public static class AppInfo implements Comparable<AppInfo> {
|
||||
@Deprecated
|
||||
public static class LegacyAppInfo implements Comparable<LegacyAppInfo> {
|
||||
public String app = null;
|
||||
public String appSignature = null;
|
||||
public String registerID = null;
|
||||
@ -46,7 +48,7 @@ public class GcmData {
|
||||
private final int STATE_REGISTERED = 3;
|
||||
private int state;
|
||||
|
||||
public AppInfo(String key, String value) {
|
||||
public LegacyAppInfo(String key, String value) {
|
||||
if (ERROR.equals(value)) {
|
||||
state = STATE_ERROR;
|
||||
} else if (REMOVED.equals(value)) {
|
||||
@ -73,42 +75,19 @@ public class GcmData {
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(AppInfo another) {
|
||||
public int compareTo(LegacyAppInfo another) {
|
||||
return app.compareTo(another.app);
|
||||
}
|
||||
}
|
||||
|
||||
public void noteAppRegistered(String app, String signature, String regId) {
|
||||
getInfoSharedPreferences().edit().putString(app + ":" + signature, regId).apply();
|
||||
}
|
||||
|
||||
public void noteAppRegistrationError(String app, String signature) {
|
||||
getInfoSharedPreferences().edit().putString(app + ":" + signature, "-").apply();
|
||||
}
|
||||
|
||||
public void noteAppUnregistered(String app, String signature) {
|
||||
getInfoSharedPreferences().edit().putString(app + ":" + signature, REMOVED).apply();
|
||||
}
|
||||
|
||||
public void noteAppUnregistrationError(String app, String signature) {
|
||||
getInfoSharedPreferences().edit().putString(app + ":" + signature, ERROR).apply();
|
||||
}
|
||||
|
||||
public void incrementAppMessageCount(String app, int i) {
|
||||
int messageCount = getStatsSharedPreferences().getInt(app, 0);
|
||||
getStatsSharedPreferences().edit().putInt(app, messageCount + i).apply();
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public int getAppMessageCount(String app) {
|
||||
return getStatsSharedPreferences().getInt(app, 0);
|
||||
}
|
||||
|
||||
public AppInfo getAppInfo(String app, String signature) {
|
||||
return getAppInfo(app + ":" + signature);
|
||||
}
|
||||
|
||||
public List<AppInfo> getAppsInfo() {
|
||||
ArrayList<AppInfo> ret = new ArrayList<>();
|
||||
@Deprecated
|
||||
public List<LegacyAppInfo> getAppsInfo() {
|
||||
ArrayList<LegacyAppInfo> ret = new ArrayList<>();
|
||||
Set<String> keys = getInfoSharedPreferences().getAll().keySet();
|
||||
for (String key : keys) {
|
||||
ret.add(getAppInfo(key));
|
||||
@ -116,8 +95,9 @@ public class GcmData {
|
||||
return ret;
|
||||
}
|
||||
|
||||
private AppInfo getAppInfo(String key) {
|
||||
return new AppInfo(key, getInfoSharedPreferences().getString(key, ""));
|
||||
@Deprecated
|
||||
private LegacyAppInfo getAppInfo(String key) {
|
||||
return new LegacyAppInfo(key, getInfoSharedPreferences().getString(key, ""));
|
||||
}
|
||||
|
||||
private SharedPreferences getInfoSharedPreferences() {
|
@ -25,9 +25,12 @@ import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
public class GcmPrefs implements SharedPreferences.OnSharedPreferenceChangeListener {
|
||||
private static final String PREF_GCM_HEARTBEAT = "gcm_heartbeat_interval";
|
||||
private static final String PREF_GCM_LOG = "gcm_full_log";
|
||||
private static final String PREF_LAST_PERSISTENT_ID = "gcm_last_persistent_id";
|
||||
public static final String PREF_HEARTBEAT = "gcm_heartbeat_interval";
|
||||
public static final String PREF_FULL_LOG = "gcm_full_log";
|
||||
public static final String PREF_LAST_PERSISTENT_ID = "gcm_last_persistent_id";
|
||||
public static final String PREF_CONFIRM_NEW_APPS = "gcm_confirm_new_apps";
|
||||
public static final String PREF_ENABLE_GCM = "gcm_enable_mcs_service";
|
||||
|
||||
private static GcmPrefs INSTANCE;
|
||||
|
||||
public static GcmPrefs get(Context context) {
|
||||
@ -41,6 +44,8 @@ public class GcmPrefs implements SharedPreferences.OnSharedPreferenceChangeListe
|
||||
private int heartbeatMs = 300000;
|
||||
private boolean gcmLogEnabled = true;
|
||||
private String lastPersistedId = "";
|
||||
private boolean confirmNewApps = false;
|
||||
private boolean gcmEnabled = false;
|
||||
|
||||
private SharedPreferences defaultPreferences;
|
||||
|
||||
@ -53,9 +58,11 @@ public class GcmPrefs implements SharedPreferences.OnSharedPreferenceChangeListe
|
||||
}
|
||||
|
||||
public void update() {
|
||||
heartbeatMs = Integer.parseInt(defaultPreferences.getString(PREF_GCM_HEARTBEAT, "300")) * 1000;
|
||||
gcmLogEnabled = defaultPreferences.getBoolean(PREF_GCM_LOG, true);
|
||||
heartbeatMs = Integer.parseInt(defaultPreferences.getString(PREF_HEARTBEAT, "300")) * 1000;
|
||||
gcmLogEnabled = defaultPreferences.getBoolean(PREF_FULL_LOG, true);
|
||||
lastPersistedId = defaultPreferences.getString(PREF_LAST_PERSISTENT_ID, "");
|
||||
confirmNewApps = defaultPreferences.getBoolean(PREF_CONFIRM_NEW_APPS, false);
|
||||
gcmEnabled = defaultPreferences.getBoolean(PREF_ENABLE_GCM, false);
|
||||
}
|
||||
|
||||
public int getHeartbeatMs() {
|
||||
@ -67,10 +74,18 @@ public class GcmPrefs implements SharedPreferences.OnSharedPreferenceChangeListe
|
||||
update();
|
||||
}
|
||||
|
||||
public boolean isGcmEnabled() {
|
||||
return gcmEnabled;
|
||||
}
|
||||
|
||||
public boolean isGcmLogEnabled() {
|
||||
return gcmLogEnabled;
|
||||
}
|
||||
|
||||
public boolean isConfirmNewApps() {
|
||||
return confirmNewApps;
|
||||
}
|
||||
|
||||
public List<String> getLastPersistedIds() {
|
||||
if (lastPersistedId.isEmpty()) return Collections.emptyList();
|
||||
return Arrays.asList(lastPersistedId.split("\\|"));
|
||||
|
@ -90,6 +90,7 @@ public class McsService extends Service implements Handler.Callback {
|
||||
private static final int WAKELOCK_TIMEOUT = 5000;
|
||||
|
||||
private static long lastHeartbeatAckElapsedRealtime = -1;
|
||||
private static long startTimestamp = 0;
|
||||
|
||||
private static Socket sslSocket;
|
||||
private static McsInputStream inputStream;
|
||||
@ -100,7 +101,7 @@ public class McsService extends Service implements Handler.Callback {
|
||||
private static HandlerThread handlerThread;
|
||||
private static Handler rootHandler;
|
||||
|
||||
private GcmData gcmStorage = new GcmData(this);
|
||||
private GcmDatabase database;
|
||||
|
||||
private AlarmManager alarmManager;
|
||||
private PowerManager powerManager;
|
||||
@ -139,6 +140,7 @@ public class McsService extends Service implements Handler.Callback {
|
||||
@Override
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
database = new GcmDatabase(this);
|
||||
heartbeatIntent = PendingIntent.getService(this, 0, new Intent(ACTION_HEARTBEAT, null, this, McsService.class), 0);
|
||||
alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
|
||||
powerManager = (PowerManager) getSystemService(POWER_SERVICE);
|
||||
@ -168,6 +170,10 @@ public class McsService extends Service implements Handler.Callback {
|
||||
return true;
|
||||
}
|
||||
|
||||
public static long getStartTimestamp() {
|
||||
return startTimestamp;
|
||||
}
|
||||
|
||||
public static void scheduleReconnect(Context context) {
|
||||
AlarmManager alarmManager = (AlarmManager) context.getSystemService(ALARM_SERVICE);
|
||||
long delay = getCurrentDelay();
|
||||
@ -240,6 +246,7 @@ public class McsService extends Service implements Handler.Callback {
|
||||
inputStream.start();
|
||||
outputStream.start();
|
||||
|
||||
startTimestamp = System.currentTimeMillis();
|
||||
lastHeartbeatAckElapsedRealtime = SystemClock.elapsedRealtime();
|
||||
scheduleHeartbeat(this);
|
||||
} catch (Exception e) {
|
||||
@ -305,27 +312,30 @@ public class McsService extends Service implements Handler.Callback {
|
||||
}
|
||||
|
||||
private void handleAppMessage(DataMessageStanza msg) {
|
||||
database.noteAppMessage(msg.category, msg.getSerializedSize());
|
||||
GcmDatabase.App app = database.getApp(msg.category);
|
||||
|
||||
Intent intent = new Intent();
|
||||
intent.setAction(ACTION_C2DM_RECEIVE);
|
||||
intent.setPackage(msg.category);
|
||||
intent.putExtra(EXTRA_FROM, msg.from);
|
||||
if (app.wakeForDelivery) intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
|
||||
if (msg.token != null) intent.putExtra(EXTRA_COLLAPSE_KEY, msg.token);
|
||||
for (AppData appData : msg.app_data) {
|
||||
intent.putExtra(appData.key, appData.value);
|
||||
}
|
||||
intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
|
||||
// FIXME: #75
|
||||
|
||||
List<ResolveInfo> infos = getPackageManager().queryBroadcastReceivers(intent, PackageManager.GET_RESOLVED_FILTER);
|
||||
if (infos == null || infos.isEmpty()) {
|
||||
logd("No target for message, wut?");
|
||||
} else {
|
||||
for (ResolveInfo resolveInfo : infos) {
|
||||
logd("Target: " + resolveInfo);
|
||||
Intent targetIntent = new Intent(intent);
|
||||
targetIntent.setComponent(new ComponentName(resolveInfo.activityInfo.packageName, resolveInfo.activityInfo.name));
|
||||
sendOrderedBroadcast(targetIntent, msg.category + ".permission.C2D_MESSAGE");
|
||||
}
|
||||
if (infos.isEmpty())
|
||||
logd("No target for message, wut?");
|
||||
|
||||
gcmStorage.incrementAppMessageCount(msg.category, 1);
|
||||
}
|
||||
}
|
||||
|
||||
private void handleSelfMessage(DataMessageStanza msg) {
|
||||
|
@ -16,22 +16,32 @@
|
||||
|
||||
package org.microg.gms.gcm;
|
||||
|
||||
import android.app.AlertDialog;
|
||||
import android.app.IntentService;
|
||||
import android.app.PendingIntent;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.os.Build;
|
||||
import android.os.Message;
|
||||
import android.os.Messenger;
|
||||
import android.text.Html;
|
||||
import android.util.Log;
|
||||
|
||||
import org.microg.gms.checkin.CheckinService;
|
||||
import org.microg.gms.checkin.LastCheckinInfo;
|
||||
import org.microg.gms.common.PackageUtils;
|
||||
import org.microg.gms.common.Utils;
|
||||
import org.microg.gms.ui.AskPushPermission;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import static android.os.Build.VERSION.SDK_INT;
|
||||
import static android.os.Build.VERSION_CODES.ICE_CREAM_SANDWICH;
|
||||
import static android.os.Build.VERSION_CODES.JELLY_BEAN;
|
||||
import static android.os.Build.VERSION_CODES.JELLY_BEAN_MR1;
|
||||
import static org.microg.gms.gcm.GcmConstants.ACTION_C2DM_REGISTER;
|
||||
import static org.microg.gms.gcm.GcmConstants.ACTION_C2DM_REGISTRATION;
|
||||
import static org.microg.gms.gcm.GcmConstants.ACTION_C2DM_UNREGISTER;
|
||||
@ -40,6 +50,7 @@ import static org.microg.gms.gcm.GcmConstants.EXTRA_APP;
|
||||
import static org.microg.gms.gcm.GcmConstants.EXTRA_DELETE;
|
||||
import static org.microg.gms.gcm.GcmConstants.EXTRA_ERROR;
|
||||
import static org.microg.gms.gcm.GcmConstants.EXTRA_MESSENGER;
|
||||
import static org.microg.gms.gcm.GcmConstants.EXTRA_PENDING_INTENT;
|
||||
import static org.microg.gms.gcm.GcmConstants.EXTRA_REGISTRATION_ID;
|
||||
import static org.microg.gms.gcm.GcmConstants.EXTRA_RETRY_AFTER;
|
||||
import static org.microg.gms.gcm.GcmConstants.EXTRA_SENDER;
|
||||
@ -49,30 +60,39 @@ public class PushRegisterService extends IntentService {
|
||||
private static final String TAG = "GmsGcmRegisterSvc";
|
||||
private static final String EXTRA_SKIP_TRY_CHECKIN = "skip_checkin";
|
||||
|
||||
private GcmData gcmStorage = new GcmData(this);
|
||||
private GcmDatabase database;
|
||||
private static boolean requestPending = false;
|
||||
|
||||
public PushRegisterService() {
|
||||
super(TAG);
|
||||
setIntentRedelivery(false);
|
||||
}
|
||||
|
||||
public static RegisterResponse register(Context context, String app, String appSignature, String sender, String info) {
|
||||
RegisterResponse response = register(context, app, appSignature, sender, info, false);
|
||||
@Override
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
database = new GcmDatabase(this);
|
||||
}
|
||||
|
||||
public static RegisterResponse register(Context context, String packageName, String pkgSignature, String sender, String info) {
|
||||
GcmDatabase database = new GcmDatabase(context);
|
||||
RegisterResponse response = register(context, packageName, pkgSignature, sender, info, false);
|
||||
String regId = response.token;
|
||||
if (regId != null) {
|
||||
(new GcmData(context)).noteAppRegistered(app, appSignature, regId);
|
||||
database.noteAppRegistered(packageName, pkgSignature, regId);
|
||||
} else {
|
||||
(new GcmData(context)).noteAppRegistrationError(app, appSignature);
|
||||
database.noteAppRegistrationError(packageName, response.responseText);
|
||||
}
|
||||
return response;
|
||||
}
|
||||
|
||||
public static RegisterResponse unregister(Context context, String app, String appSignature, String sender, String info) {
|
||||
RegisterResponse response = register(context, app, appSignature, sender, info, true);
|
||||
if (!app.equals(response.deleted)) {
|
||||
(new GcmData(context)).noteAppUnregistrationError(app, appSignature);
|
||||
public static RegisterResponse unregister(Context context, String packageName, String pkgSignature, String sender, String info) {
|
||||
GcmDatabase database = new GcmDatabase(context);
|
||||
RegisterResponse response = register(context, packageName, pkgSignature, sender, info, true);
|
||||
if (!packageName.equals(response.deleted)) {
|
||||
database.noteAppRegistrationError(packageName, response.responseText);
|
||||
} else {
|
||||
(new GcmData(context)).noteAppUnregistered(app, appSignature);
|
||||
database.noteAppUnregistered(packageName, pkgSignature);
|
||||
}
|
||||
return response;
|
||||
}
|
||||
@ -103,23 +123,49 @@ public class PushRegisterService extends IntentService {
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
private String packageFromPendingIntent(PendingIntent pi) {
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1) {
|
||||
if (SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1) {
|
||||
return pi.getTargetPackage();
|
||||
} else {
|
||||
return pi.getCreatorPackage();
|
||||
}
|
||||
}
|
||||
|
||||
private void register(Intent intent) {
|
||||
private void register(final Intent intent) {
|
||||
PendingIntent pendingIntent = intent.getParcelableExtra(EXTRA_APP);
|
||||
String sender = intent.getStringExtra(EXTRA_SENDER);
|
||||
String app = packageFromPendingIntent(pendingIntent);
|
||||
final String packageName = packageFromPendingIntent(pendingIntent);
|
||||
Log.d(TAG, "register[req]: " + intent.toString() + " extras=" + intent.getExtras());
|
||||
|
||||
Intent outIntent = new Intent(ACTION_C2DM_REGISTRATION);
|
||||
String appSignature = PackageUtils.firstSignatureDigest(this, app);
|
||||
GcmDatabase.App app = database.getApp(packageName);
|
||||
if (app == null && GcmPrefs.get(this).isConfirmNewApps()) {
|
||||
try {
|
||||
PackageManager pm = getPackageManager();
|
||||
ApplicationInfo info = pm.getApplicationInfo(packageName, 0);
|
||||
Intent i = new Intent(this, AskPushPermission.class);
|
||||
i.putExtra(EXTRA_PENDING_INTENT, intent);
|
||||
i.putExtra(EXTRA_APP, packageName);
|
||||
startActivity(i);
|
||||
} catch (PackageManager.NameNotFoundException e) {
|
||||
replyNotAvailable(this, intent, packageName);
|
||||
}
|
||||
} else if (app != null && !app.allowRegister) {
|
||||
replyNotAvailable(this, intent, packageName);
|
||||
} else {
|
||||
registerAndReply(this, intent, packageName);
|
||||
}
|
||||
}
|
||||
|
||||
String regId = register(this, app, appSignature, sender, null).token;
|
||||
public static void replyNotAvailable(Context context, Intent intent, String packageName) {
|
||||
Intent outIntent = new Intent(ACTION_C2DM_REGISTRATION);
|
||||
outIntent.putExtra(EXTRA_ERROR, ERROR_SERVICE_NOT_AVAILABLE);
|
||||
Log.d(TAG, "registration not allowed");
|
||||
sendReply(context, intent, packageName, outIntent);
|
||||
}
|
||||
|
||||
public static void registerAndReply(Context context, Intent intent, String packageName) {
|
||||
Intent outIntent = new Intent(ACTION_C2DM_REGISTRATION);
|
||||
String sender = intent.getStringExtra(EXTRA_SENDER);
|
||||
String appSignature = PackageUtils.firstSignatureDigest(context, packageName);
|
||||
String regId = register(context, packageName, appSignature, sender, null).token;
|
||||
if (regId != null) {
|
||||
outIntent.putExtra(EXTRA_REGISTRATION_ID, regId);
|
||||
} else {
|
||||
@ -127,6 +173,10 @@ public class PushRegisterService extends IntentService {
|
||||
}
|
||||
|
||||
Log.d(TAG, "register[res]: " + outIntent + " extras=" + outIntent.getExtras());
|
||||
sendReply(context, intent, packageName, outIntent);
|
||||
}
|
||||
|
||||
private static void sendReply(Context context, Intent intent, String packageName, Intent outIntent) {
|
||||
try {
|
||||
if (intent.hasExtra(EXTRA_MESSENGER)) {
|
||||
Messenger messenger = intent.getParcelableExtra(EXTRA_MESSENGER);
|
||||
@ -139,8 +189,8 @@ public class PushRegisterService extends IntentService {
|
||||
Log.w(TAG, e);
|
||||
}
|
||||
|
||||
outIntent.setPackage(app);
|
||||
sendOrderedBroadcast(outIntent, null);
|
||||
outIntent.setPackage(packageName);
|
||||
context.sendOrderedBroadcast(outIntent, null);
|
||||
}
|
||||
|
||||
public static RegisterResponse register(Context context, String app, String appSignature, String sender, String info, boolean delete) {
|
||||
@ -164,41 +214,28 @@ public class PushRegisterService extends IntentService {
|
||||
|
||||
private void unregister(Intent intent) {
|
||||
PendingIntent pendingIntent = intent.getParcelableExtra(EXTRA_APP);
|
||||
String app = packageFromPendingIntent(pendingIntent);
|
||||
String packageName = packageFromPendingIntent(pendingIntent);
|
||||
Log.d(TAG, "unregister[req]: " + intent.toString() + " extras=" + intent.getExtras());
|
||||
|
||||
Intent outIntent = new Intent(ACTION_C2DM_REGISTRATION);
|
||||
String appSignature = PackageUtils.firstSignatureDigest(this, app);
|
||||
String appSignature = PackageUtils.firstSignatureDigest(this, packageName);
|
||||
|
||||
if (!gcmStorage.getAppInfo(app, appSignature).isRemoved()) {
|
||||
outIntent.putExtra(EXTRA_UNREGISTERED, app);
|
||||
if (database.getRegistration(packageName, appSignature) == null) {
|
||||
outIntent.putExtra(EXTRA_UNREGISTERED, packageName);
|
||||
} else {
|
||||
RegisterResponse response = unregister(this, app, appSignature, null, null);
|
||||
if (!app.equals(response.deleted)) {
|
||||
RegisterResponse response = unregister(this, packageName, appSignature, null, null);
|
||||
if (!packageName.equals(response.deleted)) {
|
||||
outIntent.putExtra(EXTRA_ERROR, ERROR_SERVICE_NOT_AVAILABLE);
|
||||
|
||||
if (response.retryAfter != null && !response.retryAfter.contains(":")) {
|
||||
outIntent.putExtra(EXTRA_RETRY_AFTER, Long.parseLong(response.retryAfter));
|
||||
}
|
||||
} else {
|
||||
outIntent.putExtra(EXTRA_UNREGISTERED, app);
|
||||
outIntent.putExtra(EXTRA_UNREGISTERED, packageName);
|
||||
}
|
||||
}
|
||||
|
||||
Log.d(TAG, "unregister[res]: " + outIntent.toString() + " extras=" + outIntent.getExtras());
|
||||
try {
|
||||
if (intent.hasExtra(EXTRA_MESSENGER)) {
|
||||
Messenger messenger = intent.getParcelableExtra(EXTRA_MESSENGER);
|
||||
Message message = Message.obtain();
|
||||
message.obj = outIntent;
|
||||
messenger.send(message);
|
||||
return;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Log.w(TAG, e);
|
||||
}
|
||||
|
||||
outIntent.setPackage(app);
|
||||
sendOrderedBroadcast(outIntent, null);
|
||||
sendReply(this, intent, packageName, outIntent);
|
||||
}
|
||||
}
|
||||
|
@ -17,6 +17,7 @@
|
||||
package org.microg.gms.gcm;
|
||||
|
||||
import org.microg.gms.common.HttpFormClient.ResponseHeader;
|
||||
import org.microg.gms.common.HttpFormClient.ResponseStatusText;
|
||||
|
||||
import static org.microg.gms.common.HttpFormClient.ResponseField;
|
||||
|
||||
@ -27,6 +28,8 @@ public class RegisterResponse {
|
||||
public String retryAfter;
|
||||
@ResponseField("deleted")
|
||||
public String deleted;
|
||||
@ResponseStatusText
|
||||
public String responseText;
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
|
@ -32,14 +32,13 @@ import static org.microg.gms.gcm.McsConstants.EXTRA_REASON;
|
||||
|
||||
public class TriggerReceiver extends WakefulBroadcastReceiver {
|
||||
private static final String TAG = "GmsGcmTrigger";
|
||||
private static final String PREF_ENABLE_GCM = "gcm_enable_mcs_service";
|
||||
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
boolean force = "android.provider.Telephony.SECRET_CODE".equals(intent.getAction());
|
||||
ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
|
||||
|
||||
if (PreferenceManager.getDefaultSharedPreferences(context).getBoolean(PREF_ENABLE_GCM, false) || force) {
|
||||
if (GcmPrefs.get(context).isGcmEnabled() || force) {
|
||||
if (ConnectivityManager.CONNECTIVITY_ACTION.equals(intent.getAction())) {
|
||||
McsService.resetCurrentDelay();
|
||||
}
|
||||
|
@ -0,0 +1,21 @@
|
||||
package org.microg.gms.gcm;
|
||||
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.util.Log;
|
||||
|
||||
import static android.content.Intent.ACTION_PACKAGE_REMOVED;
|
||||
import static android.content.Intent.EXTRA_DATA_REMOVED;
|
||||
|
||||
public class UnregisterReceiver extends BroadcastReceiver {
|
||||
private static final String TAG = "GmsGcmUnregisterRcvr";
|
||||
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
Log.d(TAG, "Package removed: " + intent);
|
||||
if (ACTION_PACKAGE_REMOVED.contains(intent.getAction()) && intent.getBooleanExtra(EXTRA_DATA_REMOVED, false)) {
|
||||
Log.d(TAG, "Package removed: " + intent.getData());
|
||||
}
|
||||
}
|
||||
}
|
@ -33,6 +33,7 @@ import com.google.android.gms.people.internal.IPeopleCallbacks;
|
||||
import com.google.android.gms.people.internal.IPeopleService;
|
||||
import com.google.android.gms.people.model.AccountMetadata;
|
||||
|
||||
import org.microg.gms.auth.AuthConstants;
|
||||
import org.microg.gms.common.NonCancelToken;
|
||||
import org.microg.gms.common.PackageUtils;
|
||||
|
||||
@ -53,7 +54,7 @@ public class PeopleServiceImpl extends IPeopleService.Stub {
|
||||
PackageUtils.assertExtendedAccess(context);
|
||||
AccountManager accountManager = AccountManager.get(context);
|
||||
Bundle accountMetadata = new Bundle();
|
||||
String accountType = context.getString(R.string.google_account_type);
|
||||
String accountType = AuthConstants.DEFAULT_ACCOUNT_TYPE;
|
||||
for (Account account : accountManager.getAccountsByType(accountType)) {
|
||||
if (accountName == null || account.name.equals(accountName)) {
|
||||
accountMetadata.putParcelable(account.name, new AccountMetadata());
|
||||
|
@ -0,0 +1,50 @@
|
||||
/*
|
||||
* 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.gms.ui;
|
||||
|
||||
import android.support.v4.app.Fragment;
|
||||
|
||||
import org.microg.tools.ui.AbstractAboutFragment;
|
||||
import org.microg.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.gms.api", "microG GmsApi", "Apache License 2.0, microG Team"));
|
||||
libraries.add(new AbstractAboutFragment.Library("org.microg.safeparcel", "microG SafeParcel", "Apache License 2.0, microG Team"));
|
||||
libraries.add(new AbstractAboutFragment.Library("org.microg.nlp", "microG UnifiedNlp", "Apache License 2.0, microG Team"));
|
||||
libraries.add(new AbstractAboutFragment.Library("org.microg.nlp.api", "microG UnifiedNlp Api", "Apache License 2.0, microG Team"));
|
||||
libraries.add(new AbstractAboutFragment.Library("org.microg.wearable", "microG Wearable", "Apache License 2.0, microG Team"));
|
||||
libraries.add(new AbstractAboutFragment.Library("de.hdodenhof.circleimageview", "CircleImageView", "Apache License 2.0, Henning Dodenhof"));
|
||||
libraries.add(new AbstractAboutFragment.Library("org.oscim.android", "V™", "GNU LGPLv3, Hannes Janetzek and devemux86"));
|
||||
libraries.add(new AbstractAboutFragment.Library("com.squareup.wire", "Wire Protocol Buffers", "Apache License 2.0, Square Inc."));
|
||||
}
|
||||
|
||||
public static class AsActivity extends AbstractSettingsActivity {
|
||||
public AsActivity() {
|
||||
showHomeAsUp = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Fragment getFragment() {
|
||||
return new AboutFragment();
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Copyright (C) 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.gms.ui;
|
||||
|
||||
import com.google.android.gms.R;
|
||||
|
||||
import org.microg.tools.ui.AbstractSettingsActivity;
|
||||
|
||||
public class AccountSettingsActivity extends AbstractSettingsActivity {
|
||||
public AccountSettingsActivity() {
|
||||
preferencesResource = R.xml.preferences_account;
|
||||
}
|
||||
}
|
@ -0,0 +1,88 @@
|
||||
package org.microg.gms.ui;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.FragmentActivity;
|
||||
import android.text.Html;
|
||||
import android.view.View;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.google.android.gms.R;
|
||||
|
||||
import org.microg.gms.gcm.GcmDatabase;
|
||||
import org.microg.gms.gcm.PushRegisterService;
|
||||
|
||||
import static org.microg.gms.gcm.GcmConstants.EXTRA_APP;
|
||||
import static org.microg.gms.gcm.GcmConstants.EXTRA_PENDING_INTENT;
|
||||
|
||||
public class AskPushPermission extends FragmentActivity {
|
||||
|
||||
private GcmDatabase database;
|
||||
|
||||
private String packageName;
|
||||
private Intent intent;
|
||||
private boolean answered;
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
database = new GcmDatabase(this);
|
||||
|
||||
packageName = getIntent().getStringExtra(EXTRA_APP);
|
||||
intent = getIntent().getParcelableExtra(EXTRA_PENDING_INTENT);
|
||||
|
||||
if (database.getApp(packageName) != null) {
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
|
||||
setContentView(R.layout.ask_gcm);
|
||||
|
||||
try {
|
||||
PackageManager pm = getPackageManager();
|
||||
final ApplicationInfo info = pm.getApplicationInfo(packageName, 0);
|
||||
CharSequence label = pm.getApplicationLabel(info);
|
||||
|
||||
((TextView) findViewById(R.id.permission_message)).setText(Html.fromHtml("Allow <b>" + label + "</b> to register for push notifications?"));
|
||||
findViewById(R.id.permission_allow_button).setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if (answered) return;
|
||||
database.noteAppKnown(packageName, true);
|
||||
answered = true;
|
||||
new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
PushRegisterService.registerAndReply(AskPushPermission.this, intent, packageName);
|
||||
}
|
||||
}).start();
|
||||
finish();
|
||||
}
|
||||
});
|
||||
findViewById(R.id.permission_deny_button).setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if (answered) return;
|
||||
database.noteAppKnown(packageName, false);
|
||||
answered = true;
|
||||
PushRegisterService.replyNotAvailable(AskPushPermission.this, intent, packageName);
|
||||
finish();
|
||||
}
|
||||
});
|
||||
} catch (PackageManager.NameNotFoundException e) {
|
||||
finish();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStop() {
|
||||
super.onStop();
|
||||
if (!answered) {
|
||||
PushRegisterService.replyNotAvailable(AskPushPermission.this, intent, packageName);
|
||||
answered = true;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,86 @@
|
||||
/*
|
||||
* Copyright (C) 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.gms.ui;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.os.PowerManager;
|
||||
import android.provider.Settings;
|
||||
import android.support.v4.app.ActivityCompat;
|
||||
import android.support.v4.content.ContextCompat;
|
||||
import android.view.View;
|
||||
|
||||
import com.google.android.gms.R;
|
||||
|
||||
import org.microg.gms.gcm.GcmPrefs;
|
||||
import org.microg.tools.ui.Condition;
|
||||
|
||||
import static android.Manifest.permission.ACCESS_COARSE_LOCATION;
|
||||
import static android.Manifest.permission.GET_ACCOUNTS;
|
||||
import static android.Manifest.permission.READ_PHONE_STATE;
|
||||
import static android.Manifest.permission.WRITE_EXTERNAL_STORAGE;
|
||||
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
|
||||
import static android.os.Build.VERSION.SDK_INT;
|
||||
|
||||
public class Conditions {
|
||||
public static final Condition GCM_BATTERY_OPTIMIZATIONS = new Condition.Builder()
|
||||
.title(R.string.cond_gcm_bat_title)
|
||||
.summary(R.string.cond_gcm_bat_summary)
|
||||
.evaluation(new Condition.Evaluation() {
|
||||
@Override
|
||||
public boolean isActive(Context context) {
|
||||
if (SDK_INT < 23) return false;
|
||||
if (!GcmPrefs.get(context).isGcmEnabled()) return false;
|
||||
PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
|
||||
return !pm.isIgnoringBatteryOptimizations(context.getPackageName());
|
||||
}
|
||||
})
|
||||
.firstAction(R.string.cond_gcm_bat_action, new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if (SDK_INT < 23) return;
|
||||
Intent intent = new Intent(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS);
|
||||
intent.setData(Uri.parse("package:" + v.getContext().getPackageName()));
|
||||
v.getContext().startActivity(intent);
|
||||
}
|
||||
}).build();
|
||||
|
||||
private static final String[] REQUIRED_PERMISSIONS = new String[]{ACCESS_COARSE_LOCATION, WRITE_EXTERNAL_STORAGE, GET_ACCOUNTS, READ_PHONE_STATE};
|
||||
public static final Condition PERMISSIONS = new Condition.Builder()
|
||||
.title(R.string.cond_perm_title)
|
||||
.summary(R.string.cond_perm_summary)
|
||||
.evaluation(new Condition.Evaluation() {
|
||||
@Override
|
||||
public boolean isActive(Context context) {
|
||||
for (String permission : REQUIRED_PERMISSIONS) {
|
||||
if (ContextCompat.checkSelfPermission(context, permission) != PERMISSION_GRANTED)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
})
|
||||
.firstAction(R.string.cond_perm_action, new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if (v.getContext() instanceof Activity) {
|
||||
ActivityCompat.requestPermissions((Activity) v.getContext(), REQUIRED_PERMISSIONS, 0);
|
||||
}
|
||||
}
|
||||
}).build();
|
||||
}
|
@ -0,0 +1,202 @@
|
||||
package org.microg.gms.ui;
|
||||
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.provider.Settings;
|
||||
import android.support.v14.preference.SwitchPreference;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.v7.app.AlertDialog;
|
||||
import android.support.v7.preference.Preference;
|
||||
import android.support.v7.preference.PreferenceScreen;
|
||||
import android.text.format.DateUtils;
|
||||
import android.view.View;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.google.android.gms.R;
|
||||
|
||||
import org.microg.gms.gcm.GcmDatabase;
|
||||
import org.microg.gms.gcm.PushRegisterService;
|
||||
import org.microg.tools.ui.AbstractSettingsActivity;
|
||||
import org.microg.tools.ui.ResourceSettingsFragment;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static android.text.format.DateUtils.FORMAT_SHOW_TIME;
|
||||
import static android.text.format.DateUtils.MINUTE_IN_MILLIS;
|
||||
import static android.text.format.DateUtils.WEEK_IN_MILLIS;
|
||||
|
||||
public class GcmAppFragment extends ResourceSettingsFragment {
|
||||
public static final String EXTRA_PACKAGE_NAME = "package_name";
|
||||
|
||||
public static final String PREF_WAKE_FOR_DELIVERY = "gcm_app_wake_for_delivery";
|
||||
public static final String PREF_ALLOW_REGISTER = "gcm_app_allow_register";
|
||||
public static final String PREF_REGISTER_DETAILS = "gcm_app_register_details";
|
||||
public static final String PREF_MESSAGE_DETAILS = "gcm_app_message_details";
|
||||
|
||||
protected String packageName;
|
||||
private String appName;
|
||||
private GcmDatabase database;
|
||||
|
||||
public GcmAppFragment() {
|
||||
preferencesResource = R.xml.preferences_gcm_app_detail;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityCreated(Bundle savedInstanceState) {
|
||||
super.onActivityCreated(savedInstanceState);
|
||||
packageName = getArguments().getString(EXTRA_PACKAGE_NAME);
|
||||
|
||||
AbstractSettingsActivity activity = (AbstractSettingsActivity) getActivity();
|
||||
|
||||
if (packageName != null && activity != null) {
|
||||
activity.setCustomBarLayout(R.layout.app_bar);
|
||||
try {
|
||||
PackageManager pm = activity.getPackageManager();
|
||||
ApplicationInfo info = pm.getApplicationInfo(packageName, 0);
|
||||
((ImageView) activity.findViewById(R.id.app_icon)).setImageDrawable(pm.getApplicationIcon(info));
|
||||
appName = pm.getApplicationLabel(info).toString();
|
||||
((TextView) activity.findViewById(R.id.app_name)).setText(appName);
|
||||
View view = activity.findViewById(R.id.app_bar);
|
||||
view.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
Intent intent = new Intent();
|
||||
intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
|
||||
Uri uri = Uri.fromParts("package", packageName, null);
|
||||
intent.setData(uri);
|
||||
getContext().startActivity(intent);
|
||||
}
|
||||
});
|
||||
view.setClickable(true);
|
||||
} catch (Exception e) {
|
||||
((TextView) activity.findViewById(R.id.app_name)).setText(packageName);
|
||||
}
|
||||
}
|
||||
|
||||
database = new GcmDatabase(getContext());
|
||||
updateAppDetails();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
if (database != null) {
|
||||
updateAppDetails();
|
||||
}
|
||||
}
|
||||
|
||||
private void updateAppDetails() {
|
||||
GcmDatabase.App app = database.getApp(packageName);
|
||||
PreferenceScreen root = getPreferenceScreen();
|
||||
|
||||
SwitchPreference wakeForDelivery = (SwitchPreference) root.findPreference(PREF_WAKE_FOR_DELIVERY);
|
||||
wakeForDelivery.setChecked(app.wakeForDelivery);
|
||||
wakeForDelivery.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
|
||||
@Override
|
||||
public boolean onPreferenceChange(Preference preference, Object newValue) {
|
||||
if (newValue instanceof Boolean) {
|
||||
database.setAppWakeForDelivery(packageName, (Boolean) newValue);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
SwitchPreference allowRegister = (SwitchPreference) root.findPreference(PREF_ALLOW_REGISTER);
|
||||
allowRegister.setChecked(app.allowRegister);
|
||||
allowRegister.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
|
||||
@Override
|
||||
public boolean onPreferenceChange(Preference preference, Object newValue) {
|
||||
if (newValue instanceof Boolean) {
|
||||
database.setAppAllowRegister(packageName, (Boolean) newValue);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
Preference registerDetails = root.findPreference(PREF_REGISTER_DETAILS);
|
||||
final List<GcmDatabase.Registration> registrations = database.getRegistrationsByApp(packageName);
|
||||
if (registrations.isEmpty()) {
|
||||
registerDetails.setTitle("");
|
||||
registerDetails.setSelectable(false);
|
||||
registerDetails.setSummary(R.string.gcm_not_registered);
|
||||
} else {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (GcmDatabase.Registration registration : registrations) {
|
||||
if (sb.length() != 0) sb.append("\n");
|
||||
if (registration.timestamp == 0) {
|
||||
sb.append(getString(R.string.gcm_registered));
|
||||
} else {
|
||||
sb.append(getString(R.string.gcm_registered_since, DateUtils.getRelativeDateTimeString(getContext(), registration.timestamp, MINUTE_IN_MILLIS, WEEK_IN_MILLIS, FORMAT_SHOW_TIME)));
|
||||
}
|
||||
}
|
||||
registerDetails.setTitle(R.string.gcm_unregister_app);
|
||||
registerDetails.setSummary(sb.toString());
|
||||
registerDetails.setSelectable(true);
|
||||
registerDetails.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
|
||||
@Override
|
||||
public boolean onPreferenceClick(Preference preference) {
|
||||
new AlertDialog.Builder(getContext())
|
||||
.setTitle(String.format(getString(R.string.gcm_unregister_confirm_title), appName))
|
||||
.setMessage(R.string.gcm_unregister_confirm_message)
|
||||
.setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
for (GcmDatabase.Registration registration : registrations) {
|
||||
PushRegisterService.unregister(getContext(), registration.packageName, registration.signature, null, null);
|
||||
}
|
||||
getActivity().runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
updateAppDetails();
|
||||
}
|
||||
});
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
})
|
||||
.setNegativeButton(android.R.string.no, new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
// Do nothing
|
||||
}
|
||||
}).create().show();
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
Preference messageDetails = root.findPreference(PREF_MESSAGE_DETAILS);
|
||||
if (app.totalMessageCount == 0) {
|
||||
messageDetails.setSummary(R.string.gcm_no_message_yet);
|
||||
} else {
|
||||
String s = getString(R.string.gcm_messages_counter, app.totalMessageCount, app.totalMessageBytes);
|
||||
if (app.lastMessageTimestamp != 0) {
|
||||
s += "\n" + getString(R.string.gcm_last_message_at, DateUtils.getRelativeDateTimeString(getContext(), app.lastMessageTimestamp, MINUTE_IN_MILLIS, WEEK_IN_MILLIS, FORMAT_SHOW_TIME));
|
||||
}
|
||||
messageDetails.setSummary(s);
|
||||
}
|
||||
}
|
||||
|
||||
public static class AsActivity extends AbstractSettingsActivity {
|
||||
public AsActivity() {
|
||||
showHomeAsUp = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Fragment getFragment() {
|
||||
GcmAppFragment fragment = new GcmAppFragment();
|
||||
fragment.setArguments(getIntent().getExtras());
|
||||
return fragment;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,262 @@
|
||||
/*
|
||||
* Copyright 2013-2015 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.gms.ui;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.v7.preference.Preference;
|
||||
import android.support.v7.preference.PreferenceCategory;
|
||||
import android.support.v7.preference.PreferenceGroup;
|
||||
import android.support.v7.preference.PreferenceScreen;
|
||||
import android.support.v7.preference.PreferenceViewHolder;
|
||||
import android.support.v7.widget.SwitchCompat;
|
||||
import android.text.format.DateUtils;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuInflater;
|
||||
import android.view.MenuItem;
|
||||
|
||||
import com.google.android.gms.R;
|
||||
|
||||
import org.microg.gms.gcm.GcmDatabase;
|
||||
import org.microg.gms.gcm.GcmPrefs;
|
||||
import org.microg.gms.gcm.McsService;
|
||||
import org.microg.tools.ui.AbstractSettingsActivity;
|
||||
import org.microg.tools.ui.DimmableIconPreference;
|
||||
import org.microg.tools.ui.ResourceSettingsFragment;
|
||||
import org.microg.tools.ui.SwitchBar;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
|
||||
import static android.text.format.DateUtils.FORMAT_SHOW_TIME;
|
||||
import static android.text.format.DateUtils.MINUTE_IN_MILLIS;
|
||||
import static android.text.format.DateUtils.WEEK_IN_MILLIS;
|
||||
|
||||
public class GcmFragment extends ResourceSettingsFragment implements SwitchBar.OnSwitchChangeListener {
|
||||
|
||||
public static final String PREF_GCM_STATUS = "pref_gcm_status";
|
||||
public static final String PREF_GCM_APPS = "gcm_apps";
|
||||
|
||||
private GcmDatabase database;
|
||||
|
||||
private SwitchBar switchBar;
|
||||
private SwitchCompat switchCompat;
|
||||
private boolean listenerSetup = false;
|
||||
|
||||
private final int MENU_ADVANCED = Menu.FIRST;
|
||||
|
||||
public GcmFragment() {
|
||||
preferencesResource = R.xml.preferences_gcm;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
|
||||
super.onActivityCreated(savedInstanceState);
|
||||
|
||||
AbstractSettingsActivity activity = (AbstractSettingsActivity) getActivity();
|
||||
|
||||
setHasOptionsMenu(true);
|
||||
switchBar = activity.getSwitchBar();
|
||||
switchBar.show();
|
||||
switchCompat = switchBar.getSwitch();
|
||||
switchBar.setChecked(GcmPrefs.get(getContext()).isGcmEnabled());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreatePreferencesFix(@Nullable Bundle savedInstanceState, String rootKey) {
|
||||
super.onCreatePreferencesFix(savedInstanceState, rootKey);
|
||||
|
||||
database = new GcmDatabase(getContext());
|
||||
|
||||
updateContent();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroyView() {
|
||||
super.onDestroyView();
|
||||
switchBar.hide();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
if (!listenerSetup) {
|
||||
switchBar.addOnSwitchChangeListener(this);
|
||||
listenerSetup = true;
|
||||
}
|
||||
updateContent();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
if (listenerSetup) {
|
||||
switchBar.removeOnSwitchChangeListener(this);
|
||||
listenerSetup = false;
|
||||
}
|
||||
super.onPause();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
|
||||
menu.add(0, MENU_ADVANCED, 0, R.string.menu_advanced);
|
||||
super.onCreateOptionsMenu(menu, inflater);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
switch (item.getItemId()) {
|
||||
case MENU_ADVANCED:
|
||||
Intent intent = new Intent(getContext(), AdvancedAsActivity.class);
|
||||
startActivity(intent);
|
||||
return true;
|
||||
default:
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSwitchChanged(SwitchCompat switchView, boolean isChecked) {
|
||||
if (switchView == switchCompat) {
|
||||
getPreferenceManager().getSharedPreferences().edit().putBoolean(GcmPrefs.PREF_ENABLE_GCM, isChecked).apply();
|
||||
}
|
||||
}
|
||||
|
||||
private static void addPreferencesSorted(List<Preference> prefs, PreferenceGroup container) {
|
||||
// If there's some items to display, sort the items and add them to the container.
|
||||
Collections.sort(prefs, new Comparator<Preference>() {
|
||||
@Override
|
||||
public int compare(Preference lhs, Preference rhs) {
|
||||
return lhs.getTitle().toString().compareTo(rhs.getTitle().toString());
|
||||
}
|
||||
});
|
||||
for (Preference entry : prefs) {
|
||||
container.addPreference(entry);
|
||||
}
|
||||
}
|
||||
|
||||
private void updateContent() {
|
||||
PreferenceScreen root = getPreferenceScreen();
|
||||
|
||||
if (McsService.isConnected()) {
|
||||
root.findPreference(PREF_GCM_STATUS).setSummary(getString(R.string.gcm_state_connected, DateUtils.getRelativeTimeSpanString(McsService.getStartTimestamp(), System.currentTimeMillis(), 0)));
|
||||
} else {
|
||||
root.findPreference(PREF_GCM_STATUS).setSummary(getString(R.string.gcm_state_disconnected));
|
||||
}
|
||||
|
||||
PreferenceCategory appList = (PreferenceCategory) root.findPreference(PREF_GCM_APPS);
|
||||
appList.removeAll();
|
||||
List<GcmDatabase.App> list = database.getAppList();
|
||||
if (!list.isEmpty()) {
|
||||
List<Preference> appListPrefs = new ArrayList<>();
|
||||
PackageManager pm = getContext().getPackageManager();
|
||||
for (GcmDatabase.App app : list) {
|
||||
try {
|
||||
pm.getApplicationInfo(app.packageName, 0);
|
||||
appListPrefs.add(new GcmAppPreference(getPreferenceManager().getContext(), app));
|
||||
} catch (PackageManager.NameNotFoundException e) {
|
||||
final List<GcmDatabase.Registration> registrations = database.getRegistrationsByApp(app.packageName);
|
||||
if (registrations.isEmpty()) {
|
||||
database.removeApp(app.packageName);
|
||||
} else {
|
||||
appListPrefs.add(new GcmAppPreference(getPreferenceManager().getContext(), app));
|
||||
}
|
||||
}
|
||||
}
|
||||
addPreferencesSorted(appListPrefs, appList);
|
||||
} else {
|
||||
// If there's no item to display, add a "None" item.
|
||||
Preference banner = new Preference(getPreferenceManager().getContext());
|
||||
banner.setLayoutResource(R.layout.list_no_item);
|
||||
banner.setTitle(R.string.list_no_item_none);
|
||||
banner.setSelectable(false);
|
||||
appList.addPreference(banner);
|
||||
}
|
||||
}
|
||||
|
||||
public static class GcmAppPreference extends DimmableIconPreference implements Preference.OnPreferenceClickListener {
|
||||
|
||||
private GcmDatabase database;
|
||||
private GcmDatabase.App app;
|
||||
|
||||
public GcmAppPreference(Context context, GcmDatabase.App app) {
|
||||
super(context);
|
||||
this.app = app;
|
||||
this.database = new GcmDatabase(context);
|
||||
setKey(app.packageName);
|
||||
|
||||
PackageManager packageManager = context.getPackageManager();
|
||||
try {
|
||||
ApplicationInfo applicationInfo = packageManager.getApplicationInfo(app.packageName, 0);
|
||||
setTitle(packageManager.getApplicationLabel(applicationInfo));
|
||||
setIcon(packageManager.getApplicationIcon(applicationInfo));
|
||||
} catch (PackageManager.NameNotFoundException e) {
|
||||
setTitle(app.packageName);
|
||||
}
|
||||
setOnPreferenceClickListener(this);
|
||||
updateViewDetails();
|
||||
}
|
||||
|
||||
private void updateViewDetails() {
|
||||
if (database.getRegistrationsByApp(app.packageName).isEmpty()) {
|
||||
setSummary(R.string.gcm_not_registered);
|
||||
} else if (app.lastMessageTimestamp > 0) {
|
||||
setSummary(getContext().getString(R.string.gcm_last_message_at, DateUtils.getRelativeDateTimeString(getContext(), app.lastMessageTimestamp, MINUTE_IN_MILLIS, WEEK_IN_MILLIS, FORMAT_SHOW_TIME)));
|
||||
} else {
|
||||
setSummary(R.string.gcm_no_message_yet);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(PreferenceViewHolder view) {
|
||||
updateViewDetails();
|
||||
super.onBindViewHolder(view);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onPreferenceClick(Preference preference) {
|
||||
Intent intent = new Intent(getContext(), GcmAppFragment.AsActivity.class);
|
||||
intent.putExtra(GcmAppFragment.EXTRA_PACKAGE_NAME, app.packageName);
|
||||
getContext().startActivity(intent);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public static class AsActivity extends AbstractSettingsActivity {
|
||||
public AsActivity() {
|
||||
showHomeAsUp = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Fragment getFragment() {
|
||||
return new GcmFragment();
|
||||
}
|
||||
}
|
||||
|
||||
public static class AdvancedAsActivity extends AbstractSettingsActivity {
|
||||
public AdvancedAsActivity() {
|
||||
showHomeAsUp = true;
|
||||
preferencesResource = R.xml.preferences_gcm_advanced;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,163 +0,0 @@
|
||||
/*
|
||||
* Copyright 2013-2015 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.gms.ui;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.view.ContextMenu;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.MenuInflater;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.AdapterView;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.ListView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.google.android.gms.R;
|
||||
|
||||
import org.microg.gms.gcm.GcmData;
|
||||
import org.microg.gms.gcm.PushRegisterService;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class GcmRegisteredAppsFragment extends Fragment {
|
||||
|
||||
private AppsAdapter appsAdapter = null;
|
||||
private GcmData gcmStorage = null;
|
||||
|
||||
@Override
|
||||
@NonNull
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||
gcmStorage = new GcmData(getContext());
|
||||
|
||||
View view = inflater.inflate(R.layout.gcm_apps_list, container, false);
|
||||
ListView listView = (ListView) view.findViewById(R.id.list_view);
|
||||
registerForContextMenu(listView);
|
||||
updateListView();
|
||||
listView.setAdapter(appsAdapter);
|
||||
return listView;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
updateListView();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
|
||||
GcmData.AppInfo appInfo = appsAdapter.getItem(((AdapterView.AdapterContextMenuInfo) menuInfo).position);
|
||||
MenuInflater menuInflater = getActivity().getMenuInflater();
|
||||
menuInflater.inflate(R.menu.gcm_app, menu);
|
||||
|
||||
PackageManager packageManager = getContext().getPackageManager();
|
||||
try {
|
||||
ApplicationInfo applicationInfo = packageManager.getApplicationInfo(appInfo.app, 0);
|
||||
menu.setHeaderTitle(packageManager.getApplicationLabel(applicationInfo));
|
||||
} catch (PackageManager.NameNotFoundException e) {
|
||||
menu.setHeaderTitle(appInfo.app);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onContextItemSelected(MenuItem item) {
|
||||
AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) item.getMenuInfo();
|
||||
final GcmData.AppInfo appInfo = appsAdapter.getItem(info.position);
|
||||
|
||||
new AsyncTask<Void, Void, Void>() {
|
||||
|
||||
@Override
|
||||
protected Void doInBackground(Void... params) {
|
||||
PushRegisterService.unregister(getContext(), appInfo.app, appInfo.appSignature, null, null);
|
||||
return null;
|
||||
}
|
||||
|
||||
protected void onPostExecute(Void result) {
|
||||
updateListView();
|
||||
}
|
||||
}.execute();
|
||||
return true;
|
||||
}
|
||||
|
||||
public synchronized void updateListView() {
|
||||
ArrayList<GcmData.AppInfo> registeredApps = new ArrayList<GcmData.AppInfo>();
|
||||
for (GcmData.AppInfo appInfo : gcmStorage.getAppsInfo()) {
|
||||
if (appInfo.isRegistered()) {
|
||||
registeredApps.add(appInfo);
|
||||
}
|
||||
}
|
||||
if (appsAdapter != null) {
|
||||
appsAdapter.update(registeredApps.toArray(new GcmData.AppInfo[registeredApps.size()]));
|
||||
} else {
|
||||
appsAdapter = new AppsAdapter(getContext(), registeredApps.toArray(new GcmData.AppInfo[registeredApps.size()]));
|
||||
}
|
||||
}
|
||||
|
||||
private class AppsAdapter extends ArrayAdapter<GcmData.AppInfo> {
|
||||
|
||||
public AppsAdapter(Context context, GcmData.AppInfo[] libraries) {
|
||||
super(context, R.layout.gcm_app, R.id.title);
|
||||
addAll(libraries);
|
||||
}
|
||||
|
||||
@Override
|
||||
public View getView(int position, View convertView, ViewGroup parent) {
|
||||
View v = super.getView(position, convertView, parent);
|
||||
ImageView image = (ImageView) v.findViewById(R.id.image);
|
||||
TextView title = (TextView) v.findViewById(R.id.title);
|
||||
TextView sub = (TextView) v.findViewById(R.id.sub);
|
||||
TextView warning = (TextView) v.findViewById(R.id.warning);
|
||||
|
||||
GcmData.AppInfo appInfo = getItem(position);
|
||||
PackageManager packageManager = getContext().getPackageManager();
|
||||
try {
|
||||
ApplicationInfo applicationInfo = packageManager.getApplicationInfo(appInfo.app, 0);
|
||||
title.setText(packageManager.getApplicationLabel(applicationInfo).toString());
|
||||
image.setImageDrawable(packageManager.getApplicationIcon(applicationInfo));
|
||||
if (appInfo.hasUnregistrationError()) {
|
||||
warning.setVisibility(View.VISIBLE);
|
||||
warning.setText(getString(R.string.gcm_app_error_unregistering));
|
||||
} else {
|
||||
warning.setVisibility(View.GONE);
|
||||
}
|
||||
} catch (PackageManager.NameNotFoundException e) {
|
||||
title.setText(appInfo.app);
|
||||
image.setImageDrawable(null);
|
||||
warning.setVisibility(View.VISIBLE);
|
||||
warning.setText(getString(R.string.gcm_app_not_installed_anymore));
|
||||
}
|
||||
sub.setText(getString(R.string.gcm_messages_received_no, gcmStorage.getAppMessageCount(appInfo.app)));
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
public void update(GcmData.AppInfo[] appInfos) {
|
||||
setNotifyOnChange(false);
|
||||
clear();
|
||||
addAll(appInfos);
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,22 @@
|
||||
/*
|
||||
* Copyright (C) 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.gms.ui;
|
||||
|
||||
import android.app.Activity;
|
||||
|
||||
public class LocationSettingsActivity extends Activity {
|
||||
}
|
@ -25,6 +25,7 @@ import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.v4.app.ActivityCompat;
|
||||
import android.support.v4.view.MenuItemCompat;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.support.v7.widget.SearchView;
|
||||
import android.support.v7.widget.Toolbar;
|
||||
@ -153,7 +154,7 @@ public class PlacePickerActivity extends AppCompatActivity implements Map.Update
|
||||
super.onCreateOptionsMenu(menu);
|
||||
MenuInflater inflater = getMenuInflater();
|
||||
inflater.inflate(R.menu.pick_place, menu);
|
||||
SearchView searchView = (SearchView) menu.findItem(R.id.menu_action_search).getActionView();
|
||||
SearchView searchView = (SearchView) MenuItemCompat.getActionView(menu.findItem(R.id.menu_action_search));
|
||||
// TODO: search
|
||||
return true;
|
||||
}
|
||||
|
@ -0,0 +1,83 @@
|
||||
/*
|
||||
* 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.gms.ui;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.os.Build;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.view.LayoutInflater;
|
||||
|
||||
import org.microg.tools.selfcheck.InstalledPackagesChecks;
|
||||
import org.microg.tools.selfcheck.NlpOsCompatChecks;
|
||||
import org.microg.tools.selfcheck.NlpStatusChecks;
|
||||
import org.microg.tools.selfcheck.PermissionCheckGroup;
|
||||
import org.microg.tools.selfcheck.RomSpoofSignatureChecks;
|
||||
import org.microg.tools.selfcheck.SelfCheckGroup;
|
||||
import org.microg.tools.selfcheck.SystemChecks;
|
||||
import org.microg.tools.ui.AbstractSelfCheckFragment;
|
||||
import org.microg.tools.ui.AbstractSettingsActivity;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static android.Manifest.permission.ACCESS_COARSE_LOCATION;
|
||||
import static android.Manifest.permission.GET_ACCOUNTS;
|
||||
import static android.Manifest.permission.READ_PHONE_STATE;
|
||||
import static android.Manifest.permission.WRITE_EXTERNAL_STORAGE;
|
||||
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) {
|
||||
checks.add(new RomSpoofSignatureChecks());
|
||||
checks.add(new InstalledPackagesChecks());
|
||||
if (SDK_INT > LOLLIPOP_MR1) {
|
||||
checks.add(new PermissionCheckGroup(ACCESS_COARSE_LOCATION, WRITE_EXTERNAL_STORAGE, GET_ACCOUNTS, READ_PHONE_STATE));
|
||||
}
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||
checks.add(new SystemChecks());
|
||||
}
|
||||
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) {
|
||||
if (requestCode == SystemChecks.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS)
|
||||
reset(LayoutInflater.from(getContext()));
|
||||
else
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
}
|
||||
|
||||
public static class AsActivity extends AbstractSettingsActivity {
|
||||
public AsActivity() {
|
||||
showHomeAsUp = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Fragment getFragment() {
|
||||
return new SelfCheckFragment();
|
||||
}
|
||||
}
|
||||
}
|
@ -16,137 +16,51 @@
|
||||
|
||||
package org.microg.gms.ui;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.preference.Preference;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.v4.app.FragmentTransaction;
|
||||
import android.support.v4.preference.PreferenceFragment;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.support.v7.widget.Toolbar;
|
||||
import android.view.LayoutInflater;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.v7.preference.PreferenceManager;
|
||||
|
||||
import com.google.android.gms.R;
|
||||
|
||||
import org.microg.tools.selfcheck.InstalledPackagesChecks;
|
||||
import org.microg.tools.selfcheck.NlpOsCompatChecks;
|
||||
import org.microg.tools.selfcheck.NlpStatusChecks;
|
||||
import org.microg.tools.selfcheck.PermissionCheckGroup;
|
||||
import org.microg.tools.selfcheck.RomSpoofSignatureChecks;
|
||||
import org.microg.tools.selfcheck.SelfCheckGroup;
|
||||
import org.microg.tools.selfcheck.SystemChecks;
|
||||
import org.microg.tools.ui.AbstractAboutFragment;
|
||||
import org.microg.tools.ui.AbstractSelfCheckFragment;
|
||||
import org.microg.gms.gcm.GcmDatabase;
|
||||
import org.microg.gms.gcm.GcmPrefs;
|
||||
import org.microg.tools.ui.AbstractDashboardActivity;
|
||||
import org.microg.tools.ui.ResourceSettingsFragment;
|
||||
|
||||
import java.util.List;
|
||||
public class SettingsActivity extends AbstractDashboardActivity {
|
||||
|
||||
import static android.Manifest.permission.ACCESS_COARSE_LOCATION;
|
||||
import static android.Manifest.permission.GET_ACCOUNTS;
|
||||
import static android.Manifest.permission.READ_PHONE_STATE;
|
||||
import static android.Manifest.permission.WRITE_EXTERNAL_STORAGE;
|
||||
import static android.os.Build.VERSION.SDK_INT;
|
||||
import static android.os.Build.VERSION_CODES.LOLLIPOP_MR1;
|
||||
|
||||
public class SettingsActivity extends AppCompatActivity {
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.settings_activity);
|
||||
setSupportActionBar((Toolbar) findViewById(R.id.toolbar));
|
||||
getSupportFragmentManager().beginTransaction()
|
||||
.replace(R.id.content_wrapper, new MyPreferenceFragment())
|
||||
.commit();
|
||||
}
|
||||
|
||||
public static class MyPreferenceFragment extends PreferenceFragment {
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
addPreferencesFromResource(R.xml.gms_preferences);
|
||||
|
||||
findPreference(getString(R.string.self_check_title))
|
||||
.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
|
||||
@Override
|
||||
public boolean onPreferenceClick(Preference preference) {
|
||||
getFragmentManager().beginTransaction()
|
||||
.addToBackStack("root")
|
||||
.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN)
|
||||
.replace(R.id.content_wrapper, new MySelfCheckFragment())
|
||||
.commit();
|
||||
return true;
|
||||
}
|
||||
});
|
||||
findPreference(getString(R.string.pref_about_title))
|
||||
.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
|
||||
@Override
|
||||
public boolean onPreferenceClick(Preference preference) {
|
||||
getFragmentManager().beginTransaction()
|
||||
.addToBackStack("root")
|
||||
.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN)
|
||||
.replace(R.id.content_wrapper, new MyAboutFragment())
|
||||
.commit();
|
||||
return true;
|
||||
}
|
||||
});
|
||||
findPreference(getString(R.string.pref_gcm_apps))
|
||||
.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
|
||||
@Override
|
||||
public boolean onPreferenceClick(Preference preference) {
|
||||
getFragmentManager().beginTransaction()
|
||||
.addToBackStack("root")
|
||||
.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN)
|
||||
.replace(R.id.content_wrapper, new GcmRegisteredAppsFragment())
|
||||
.commit();
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public static class MySelfCheckFragment extends AbstractSelfCheckFragment {
|
||||
|
||||
@Override
|
||||
protected void prepareSelfCheckList(List<SelfCheckGroup> checks) {
|
||||
checks.add(new RomSpoofSignatureChecks());
|
||||
checks.add(new InstalledPackagesChecks());
|
||||
if (SDK_INT > LOLLIPOP_MR1) {
|
||||
checks.add(new PermissionCheckGroup(ACCESS_COARSE_LOCATION, WRITE_EXTERNAL_STORAGE, GET_ACCOUNTS, READ_PHONE_STATE));
|
||||
}
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||
checks.add(new SystemChecks());
|
||||
}
|
||||
checks.add(new NlpOsCompatChecks());
|
||||
checks.add(new NlpStatusChecks());
|
||||
public SettingsActivity() {
|
||||
preferencesResource = R.xml.preferences_start;
|
||||
addCondition(Conditions.GCM_BATTERY_OPTIMIZATIONS);
|
||||
addCondition(Conditions.PERMISSIONS);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
|
||||
reset(LayoutInflater.from(getContext()));
|
||||
protected Fragment getFragment() {
|
||||
return new FragmentImpl();
|
||||
}
|
||||
|
||||
public static class FragmentImpl extends ResourceSettingsFragment {
|
||||
|
||||
public static final String PREF_ABOUT = "pref_about";
|
||||
public static final String PREF_GCM = "pref_gcm";
|
||||
|
||||
public FragmentImpl() {
|
||||
preferencesResource = R.xml.preferences_start;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
if (requestCode == SystemChecks.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS)
|
||||
reset(LayoutInflater.from(getContext()));
|
||||
else
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
}
|
||||
}
|
||||
|
||||
public static class MyAboutFragment extends AbstractAboutFragment {
|
||||
|
||||
@Override
|
||||
protected void collectLibraries(List<Library> libraries) {
|
||||
libraries.add(new Library("org.microg.gms.api", "microG GmsApi", "Apache License 2.0 by microG Team"));
|
||||
libraries.add(new Library("org.microg.safeparcel", "microG SafeParcel", "Apache License 2.0 by microG Team"));
|
||||
libraries.add(new Library("org.microg.nlp", "microG UnifiedNlp", "Apache License 2.0 by microG Team"));
|
||||
libraries.add(new Library("org.microg.nlp.api", "microG UnifiedNlp Api", "Apache License 2.0, by microG Team"));
|
||||
libraries.add(new Library("org.microg.wearable", "microG Wearable", "Apache License 2.0 by microG Team"));
|
||||
libraries.add(new Library("de.hdodenhof.circleimageview", "CircleImageView", "Apache License 2.0 by Henning Dodenhof"));
|
||||
libraries.add(new Library("org.oscim.android", "<vector<tile>>map", "GNU LGPLv3 by Hannes Janetzek"));
|
||||
libraries.add(new Library("com.squareup.wire", "Wire Protocol Buffers", "Apache License 2.0 by Square Inc."));
|
||||
public void onCreatePreferencesFix(@Nullable Bundle savedInstanceState, String rootKey) {
|
||||
super.onCreatePreferencesFix(savedInstanceState, rootKey);
|
||||
PreferenceManager prefs = getPreferenceManager();
|
||||
prefs.findPreference(PREF_ABOUT).setSummary(getString(R.string.about_version_str, AboutFragment.getSelfVersion(getContext())));
|
||||
if (GcmPrefs.get(getContext()).isGcmEnabled()) {
|
||||
int regCount = new GcmDatabase(getContext()).getRegistrationList().size();
|
||||
prefs.findPreference(PREF_GCM).setSummary(getString(R.string.v7_preference_on) + " / " + getContext().getString(R.string.gcm_registered_apps_counter, regCount));
|
||||
} else {
|
||||
prefs.findPreference(PREF_GCM).setSummary(R.string.v7_preference_off);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -16,6 +16,7 @@
|
||||
|
||||
package org.microg.gms.wearable;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.database.Cursor;
|
||||
@ -67,6 +68,8 @@ import java.util.Set;
|
||||
|
||||
import okio.ByteString;
|
||||
|
||||
import static android.os.Build.VERSION.SDK_INT;
|
||||
|
||||
public class WearableImpl {
|
||||
|
||||
private static final String TAG = "GmsWear";
|
||||
@ -456,16 +459,7 @@ public class WearableImpl {
|
||||
return null;
|
||||
}
|
||||
Cursor dataHolderItems = nodeDatabase.getDataItemsForDataHolderByHostAndPath(packageName, firstSignature, fixHost(uri.getHost(), false), uri.getPath());
|
||||
int j = 0;
|
||||
while (dataHolderItems.moveToNext()) {
|
||||
for (int i = 0; i < dataHolderItems.getColumnCount(); i++) {
|
||||
if (dataHolderItems.getType(i) == Cursor.FIELD_TYPE_STRING) {
|
||||
Log.d(TAG, "getDataItems[" + j + "]: " + dataHolderItems.getColumnName(i) + "=" + dataHolderItems.getString(i));
|
||||
}
|
||||
if (dataHolderItems.getType(i) == Cursor.FIELD_TYPE_INTEGER)
|
||||
Log.d(TAG, "getDataItems[" + j + "]: " + dataHolderItems.getColumnName(i) + "=" + dataHolderItems.getLong(i));
|
||||
}
|
||||
}
|
||||
maybeDebugCursor("getDataItems",dataHolderItems);
|
||||
dataHolderItems.moveToFirst();
|
||||
dataHolderItems.moveToPrevious();
|
||||
DataHolder dataHolder = new DataHolder(dataHolderItems, 0, null);
|
||||
@ -473,6 +467,22 @@ public class WearableImpl {
|
||||
return dataHolder;
|
||||
}
|
||||
|
||||
@TargetApi(11)
|
||||
private void maybeDebugCursor(String what, Cursor cursor) {
|
||||
if (SDK_INT >= 11) {
|
||||
int j = 0;
|
||||
while (cursor.moveToNext()) {
|
||||
for (int i = 0; i < cursor.getColumnCount(); i++) {
|
||||
if (cursor.getType(i) == Cursor.FIELD_TYPE_STRING) {
|
||||
Log.d(TAG, what+"[" + j + "]: " + cursor.getColumnName(i) + "=" + cursor.getString(i));
|
||||
}
|
||||
if (cursor.getType(i) == Cursor.FIELD_TYPE_INTEGER)
|
||||
Log.d(TAG, what+"[" + j + "]: " + cursor.getColumnName(i) + "=" + cursor.getLong(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized void addListener(String packageName, IWearableListener listener) {
|
||||
if (!listeners.containsKey(packageName)) {
|
||||
listeners.put(packageName, new ArrayList<IWearableListener>());
|
||||
|
11
play-services-core/src/main/res/drawable/device_login.xml
Normal file
11
play-services-core/src/main/res/drawable/device_login.xml
Normal file
@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportHeight="24"
|
||||
android:viewportWidth="24">
|
||||
|
||||
<path
|
||||
android:fillColor="#000000"
|
||||
android:pathData="M10,17.25V14H3V10H10V6.75L15.25,12L10,17.25M8,2H17A2,2 0 0,1 19,4V20A2,2 0 0,1 17,22H8A2,2 0 0,1 6,20V16H8V20H17V4H8V8H6V4A2,2 0 0,1 8,2Z"/>
|
||||
</vector>
|
11
play-services-core/src/main/res/drawable/gcm_bell.xml
Normal file
11
play-services-core/src/main/res/drawable/gcm_bell.xml
Normal file
@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportHeight="24"
|
||||
android:viewportWidth="24">
|
||||
|
||||
<path
|
||||
android:fillColor="#000000"
|
||||
android:pathData="M 12 4 C 9.11 4 6.5996094 5.6392969 5.3496094 8.0292969 C 2.3396094 8.3592969 0 10.9 0 14 A 6 6 0 0 0 6 20 L 19 20 A 5 5 0 0 0 24 15 C 24 12.36 21.949609 10.219297 19.349609 10.029297 C 18.669609 6.5892969 15.64 4 12 4 z M 12 7.5 A 0.5 0.5 0 0 1 12.5 8 L 12.5 8.5390625 C 13.92 8.7790625 15 10.015 15 11.5 L 15 14.5 L 16.5 16 L 7.5 16 L 9 14.5 L 9 11.5 C 9 10.015 10.08 8.7790625 11.5 8.5390625 L 11.5 8 A 0.5 0.5 0 0 1 12 7.5 z M 11 16.5 L 13 16.5 A 1 1 0 0 1 12 17.5 A 1 1 0 0 1 11 16.5 z"/>
|
||||
</vector>
|
133
play-services-core/src/main/res/layout/ask_gcm.xml
Normal file
133
play-services-core/src/main/res/layout/ask_gcm.xml
Normal file
@ -0,0 +1,133 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright (C) 2015 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.
|
||||
-->
|
||||
|
||||
<FrameLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent"
|
||||
android:clipChildren="false"
|
||||
android:clipToPadding="false">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/dialog_container"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/desc_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingEnd="16dip"
|
||||
android:paddingLeft="20dip"
|
||||
android:paddingRight="16dip"
|
||||
android:paddingStart="20dip"
|
||||
android:paddingTop="18dip">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/perm_desc_root"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/permission_icon"
|
||||
android:layout_width="36dip"
|
||||
android:layout_height="36dip"
|
||||
android:scaleType="fitCenter"
|
||||
android:src="@drawable/gcm_bell"
|
||||
android:tint="?attr/colorAccent">
|
||||
</ImageView>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/permission_message"
|
||||
style="@style/TextAppearance.AppCompat.Subhead"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingLeft="16dip"
|
||||
android:paddingStart="16dip"
|
||||
android:text="Allow {appName} to register for push notifications?"
|
||||
android:textSize="20sp">
|
||||
</TextView>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</FrameLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:paddingEnd="16dip"
|
||||
android:paddingLeft="20dip"
|
||||
android:paddingRight="16dip"
|
||||
android:paddingStart="20dip">
|
||||
|
||||
<android.support.v7.widget.ButtonBarLayout
|
||||
android:id="@+id/button_group"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="bottom"
|
||||
android:orientation="horizontal"
|
||||
android:paddingBottom="4dp"
|
||||
android:paddingLeft="6dip"
|
||||
android:paddingStart="6dip"
|
||||
android:paddingTop="4dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/current_page_text"
|
||||
style="?android:attr/textAppearanceSmall"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:maxLines="1"
|
||||
android:paddingEnd="12dp"
|
||||
android:paddingRight="12dp"
|
||||
android:textColor="?android:attr/textColorSecondary"
|
||||
android:visibility="invisible">
|
||||
</TextView>
|
||||
|
||||
<android.support.v4.widget.Space
|
||||
android:id="@*android:id/spacer"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1"
|
||||
android:visibility="invisible">
|
||||
</android.support.v4.widget.Space>
|
||||
|
||||
<Button
|
||||
android:id="@+id/permission_deny_button"
|
||||
style="?attr/buttonBarButtonStyle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/deny">
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
android:id="@+id/permission_allow_button"
|
||||
style="?attr/buttonBarButtonStyle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/allow">
|
||||
</Button>
|
||||
|
||||
</android.support.v7.widget.ButtonBarLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</FrameLayout>
|
@ -118,14 +118,14 @@
|
||||
|
||||
<Button
|
||||
android:id="@android:id/button2"
|
||||
style="?android:attr/buttonBarButtonStyle"
|
||||
style="?attr/buttonBarButtonStyle"
|
||||
android:text="@string/deny"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
<Button
|
||||
android:id="@android:id/button1"
|
||||
style="?android:attr/buttonBarButtonStyle"
|
||||
style="?attr/buttonBarButtonStyle"
|
||||
android:text="@string/allow"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content" />
|
||||
|
@ -99,7 +99,7 @@
|
||||
|
||||
<Button
|
||||
android:id="@android:id/button1"
|
||||
style="?android:attr/buttonBarButtonStyle"
|
||||
style="?attr/buttonBarButtonStyle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@android:string/ok"/>
|
||||
|
@ -1,75 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?><!--
|
||||
~ Copyright 2013-2015 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:minHeight="?attr/listPreferredItemHeight"
|
||||
android:paddingLeft="?attr/listPreferredItemPaddingLeft"
|
||||
android:paddingRight="?attr/listPreferredItemPaddingRight">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/image"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:adjustViewBounds="true"
|
||||
android:maxHeight="40dp"
|
||||
android:maxWidth="40dp"
|
||||
android:minHeight="40dp"
|
||||
android:minWidth="40dp"
|
||||
android:scaleType="fitCenter"/>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="10dp"
|
||||
android:minHeight="?attr/listPreferredItemHeight"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textAppearance="?android:attr/textAppearanceListItem"/>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/sub"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginRight="8dp"
|
||||
android:ellipsize="end"
|
||||
android:lines="1"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Body1"
|
||||
android:textColor="@android:color/darker_gray"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/warning"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:ellipsize="end"
|
||||
android:lines="1"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Body2"
|
||||
android:textColor="@color/material_error"
|
||||
android:visibility="gone"/>
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
@ -1,21 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?><!--
|
||||
~ Copyright 2013-2015 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.
|
||||
-->
|
||||
|
||||
<ListView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/list_view"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_width="match_parent">
|
||||
</ListView>
|
50
play-services-core/src/main/res/layout/list_no_item.xml
Normal file
50
play-services-core/src/main/res/layout/list_no_item.xml
Normal file
@ -0,0 +1,50 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
~ Copyright (C) 2013 The Android Open Source Project
|
||||
~ Copyright (C) 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.
|
||||
-->
|
||||
|
||||
<!-- text that appears when the recent app list is empty -->
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:minHeight="?android:attr/listPreferredItemHeight"
|
||||
android:gravity="center_vertical"
|
||||
android:paddingEnd="?android:attr/scrollbarSize"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:paddingRight="?android:attr/scrollbarSize">
|
||||
|
||||
<RelativeLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="15dip"
|
||||
android:layout_marginEnd="6dip"
|
||||
android:layout_marginTop="6dip"
|
||||
android:layout_marginBottom="6dip"
|
||||
android:layout_weight="1"
|
||||
android:layout_marginLeft="15dip"
|
||||
android:layout_marginRight="6dip">
|
||||
|
||||
<TextView android:id="@+android:id/title"
|
||||
android:gravity="center"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:textAppearance="?android:attr/textAppearanceSmall"
|
||||
android:textColor="?android:attr/textColorSecondary" />
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
@ -70,7 +70,7 @@
|
||||
android:layout_gravity="top"
|
||||
android:layout_marginTop="12.0dip"
|
||||
android:ellipsize="end"
|
||||
android:singleLine="true"
|
||||
android:maxLines="1"
|
||||
android:text="@string/place_picker_select_title"
|
||||
android:textAppearance="?android:textAppearanceMedium"
|
||||
android:textColor="?attr/colorAccent"/>
|
||||
|
@ -44,9 +44,7 @@ Dies kann einige Minuten dauern."</string>
|
||||
<string name="pref_auth_trust_google_title">Vertraue Google bei App Rechten</string>
|
||||
<string name="pref_auth_trust_google_summary">Wenn deaktiviert, wird der Nutzer gefragt bevor eine App Autorisierungsanfrage an Google geschickt wird. Einige Apps werden das Google Konto nicht nutzen können, wenn deaktiviert.</string>
|
||||
|
||||
<string name="pref_checkin_enable_title">Aktiviere Geräte Check-In</string>
|
||||
<string name="pref_checkin_enable_summary">Geräte Check-In ist ein versteckter Prozess, der genutzt wird um eine eindeutige Kennung für Google Dienste zu erzeugen. microG entfernt identifizierende Daten bis auf den Google Konto Namen.</string>
|
||||
<string name="pref_gcm_enable_mcs_title">Aktiviere Google Cloud Messaging</string>
|
||||
<string name="pref_gcm_enable_mcs_summary">Google Cloud Messaging ist ein Push-Nachrichten Dienst, der von vielen Apps genutzt wird. Zur Benutztung muss Geräte Check-In aktiviert werden.</string>
|
||||
|
||||
<string name="prefcat_services">Hintergrunddienste</string>
|
||||
|
@ -47,10 +47,8 @@ Esto podría tardar algunos minutos."</string>
|
||||
|
||||
<string name="prefcat_services">Servicios de segundo plano</string>
|
||||
|
||||
<string name="pref_checkin_enable_title">Habilitar registro del dispositivo</string>
|
||||
<string name="pref_checkin_enable_summary">El registro del dispositivo es un proceso oculto que se usa para crear un identificador único para los servicios de Google. microG quita información identificativa aparte del nombre en tu cuenta de Google de estos datos.</string>
|
||||
|
||||
<string name="pref_gcm_enable_mcs_title">Habilitar Google Cloud Messaging</string>
|
||||
<string name="pref_gcm_enable_mcs_summary">Google Cloud Messaging es un proveedor de notificaciones push usado por muchas aplicaciones. Para usarlo debes habilitar el registro del dispositivo.</string>
|
||||
|
||||
<string name="pref_gcm_heartbeat_title">Intervalo del Cloud Messaging heartbeat</string>
|
||||
|
@ -44,9 +44,7 @@ To zajmie kilka minut."</string>
|
||||
<string name="pref_auth_trust_google_title">Zaufaj uprawnieniom aplikacji Google</string>
|
||||
<string name="pref_auth_trust_google_summary">Po wyłączeniu, do użytkownika kierowane jest pytanie przed wysyłaniem prośby o autoryzację do Google. Niektóre aplikacje nie będą mogły skorzystać z konta Google po wyłączeniu tej opcji.</string>
|
||||
|
||||
<string name="pref_checkin_enable_title">Uruchom zgłaszanie urządzenia</string>
|
||||
<string name="pref_checkin_enable_summary">Zgłaszanie urządzenia to ukryty proces, służący do wygenerowania unikalnego identyfikatora dla usług Google.Usługi microG wyciągają inne dane identyfikacyjne niż nazwa Twojego konta z tego identyfikatora.</string>
|
||||
<string name="pref_gcm_enable_mcs_title">Uruchom Google Cloud Messaging</string>
|
||||
<string name="pref_gcm_enable_mcs_summary">Google Cloud Messaging jest systemem zapewniającym powiadomienia dla wielu aplikacji. Żeby z niego korzystać, musisz uruchomić zgłaszanie urządzenia.</string>
|
||||
|
||||
<string name="prefcat_services">Usługi w tle</string>
|
||||
|
@ -41,9 +41,7 @@ Acest lucru poate dura câteva minute."</string>
|
||||
<string name="perm_c2dm_send_label">trimite mesaje C2DM altor aplicaţii</string>
|
||||
<string name="pref_auth_trust_google_title">Credeţi Google pentru permisiunile aplicaţiei</string>
|
||||
<string name="pref_auth_trust_google_summary">Dacă este dezactivat, utilizatorul este întrebat înainte de trimiterea către Google a unei solicitări de autorizare a aplicaţiei. Unele aplicații nu vor reuși să utilizeze contul Google, dacă această opţiune este dezactivată.</string>
|
||||
<string name="pref_checkin_enable_title">Activaţi înregistrarea dispozitivului</string>
|
||||
<string name="pref_checkin_enable_summary">\"Înregistrarea dispozitivului\" este un proces ascuns care este utilizat pentru a crea un identificator unic pentru serviciile Google. Serviciile microG înlătură alte date de identificare cu excepţia numelui contului dvs. Google.</string>
|
||||
<string name="pref_gcm_enable_mcs_title">Activaţi Mesageria Google Cloud</string>
|
||||
<string name="pref_gcm_enable_mcs_summary">Mesageria Google Cloud este un furnizor de notificări de ti push utilizat de multe aplicații. Pentru a utiliza trebuie să activați \"Înregistrarea dispozitivului\".</string>
|
||||
<string name="prefcat_services">Servicii de fundal</string>
|
||||
<string name="prefcat_components">Componente</string>
|
||||
|
@ -48,10 +48,8 @@
|
||||
|
||||
<string name="prefcat_services">Услуге у позадини</string>
|
||||
|
||||
<string name="pref_checkin_enable_title">Укључи пријаву уређаја</string>
|
||||
<string name="pref_checkin_enable_summary">Пријава уређаја је скривени процес који служи за прављење јединственог идентификатора за Гуглове услуге. микроГ сервиси скидају идентификујуће бите са ових података, осим имена вашег Гугл налога.</string>
|
||||
|
||||
<string name="pref_gcm_enable_mcs_title">Омогући Гуглове облак поруке</string>
|
||||
<string name="pref_gcm_enable_mcs_summary">Гуглове облак поруке (Google Cloud Messaging) је провајдер гурања обавештења (push) којег користе многе апликације. Да бисте га користили укључите пријаву уређаја.</string>
|
||||
|
||||
<string name="pref_gcm_heartbeat_title">Интервал откуцаја облак порука</string>
|
||||
|
@ -1,5 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?><!--
|
||||
~ Copyright 2013-2015 microG Project Team
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
~ Copyright (C) 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.
|
||||
@ -14,7 +15,18 @@
|
||||
~ limitations under the License.
|
||||
-->
|
||||
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:id="@+id/delete"
|
||||
android:title="@string/gcm_unregister_app" />
|
||||
</menu>
|
||||
<resources>
|
||||
<string-array name="network_types" translatable="false">
|
||||
<item>mobile</item>
|
||||
<item>wifi</item>
|
||||
<item>roaming</item>
|
||||
<item>other</item>
|
||||
</string-array>
|
||||
|
||||
<string-array name="network_types_names">
|
||||
<item>@string/network_type_mobile</item>
|
||||
<item>@string/network_type_wifi</item>
|
||||
<item>@string/network_type_roaming</item>
|
||||
<item>@string/network_type_other</item>
|
||||
</string-array>
|
||||
</resources>
|
@ -14,17 +14,15 @@
|
||||
~ limitations under the License.
|
||||
-->
|
||||
|
||||
<resources>
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<string name="gms_app_name">microG Services Core</string>
|
||||
<string name="gms_settings_name">microG Settings</string>
|
||||
|
||||
<string name="google_account_type" translatable="false">com.google</string>
|
||||
|
||||
<string name="just_a_sec">Just a sec…</string>
|
||||
<string name="google_account_label">Google</string>
|
||||
<string name="ask_permission_tos">By continuing, you allow this app and Google to use your information in accordance with their respective terms of service and privacy policies.</string>
|
||||
<string name="ask_scope_permission_title">%1$s would like to:</string>
|
||||
<string name="ask_service_permission_title">%1$s would like to use:</string>
|
||||
<string name="ask_scope_permission_title"><xliff:g example="F-Droid">%1$s</xliff:g> would like to:</string>
|
||||
<string name="ask_service_permission_title"><xliff:g example="F-Droid">%1$s</xliff:g> would like to use:</string>
|
||||
<string name="account_manager_title">Google Account Manager</string>
|
||||
<string name="sorry">Sorry…</string>
|
||||
<string name="no_network_error_desc">"You don't have a network connection.
|
||||
@ -39,31 +37,30 @@ This can take a couple of minutes."</string>
|
||||
<string name="allow">Allow</string>
|
||||
<string name="deny">Deny</string>
|
||||
<string name="auth_notification_title">Authentication required</string>
|
||||
<string name="auth_notification_content">%1$s requires your authorization to access your Google account.</string>
|
||||
<string name="auth_notification_content"><xliff:g example="F-Droid">%1$s</xliff:g> requires your authorization to access your Google account.</string>
|
||||
|
||||
<string name="perm_status_broadcast_label">listen to internal status broadcasts</string>
|
||||
<string name="perm_c2dm_receive_label">listen to C2DM messages</string>
|
||||
<string name="perm_c2dm_send_label">send C2DM messages to other apps</string>
|
||||
|
||||
<string name="pref_auth_trust_google" translatable="false">auth_manager_trust_google</string>
|
||||
<string name="pref_auth_trust_google_title">Trust Google for app permissions</string>
|
||||
<string name="pref_auth_trust_google_summary">When disabled, the user is asked before an apps authorization request is sent to Google. Some applications will fail to use the Google account if this is disabled.</string>
|
||||
|
||||
<string name="prefcat_services">Background services</string>
|
||||
<string name="prefs_account">Account preferences</string>
|
||||
<string name="prefs_account_privacy">Personal info & privacy</string>
|
||||
<string name="prefs_account_security">Sign-in & security</string>
|
||||
|
||||
<string name="pref_checkin_enable" translatable="false">checkin_enable_service</string>
|
||||
<string name="pref_checkin_enable_title">Enable device checkin</string>
|
||||
<string name="pref_checkin_enable_summary">Device checkin is a hidden process that is used to create an unique identifier for Google services. microG Services strips identifying bits other than your Google account name from this data.</string>
|
||||
<string name="prefcat_services">Services</string>
|
||||
|
||||
<string name="pref_gcm_enable_mcs" translatable="false">gcm_enable_mcs_service</string>
|
||||
<string name="pref_gcm_enable_mcs_title">Enable Google Cloud Messaging</string>
|
||||
<string name="pref_gcm_enable_mcs_summary">Google Cloud Messaging is a push notification provider used by many applications. To use it you must enable device checkin.</string>
|
||||
<string name="service_name_checkin">Google device registration</string>
|
||||
<string name="service_name_mcs">Google Cloud Messaging</string>
|
||||
|
||||
<string name="pref_checkin_enable_summary">Registers your device to Google services and creates a unique device identifier. microG strips identifying bits other than your Google account name from registration data.</string>
|
||||
<string name="pref_gcm_enable_mcs_summary">Google Cloud Messaging is a push notification provider used by many third-party applications. To use it you must enable device registration.</string>
|
||||
|
||||
<string name="pref_gcm_heartbeat" translatable="false">gcm_heartbeat_interval</string>
|
||||
<string name="pref_gcm_heartbeat_title">Cloud Messaging heartbeat interval</string>
|
||||
<string name="pref_gcm_heartbeat_summary">The interval in seconds for the system to heartbeat the Google servers. Increasing this number will reduce battery consumption, but might cause delays on push messages.</string>
|
||||
<string name="pref_gcm_heartbeat_summary">The interval in seconds for the system to heartbeat the Google servers. Increasing this number will reduce battery consumption, but might cause delays on push messages.\nDeprecated, will be replaced in future release.</string>
|
||||
|
||||
<string name="pref_gcm_apps">gcm_apps</string>
|
||||
<string name="pref_gcm_apps_title">Apps using Google Cloud Messaging</string>
|
||||
<string name="pref_gcm_apps_summary">List of apps currently registered for Google Cloud Messaging.</string>
|
||||
|
||||
@ -71,7 +68,7 @@ This can take a couple of minutes."</string>
|
||||
<string name="prefcat_location_service">Location service</string>
|
||||
|
||||
<string name="games_title">Google Play Games</string>
|
||||
<string name="games_info_title">%1$s would like to use Play Games</string>
|
||||
<string name="games_info_title"><xliff:g example="F-Droid">%1$s</xliff:g> would like to use Play Games</string>
|
||||
<string name="games_info_content">To use Play Games it is required to install the Google Play Games app. The application might continue without Play Games, but it is possible that it will behave unexpectedly.</string>
|
||||
|
||||
<string name="pick_place_title">Pick a place</string>
|
||||
@ -93,25 +90,52 @@ This can take a couple of minutes."</string>
|
||||
<string name="self_check_pkg_gms">Play Services (GmsCore)</string>
|
||||
<string name="self_check_pkg_vending">Play Store (Phonesky)</string>
|
||||
<string name="self_check_pkg_gsf">Services Framework (GSF)</string>
|
||||
<string name="self_check_name_app_installed">%1$s installed: </string>
|
||||
<string name="self_check_resolution_app_installed">Install the application %1$s or a compatible one. Please check the documentation on which applications are compatible.</string>
|
||||
<string name="self_check_name_correct_sig">%1$s has correct signature: </string>
|
||||
<string name="self_check_resolution_correct_sig">Either the installed %1$s is not compatible or signature spoofing is not active for it. Please check the documentation on which applications and ROMs are compatible.</string>
|
||||
<string name="self_check_name_app_installed"><xliff:g example="F-Droid">%1$s</xliff:g> installed: </string>
|
||||
<string name="self_check_resolution_app_installed">Install the application <xliff:g example="F-Droid">%1$s</xliff:g> or a compatible one. Please check the documentation on which applications are compatible.</string>
|
||||
<string name="self_check_name_correct_sig"><xliff:g example="F-Droid">%1$s</xliff:g> has correct signature: </string>
|
||||
<string name="self_check_resolution_correct_sig">Either the installed <xliff:g example="F-Droid">%1$s</xliff:g> is not compatible or signature spoofing is not active for it. Please check the documentation on which applications and ROMs are compatible.</string>
|
||||
<string name="perm_extended_access_label">Extended access to Google services</string>
|
||||
|
||||
<string name="self_check_cat_system">System</string>
|
||||
<string name="self_check_name_battery_optimizations">Battery optimizations ignored:</string>
|
||||
<string name="self_check_resolution_battery_optimizations">Touch here to disable battery optimizations. Not doing this may result in misbehaving applications</string>
|
||||
|
||||
<string name="lacking_permission_toast">microG Services Core: Lacking permission %1$s</string>
|
||||
<string name="lacking_permission_toast">microG Services Core: Lacking permission to <xliff:g example="have full network acccess">%1$s</xliff:g></string>
|
||||
|
||||
<string name="place_picker_select_title">Select this location</string>
|
||||
<string name="place_picker_nearby_places">Nearby places</string>
|
||||
<string name="place_picker_location_lat_lng">(%1$.7f, %2$.7f)</string>
|
||||
|
||||
<string name="gcm_registered_apps_counter"><xliff:g example="123">%1$i</xliff:g> registered Apps</string>
|
||||
<string name="gcm_app_error_unregistering">Error unregistering</string>
|
||||
<string name="gcm_app_not_installed_anymore">No longer installed</string>
|
||||
<string name="gcm_messages_received_no">%1$s messages received</string>
|
||||
<string name="gcm_messages_received_no"><xliff:g example="123">%1$i</xliff:g> messages received</string>
|
||||
<string name="gcm_unregister_app">Unregister</string>
|
||||
<string name="gcm_not_registered">Not registered</string>
|
||||
<string name="gcm_no_message_yet">No messages received so far</string>
|
||||
<string name="gcm_last_message_at">Last message: <xliff:g example="Yesterday, 02:20 PM">%1$s</xliff:g></string>
|
||||
<string name="gcm_registered">Registered</string>
|
||||
<string name="gcm_registered_since">Registered since: <xliff:g example="Yesterday, 02:20 PM">%1$s</xliff:g></string>
|
||||
<string name="gcm_unregister_confirm_title">Unregister <xliff:g example="F-Droid">%1$s</xliff:g>?</string>
|
||||
<string name="gcm_unregister_confirm_message">Some apps do not automatically re-register and/or do not provide an option to do so manually. These apps might not work correctly after unregistering.\nContinue?</string>
|
||||
<string name="gcm_messages_counter">Messages: <xliff:g example="123">%1$i</xliff:g> (<xliff:g example="12345">%2$i</xliff:g> bytes)</string>
|
||||
<string name="gcm_state_disconnected">Current State: Disconnected</string>
|
||||
<string name="gcm_state_connected">Current State: Connected since <xliff:g example="2 hours ago">%1$s</xliff:g></string>
|
||||
|
||||
<string name="menu_advanced">Advanced</string>
|
||||
<string name="list_no_item_none">None</string>
|
||||
|
||||
<string name="cond_gcm_bat_title">Battery optimizations enabled</string>
|
||||
<string name="cond_gcm_bat_summary">You enabled Google Cloud Messaging but have battery optimizations active for microG Services Core. For push notifications to arrive you should ignore battery optimizations.</string>
|
||||
<string name="cond_gcm_bat_action">Ignore optimizations</string>
|
||||
<string name="cond_perm_title">Permission missing</string>
|
||||
<string name="cond_perm_summary">One or more permissions required for proper functionality of microG Service Core is missing.</string>
|
||||
<string name="cond_perm_action">Request missing permissions</string>
|
||||
|
||||
<string name="network_type_mobile">Mobile network</string>
|
||||
<string name="network_type_wifi">Wi-Fi</string>
|
||||
<string name="network_type_roaming">Roaming</string>
|
||||
<string name="network_type_other">Other networks</string>
|
||||
|
||||
|
||||
</resources>
|
||||
|
@ -15,8 +15,8 @@
|
||||
-->
|
||||
|
||||
<account-authenticator xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:accountPreferences="@xml/account_preferences"
|
||||
android:accountType="@string/google_account_type"
|
||||
android:accountPreferences="@xml/preferences_auth"
|
||||
android:accountType="com.google"
|
||||
android:customTokens="true"
|
||||
android:icon="@drawable/proprietary_auth_gls_ic_google_selected"
|
||||
android:smallIcon="@drawable/proprietary_auth_gls_ic_google_minitab_selected"
|
||||
|
@ -1,63 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?><!--
|
||||
~ Copyright 2013-2015 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">
|
||||
<PreferenceCategory android:title="@string/prefcat_setup">
|
||||
<Preference
|
||||
android:key="@string/self_check_title"
|
||||
android:summary="@string/self_check_desc"
|
||||
android:title="@string/self_check_title">
|
||||
</Preference>
|
||||
</PreferenceCategory>
|
||||
<PreferenceCategory android:title="@string/prefcat_services">
|
||||
<CheckBoxPreference
|
||||
android:defaultValue="false"
|
||||
android:key="@string/pref_checkin_enable"
|
||||
android:summary="@string/pref_checkin_enable_summary"
|
||||
android:title="@string/pref_checkin_enable_title"/>
|
||||
<CheckBoxPreference
|
||||
android:defaultValue="false"
|
||||
android:dependency="@string/pref_checkin_enable"
|
||||
android:key="@string/pref_gcm_enable_mcs"
|
||||
android:summary="@string/pref_gcm_enable_mcs_summary"
|
||||
android:title="@string/pref_gcm_enable_mcs_title"/>
|
||||
<EditTextPreference
|
||||
android:defaultValue="300"
|
||||
android:dependency="@string/pref_gcm_enable_mcs"
|
||||
android:key="@string/pref_gcm_heartbeat"
|
||||
android:summary="@string/pref_gcm_heartbeat_summary"
|
||||
android:title="@string/pref_gcm_heartbeat_title"/>
|
||||
<Preference
|
||||
android:dependency="@string/pref_gcm_enable_mcs"
|
||||
android:key="@string/pref_gcm_apps"
|
||||
android:summary="@string/pref_gcm_apps_summary"
|
||||
android:title="@string/pref_gcm_apps_title">
|
||||
</Preference>
|
||||
</PreferenceCategory>
|
||||
<PreferenceCategory android:title="@string/prefcat_location_service">
|
||||
<Preference android:title="@string/nlp_settings_label">
|
||||
<intent
|
||||
android:targetClass="org.microg.nlp.ui.SettingsActivity"
|
||||
android:targetPackage="com.google.android.gms"/>
|
||||
</Preference>
|
||||
</PreferenceCategory>
|
||||
<PreferenceCategory android:title="@string/prefcat_about">
|
||||
<Preference
|
||||
android:key="@string/pref_about_title"
|
||||
android:summary="@string/pref_about_summary"
|
||||
android:title="@string/pref_about_title"/>
|
||||
</PreferenceCategory>
|
||||
</PreferenceScreen>
|
@ -1,5 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?><!--
|
||||
~ Copyright 2013-2015 microG Project Team
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
~ Copyright (C) 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.
|
||||
@ -15,11 +16,16 @@
|
||||
-->
|
||||
|
||||
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<PreferenceCategory android:title="@string/account_manager_title">
|
||||
<CheckBoxPreference
|
||||
android:key="@string/pref_auth_trust_google"
|
||||
<SwitchPreference
|
||||
android:defaultValue="true"
|
||||
android:title="@string/pref_auth_trust_google_title"
|
||||
android:summary="@string/pref_auth_trust_google_summary" />
|
||||
android:key="auth_manager_trust_google"
|
||||
android:summary="@string/pref_auth_trust_google_summary"
|
||||
android:title="@string/pref_auth_trust_google_title"/>
|
||||
</PreferenceCategory>
|
||||
|
||||
<Preference
|
||||
android:selectable="false"
|
||||
android:summary="Google account settings not yet implemented."/>
|
||||
</PreferenceScreen>
|
33
play-services-core/src/main/res/xml/preferences_auth.xml
Normal file
33
play-services-core/src/main/res/xml/preferences_auth.xml
Normal file
@ -0,0 +1,33 @@
|
||||
<?xml version="1.0" encoding="utf-8"?><!--
|
||||
~ Copyright 2013-2015 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">
|
||||
<PreferenceScreen
|
||||
android:key="k2"
|
||||
android:title="@string/prefs_account_security">
|
||||
<intent android:action="com.google.android.gms.accountsettings.SECURITY_SETTINGS"/>
|
||||
</PreferenceScreen>
|
||||
<PreferenceScreen
|
||||
android:key="k3"
|
||||
android:title="@string/prefs_account_privacy">
|
||||
<intent android:action="com.google.android.gms.accountsettings.PRIVACY_SETTINGS"/>
|
||||
</PreferenceScreen>
|
||||
<PreferenceScreen
|
||||
android:key="k4"
|
||||
android:title="@string/prefs_account">
|
||||
<intent android:action="com.google.android.gms.accountsettings.ACCOUNT_PREFERENCES_SETTINGS"/>
|
||||
</PreferenceScreen>
|
||||
</PreferenceScreen>
|
32
play-services-core/src/main/res/xml/preferences_gcm.xml
Normal file
32
play-services-core/src/main/res/xml/preferences_gcm.xml
Normal file
@ -0,0 +1,32 @@
|
||||
<?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.
|
||||
-->
|
||||
|
||||
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<Preference
|
||||
android:selectable="false"
|
||||
android:summary="@string/pref_gcm_enable_mcs_summary"/>
|
||||
|
||||
<Preference
|
||||
android:key="pref_gcm_status"
|
||||
android:persistent="false"
|
||||
android:selectable="false"
|
||||
android:summary="Current state: Connected since 2 min ago"/>
|
||||
|
||||
<PreferenceCategory
|
||||
android:key="gcm_apps"
|
||||
android:title="@string/pref_gcm_apps_title"/>
|
||||
</PreferenceScreen>
|
@ -0,0 +1,70 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
~ Copyright (C) 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.
|
||||
-->
|
||||
|
||||
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<EditTextPreference
|
||||
android:defaultValue="300"
|
||||
android:key="gcm_heartbeat_interval"
|
||||
android:summary="@string/pref_gcm_heartbeat_summary"
|
||||
android:title="@string/pref_gcm_heartbeat_title"/>
|
||||
|
||||
<SwitchPreference
|
||||
android:defaultValue="false"
|
||||
android:key="gcm_confirm_new_apps"
|
||||
android:summary="Ask before registering a new app to receive push notifications"
|
||||
android:title="Confirm new apps"/>
|
||||
|
||||
<MultiSelectListPreference
|
||||
android:enabled="false"
|
||||
android:entries="@array/network_types_names"
|
||||
android:entryValues="@array/network_types"
|
||||
android:key="gcm_network_types"
|
||||
android:summary="Connect to Google servers while connected to one of these networks.\nNot yet supported"
|
||||
android:title="Networks"/>
|
||||
|
||||
<SwitchPreference
|
||||
android:defaultValue="false"
|
||||
android:enabled="false"
|
||||
android:key="gcm_use_tor"
|
||||
android:summary="Requires Orbot to be installed\nNot yet supported"
|
||||
android:title="Connect via Tor network"/>
|
||||
|
||||
<PreferenceCategory
|
||||
android:enabled="false"
|
||||
android:title="Connection configuration\nNot yet supported">
|
||||
|
||||
<ListPreference
|
||||
android:defaultValue="auto"
|
||||
android:key="gcm_ping_mobile"
|
||||
android:summary="Automatic: 13 min"
|
||||
android:title="Mobile network heartbeat interval"/>
|
||||
|
||||
<ListPreference
|
||||
android:defaultValue="auto"
|
||||
android:key="gcm_ping_wifi"
|
||||
android:summary="Automatic: 30 min"
|
||||
android:title="Wi-Fi heartbeat interval"/>
|
||||
|
||||
<ListPreference
|
||||
android:defaultValue="auto"
|
||||
android:key="gcm_ping_other"
|
||||
android:summary="Automatic: 30 min"
|
||||
android:title="Other network heartbeat interval"/>
|
||||
|
||||
</PreferenceCategory>
|
||||
</PreferenceScreen>
|
@ -0,0 +1,35 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<PreferenceCategory
|
||||
android:title="Messaging">
|
||||
|
||||
<SwitchPreference
|
||||
android:defaultValue="true"
|
||||
android:key="gcm_app_wake_for_delivery"
|
||||
android:persistent="false"
|
||||
android:summary="Start the app in background to receive the incoming push messages. Disabling this might delay message delivery up to the moment the app is started or cause complete message loss."
|
||||
android:title="Start app on push message"/>
|
||||
|
||||
<Preference
|
||||
android:selectable="false"
|
||||
android:key="gcm_app_message_details"
|
||||
android:summary="Messages: 1000 (37 MB)\nLast message: 22 min ago"/>
|
||||
</PreferenceCategory>
|
||||
|
||||
<PreferenceCategory
|
||||
android:title="Registration">
|
||||
|
||||
<SwitchPreference
|
||||
android:defaultValue="true"
|
||||
android:key="gcm_app_allow_register"
|
||||
android:persistent="false"
|
||||
android:summary="Allow the app to register for push notifications."
|
||||
android:title="Allow registration"/>
|
||||
|
||||
<Preference
|
||||
android:title="Unregister"
|
||||
android:key="gcm_app_register_details"
|
||||
android:summary="Registered since: 3 month ago"/>
|
||||
</PreferenceCategory>
|
||||
</PreferenceScreen>
|
62
play-services-core/src/main/res/xml/preferences_start.xml
Normal file
62
play-services-core/src/main/res/xml/preferences_start.xml
Normal file
@ -0,0 +1,62 @@
|
||||
<?xml version="1.0" encoding="utf-8"?><!--
|
||||
~ Copyright 2013-2015 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">
|
||||
<PreferenceCategory android:title="@string/prefcat_setup">
|
||||
<org.microg.tools.ui.TintIconPreference
|
||||
android:icon="@drawable/self_check"
|
||||
android:summary="@string/self_check_desc"
|
||||
android:title="@string/self_check_title">
|
||||
<intent
|
||||
android:targetClass="org.microg.gms.ui.SelfCheckFragment$AsActivity"
|
||||
android:targetPackage="com.google.android.gms"/>
|
||||
</org.microg.tools.ui.TintIconPreference>
|
||||
</PreferenceCategory>
|
||||
<PreferenceCategory android:title="@string/prefcat_services">
|
||||
<SwitchPreferenceCompat
|
||||
android:defaultValue="false"
|
||||
android:icon="@drawable/device_login"
|
||||
android:key="checkin_enable_service"
|
||||
android:summary="@string/pref_checkin_enable_summary"
|
||||
android:title="@string/service_name_checkin"/>
|
||||
<org.microg.tools.ui.TintIconPreference
|
||||
android:dependency="checkin_enable_service"
|
||||
android:icon="@drawable/gcm_bell"
|
||||
android:key="pref_gcm"
|
||||
android:title="@string/service_name_mcs">
|
||||
<intent
|
||||
android:targetClass="org.microg.gms.ui.GcmFragment$AsActivity"
|
||||
android:targetPackage="com.google.android.gms"/>
|
||||
</org.microg.tools.ui.TintIconPreference>
|
||||
<org.microg.tools.ui.TintIconPreference
|
||||
android:icon="@drawable/location_marker"
|
||||
android:title="@string/nlp_settings_label">
|
||||
<intent
|
||||
android:targetClass="org.microg.nlp.ui.SettingsActivity"
|
||||
android:targetPackage="com.google.android.gms"/>
|
||||
</org.microg.tools.ui.TintIconPreference>
|
||||
</PreferenceCategory>
|
||||
<PreferenceCategory android:title="@string/prefcat_about">
|
||||
<org.microg.tools.ui.TintIconPreference
|
||||
android:icon="@drawable/info"
|
||||
android:key="pref_about"
|
||||
android:title="@string/pref_about_title">
|
||||
<intent
|
||||
android:targetClass="org.microg.gms.ui.AboutFragment$AsActivity"
|
||||
android:targetPackage="com.google.android.gms"/>
|
||||
</org.microg.tools.ui.TintIconPreference>
|
||||
</PreferenceCategory>
|
||||
</PreferenceScreen>
|
@ -10,6 +10,7 @@ include ':play-services-basement'
|
||||
|
||||
include ':play-services-api'
|
||||
include ':play-services-cast-api'
|
||||
include ':play-services-cast-framework-api'
|
||||
include ':play-services-iid-api'
|
||||
include ':play-services-location-api'
|
||||
include ':play-services-wearable-api'
|
||||
|
Loading…
Reference in New Issue
Block a user