forked from mirror/monocles_chat
migrate to targetSdkVersion 30 (Christian Schneppe)
This commit is contained in:
parent
b111f6263c
commit
1d57c88bbd
11 changed files with 176 additions and 96 deletions
|
@ -74,7 +74,6 @@ dependencies {
|
|||
implementation 'com.davemorrissey.labs:subsampling-scale-image-view:3.10.0'
|
||||
implementation 'com.google.android.exoplayer:exoplayer-core:2.15.0'
|
||||
implementation 'com.google.android.exoplayer:exoplayer-ui:2.15.0'
|
||||
implementation 'pub.devrel:easypermissions:3.0.0' // version >= 3.0.0 needs android X libraries
|
||||
implementation 'com.wefika:flowlayout:0.4.1'
|
||||
implementation 'com.googlecode.ez-vcard:ez-vcard:0.10.5'
|
||||
implementation 'org.jxmpp:jxmpp-jid:1.0.1'
|
||||
|
@ -106,11 +105,11 @@ android {
|
|||
|
||||
}
|
||||
}
|
||||
compileSdkVersion 29
|
||||
compileSdkVersion 30
|
||||
|
||||
defaultConfig {
|
||||
minSdkVersion 21
|
||||
targetSdkVersion 29
|
||||
targetSdkVersion 30
|
||||
|
||||
//versionNameSuffix " beta_(2021-12-08)" // " beta_(XXXX-XX-XX)" // activate for beta versions
|
||||
versionCode 109
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
||||
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
|
||||
<uses-permission android:name="android.permission.READ_CONTACTS" />
|
||||
<uses-permission android:name="android.permission.READ_PROFILE" />
|
||||
<uses-permission android:name="android.permission.READ_PHONE_STATE" android:maxSdkVersion="28" />
|
||||
|
@ -94,7 +95,7 @@
|
|||
<receiver android:name=".services.AlarmReceiver"></receiver>
|
||||
|
||||
<activity
|
||||
android:name="de.monocles.chat.ui.StartUI"
|
||||
android:name="de.pixart.messenger.ui.StartUI"
|
||||
android:configChanges="orientation|screenSize"
|
||||
android:label="@string/app_name"
|
||||
android:launchMode="singleTask"
|
||||
|
|
|
@ -0,0 +1,94 @@
|
|||
package de.pixart.messenger.ui;
|
||||
|
||||
import android.Manifest;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.os.Environment;
|
||||
import android.provider.Settings;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.core.app.ActivityCompat;
|
||||
|
||||
import eu.siacs.conversations.R;
|
||||
import eu.siacs.conversations.utils.Compatibility;
|
||||
import me.drakeet.support.toast.ToastCompat;
|
||||
|
||||
public class PermissionsActivity extends AppCompatActivity
|
||||
implements ActivityCompat.OnRequestPermissionsResultCallback {
|
||||
|
||||
private static final int PERMISSION_LENGTH = 2;
|
||||
public static final int STORAGE_PERMISSION = 0, ALL_FILES_PERMISSION = 1;
|
||||
|
||||
private final OnPermissionGranted[] permissionCallbacks = new OnPermissionGranted[PERMISSION_LENGTH];
|
||||
|
||||
@Override
|
||||
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
|
||||
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
|
||||
if (requestCode == STORAGE_PERMISSION) {
|
||||
if (Compatibility.hasStoragePermission(PermissionsActivity.this)) {
|
||||
permissionCallbacks[STORAGE_PERMISSION].onPermissionGranted();
|
||||
permissionCallbacks[STORAGE_PERMISSION] = null;
|
||||
} else {
|
||||
ToastCompat.makeText(this, R.string.no_storage_permission, Toast.LENGTH_SHORT).show();
|
||||
requestStoragePermission(permissionCallbacks[STORAGE_PERMISSION]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean checkStoragePermission() {
|
||||
return Compatibility.hasStoragePermission(PermissionsActivity.this);
|
||||
}
|
||||
|
||||
public void requestStoragePermission(@NonNull final PermissionsActivity.OnPermissionGranted onPermissionGranted) {
|
||||
final AlertDialog.Builder builder = new AlertDialog.Builder(this);
|
||||
builder.setTitle(R.string.intro_required_permissions);
|
||||
builder.setMessage(getString(R.string.no_storage_permission));
|
||||
builder.setNegativeButton(R.string.cancel, (dialog, which) -> finish());
|
||||
builder.setPositiveButton(R.string.grant, (dialog, which) -> {
|
||||
permissionCallbacks[STORAGE_PERMISSION] = onPermissionGranted;
|
||||
ActivityCompat.requestPermissions(PermissionsActivity.this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, STORAGE_PERMISSION);
|
||||
});
|
||||
builder.setOnCancelListener(dialog -> finish());
|
||||
final AlertDialog dialog = builder.create();
|
||||
dialog.setCanceledOnTouchOutside(false);
|
||||
dialog.setCancelable(false);
|
||||
dialog.show();
|
||||
}
|
||||
|
||||
public void requestAllFilesAccess(@NonNull final PermissionsActivity.OnPermissionGranted onPermissionGranted) {
|
||||
if (Compatibility.runsAndTargetsThirty(this) && !Environment.isExternalStorageManager()) {
|
||||
final AlertDialog.Builder builder = new AlertDialog.Builder(this);
|
||||
builder.setTitle(R.string.intro_required_permissions);
|
||||
builder.setMessage(getString(R.string.no_manage_storage_permission));
|
||||
builder.setNegativeButton(R.string.cancel, (dialog, which) -> finish());
|
||||
builder.setPositiveButton(R.string.grant, (dialog, which) -> {
|
||||
permissionCallbacks[ALL_FILES_PERMISSION] = onPermissionGranted;
|
||||
try {
|
||||
Intent intent = new Intent(Settings.ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION);
|
||||
Uri uri = Uri.fromParts("package", getPackageName(), null);
|
||||
intent.setData(uri);
|
||||
startActivityForResult(intent, ALL_FILES_PERMISSION);
|
||||
} catch (Exception e) {
|
||||
Intent intent = new Intent(Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION);
|
||||
Uri uri = Uri.fromParts("package", getPackageName(), null);
|
||||
intent.setData(uri);
|
||||
startActivityForResult(intent, ALL_FILES_PERMISSION);
|
||||
}
|
||||
});
|
||||
builder.setOnCancelListener(dialog -> finish());
|
||||
final AlertDialog dialog = builder.create();
|
||||
dialog.setCanceledOnTouchOutside(false);
|
||||
dialog.setCancelable(false);
|
||||
dialog.show();
|
||||
} else {
|
||||
StartUI.next(this);
|
||||
}
|
||||
}
|
||||
|
||||
public interface OnPermissionGranted {
|
||||
void onPermissionGranted();
|
||||
}
|
||||
}
|
|
@ -1,115 +1,66 @@
|
|||
package de.monocles.chat.ui;
|
||||
package de.pixart.messenger.ui;
|
||||
|
||||
import android.Manifest;
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.res.Configuration;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.provider.Settings;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import eu.siacs.conversations.Config;
|
||||
import eu.siacs.conversations.R;
|
||||
import eu.siacs.conversations.ui.ConversationsActivity;
|
||||
import eu.siacs.conversations.ui.util.IntroHelper;
|
||||
import pub.devrel.easypermissions.AfterPermissionGranted;
|
||||
import pub.devrel.easypermissions.EasyPermissions;
|
||||
|
||||
public class StartUI extends AppCompatActivity
|
||||
implements EasyPermissions.PermissionCallbacks {
|
||||
|
||||
private static final int NeededPermissions = 1000;
|
||||
String[] perms = {Manifest.permission.READ_EXTERNAL_STORAGE,
|
||||
Manifest.permission.WRITE_EXTERNAL_STORAGE,
|
||||
};
|
||||
import eu.siacs.conversations.utils.Compatibility;
|
||||
import eu.siacs.conversations.utils.ThemeHelper;
|
||||
|
||||
public class StartUI extends PermissionsActivity
|
||||
implements PermissionsActivity.OnPermissionGranted {
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_start_ui);
|
||||
setTheme(ThemeHelper.findDialog(this));
|
||||
IntroHelper.showIntro(this, false);
|
||||
requestNeededPermissions();
|
||||
}
|
||||
|
||||
@AfterPermissionGranted(NeededPermissions)
|
||||
private void requestNeededPermissions() {
|
||||
String PREF_FIRST_START = "FirstStart";
|
||||
SharedPreferences FirstStart = getApplicationContext().getSharedPreferences(PREF_FIRST_START, Context.MODE_PRIVATE);
|
||||
long FirstStartTime = FirstStart.getLong(PREF_FIRST_START, 0);
|
||||
if (EasyPermissions.hasPermissions(this, perms)) {
|
||||
// Already have permission, start ConversationsActivity
|
||||
Log.d(Config.LOGTAG, "All permissions granted, starting " + getString(R.string.app_name) + "(" + FirstStartTime + ")");
|
||||
Intent intent = new Intent(this, ConversationsActivity.class);
|
||||
intent.putExtra(PREF_FIRST_START, FirstStartTime);
|
||||
startActivity(intent);
|
||||
overridePendingTransition(R.animator.fade_in, R.animator.fade_out);
|
||||
finish();
|
||||
} else {
|
||||
// set first start to 0 if there are permissions to request
|
||||
Log.d(Config.LOGTAG, "Requesting required permissions");
|
||||
SharedPreferences.Editor editor = FirstStart.edit();
|
||||
editor.putLong(PREF_FIRST_START, 0);
|
||||
editor.commit();
|
||||
// Do not have permissions, request them now
|
||||
EasyPermissions.requestPermissions(this, getString(R.string.request_permissions_message),
|
||||
NeededPermissions, perms);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
|
||||
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
|
||||
// Forward results to EasyPermissions
|
||||
EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this);
|
||||
protected void onStart() {
|
||||
super.onStart();
|
||||
requestNeededPermissions();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPermissionsGranted(int requestCode, List<String> list) {
|
||||
Log.d(Config.LOGTAG, "Permissions granted:" + requestCode);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPermissionsDenied(int requestCode, List<String> list) {
|
||||
Log.d(Config.LOGTAG, "Permissions denied:" + requestCode);
|
||||
final AlertDialog dialog = new AlertDialog.Builder(this)
|
||||
.setMessage(getString(R.string.request_permissions_message_again))
|
||||
.setPositiveButton(getString(R.string.yes), new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
|
||||
Uri uri = Uri.fromParts("package", getPackageName(), null);
|
||||
intent.setData(uri);
|
||||
startActivity(intent);
|
||||
overridePendingTransition(R.animator.fade_in, R.animator.fade_out);
|
||||
}
|
||||
})
|
||||
.setNegativeButton(getString(R.string.no), new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
finish();
|
||||
}
|
||||
})
|
||||
.create();
|
||||
dialog.show();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onConfigurationChanged(Configuration newConfig) {
|
||||
super.onConfigurationChanged(newConfig);
|
||||
private void requestNeededPermissions() {
|
||||
if (Compatibility.runsTwentyThree()) {
|
||||
if (!checkStoragePermission()) {
|
||||
requestStoragePermission(this);
|
||||
}
|
||||
if (Compatibility.runsAndTargetsThirty(this)) {
|
||||
requestAllFilesAccess(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPermissionGranted() {
|
||||
next(this);
|
||||
}
|
||||
|
||||
public static void next(final Activity activity) {
|
||||
String PREF_FIRST_START = "FirstStart";
|
||||
SharedPreferences FirstStart = activity.getSharedPreferences(PREF_FIRST_START, Context.MODE_PRIVATE);
|
||||
long FirstStartTime = FirstStart.getLong(PREF_FIRST_START, 0);
|
||||
Intent intent = new Intent(activity, ConversationsActivity.class);
|
||||
intent.putExtra(PREF_FIRST_START, FirstStartTime);
|
||||
activity.startActivity(intent);
|
||||
activity.overridePendingTransition(R.animator.fade_in, R.animator.fade_out);
|
||||
activity.finish();
|
||||
}
|
||||
}
|
|
@ -150,7 +150,7 @@ public class XmppAxolotlMessage {
|
|||
try {
|
||||
SecretKey secretKey = new SecretKeySpec(innerKey, KEYTYPE);
|
||||
IvParameterSpec ivSpec = new IvParameterSpec(iv);
|
||||
Cipher cipher = Compatibility.twentyEight() ? Cipher.getInstance(CIPHERMODE) : Cipher.getInstance(CIPHERMODE, PROVIDER);
|
||||
Cipher cipher = Compatibility.runsTwentyEight() ? Cipher.getInstance(CIPHERMODE) : Cipher.getInstance(CIPHERMODE, PROVIDER);
|
||||
cipher.init(Cipher.ENCRYPT_MODE, secretKey, ivSpec);
|
||||
this.ciphertext = cipher.doFinal(Config.OMEMO_PADDING ? getPaddedBytes(plaintext) : plaintext.getBytes());
|
||||
if (Config.PUT_AUTH_TAG_INTO_KEY && this.ciphertext != null) {
|
||||
|
@ -255,7 +255,7 @@ public class XmppAxolotlMessage {
|
|||
ciphertext = newCipherText;
|
||||
key = newKey;
|
||||
|
||||
final Cipher cipher = Compatibility.twentyEight() ? Cipher.getInstance(CIPHERMODE) : Cipher.getInstance(CIPHERMODE, PROVIDER);
|
||||
final Cipher cipher = Compatibility.runsTwentyEight() ? Cipher.getInstance(CIPHERMODE) : Cipher.getInstance(CIPHERMODE, PROVIDER);
|
||||
SecretKeySpec keySpec = new SecretKeySpec(key, KEYTYPE);
|
||||
IvParameterSpec ivSpec = new IvParameterSpec(iv);
|
||||
|
||||
|
|
|
@ -367,7 +367,7 @@ public class ExportBackupService extends Service {
|
|||
backupFileHeader.write(dataOutputStream);
|
||||
dataOutputStream.flush();
|
||||
|
||||
final Cipher cipher = Compatibility.twentyEight() ? Cipher.getInstance(CIPHERMODE) : Cipher.getInstance(CIPHERMODE, PROVIDER);
|
||||
final Cipher cipher = Compatibility.runsTwentyEight() ? Cipher.getInstance(CIPHERMODE) : Cipher.getInstance(CIPHERMODE, PROVIDER);
|
||||
final byte[] key = getKey(password, salt);
|
||||
Log.d(Config.LOGTAG, backupFileHeader.toString());
|
||||
SecretKeySpec keySpec = new SecretKeySpec(key, KEYTYPE);
|
||||
|
|
|
@ -1862,6 +1862,11 @@ public class ConversationFragment extends XmppFragment implements EditMessage.Ke
|
|||
if (Config.ONLY_INTERNAL_STORAGE && permission.equals(Manifest.permission.WRITE_EXTERNAL_STORAGE) && permission.equals(Manifest.permission.READ_EXTERNAL_STORAGE)) {
|
||||
continue;
|
||||
}
|
||||
if (Compatibility.runsAndTargetsThirty(activity)) {
|
||||
if (Config.ONLY_INTERNAL_STORAGE && permission.equals(Manifest.permission.MANAGE_EXTERNAL_STORAGE)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (activity.checkSelfPermission(permission) != PackageManager.PERMISSION_GRANTED) {
|
||||
missingPermissions.add(permission);
|
||||
}
|
||||
|
|
|
@ -59,14 +59,22 @@ public class Compatibility {
|
|||
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.O;
|
||||
}
|
||||
|
||||
public static boolean runsTwentyThree() {
|
||||
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.M;
|
||||
}
|
||||
|
||||
public static boolean runsTwentyFour() {
|
||||
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.N;
|
||||
}
|
||||
|
||||
public static boolean twentyEight() {
|
||||
public static boolean runsTwentyEight() {
|
||||
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.P;
|
||||
}
|
||||
|
||||
public static boolean runsThirty() {
|
||||
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.R;
|
||||
}
|
||||
|
||||
private static boolean getBooleanPreference(Context context, String name, @BoolRes int res) {
|
||||
return getPreferences(context).getBoolean(name, context.getResources().getBoolean(res));
|
||||
}
|
||||
|
@ -86,6 +94,17 @@ public class Compatibility {
|
|||
return true; //when in doubt…
|
||||
}
|
||||
}
|
||||
private static boolean targetsThirty(Context context) {
|
||||
try {
|
||||
final PackageManager packageManager = context.getPackageManager();
|
||||
final ApplicationInfo applicationInfo = packageManager.getApplicationInfo(context.getPackageName(), 0);
|
||||
return applicationInfo == null || applicationInfo.targetSdkVersion >= 30;
|
||||
} catch (PackageManager.NameNotFoundException e) {
|
||||
return true; //when in doubt…
|
||||
} catch (RuntimeException e) {
|
||||
return true; //when in doubt…
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean targetsTwentyFour(Context context) {
|
||||
try {
|
||||
|
@ -98,13 +117,16 @@ public class Compatibility {
|
|||
return true; //when in doubt…
|
||||
}
|
||||
}
|
||||
public static boolean runsAndTargetsTwentyFour(Context context) {
|
||||
return runsTwentyFour() && targetsTwentyFour(context);
|
||||
}
|
||||
|
||||
public static boolean runsAndTargetsTwentySix(Context context) {
|
||||
return runsTwentySix() && targetsTwentySix(context);
|
||||
}
|
||||
|
||||
public static boolean runsAndTargetsTwentyFour(Context context) {
|
||||
return runsTwentyFour() && targetsTwentyFour(context);
|
||||
public static boolean runsAndTargetsThirty(Context context) {
|
||||
return runsThirty() && targetsThirty(context);
|
||||
}
|
||||
|
||||
public static boolean keepForegroundService(Context context) {
|
||||
|
|
|
@ -1162,4 +1162,6 @@
|
|||
<string name="plain_text_document">Plain text document</string>
|
||||
<string name="pref_import_settings_summary">Import app settings from settings.dat file within the monocles chat backup directory.</string>
|
||||
<string name="pref_import_settings">Import app settings</string>
|
||||
<string name="grant">Grant</string>
|
||||
<string name="no_manage_storage_permission">Since Android 11, apps needs a special permission to access all file types on the external storage. monocles chat will ask you to grant this permission to continue.</string>
|
||||
</resources>
|
||||
|
|
|
@ -163,6 +163,10 @@
|
|||
<item name="android:buttonStyle">@style/Widget.Conversations.Button.Borderless</item>
|
||||
</style>
|
||||
|
||||
<style name="Conversations.Dialog.Alert.Buttons" parent="Widget.AppCompat.Button.Borderless">
|
||||
<item name="android:textColor">@color/white</item>
|
||||
</style>
|
||||
|
||||
<style name="ExoMediaButton.Previous">
|
||||
<item name="android:visibility">gone</item>
|
||||
</style>
|
||||
|
|
|
@ -373,7 +373,7 @@
|
|||
</style>
|
||||
|
||||
<!-- blue dialog -->
|
||||
<style name="ConversationsTheme.Dialog" parent="Theme.MaterialComponents.Light.Dialog">
|
||||
<style name="ConversationsTheme.Dialog" parent="Theme.AppCompat.Light.Dialog">
|
||||
<item name="colorPrimary">@color/primary</item>
|
||||
<item name="colorPrimaryDark">@color/primary_dark</item>
|
||||
<item name="colorAccent">@color/accent</item>
|
||||
|
@ -385,10 +385,11 @@
|
|||
<item name="TextSizeBody2">14sp</item>
|
||||
<item name="TextSizeDisplay2">45sp</item>
|
||||
<item name="android:windowNoTitle">true</item>
|
||||
<item name="buttonBarButtonStyle">@style/Conversations.Dialog.Alert.Buttons</item>
|
||||
</style>
|
||||
|
||||
<!-- blue dialog - dark -->
|
||||
<style name="ConversationsTheme.Dark.Dialog" parent="Theme.MaterialComponents.Dialog">
|
||||
<style name="ConversationsTheme.Dark.Dialog" parent="Theme.AppCompat.Dialog">
|
||||
<item name="colorPrimary">@color/primary</item>
|
||||
<item name="colorPrimaryDark">@color/primary_dark</item>
|
||||
<item name="colorAccent">@color/accent</item>
|
||||
|
@ -399,6 +400,7 @@
|
|||
<item name="TextSizeBody2">14sp</item>
|
||||
<item name="TextSizeDisplay2">45sp</item>
|
||||
<item name="android:windowNoTitle">true</item>
|
||||
<item name="buttonBarButtonStyle">@style/Conversations.Dialog.Alert.Buttons</item>
|
||||
</style>
|
||||
|
||||
<!-- blue dialog - black -->
|
||||
|
|
Loading…
Reference in a new issue