Compare commits

...

7 Commits

Author SHA1 Message Date
r4sas 97abcc661f 2.45.1
Signed-off-by: r4sas <r4sas@i2pmail.org>
2023-01-11 22:59:51 +00:00
R4SAS 8a791c45c2 [readme] add release singing fingerprint info
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2023-01-08 21:22:49 +03:00
R4SAS 4334fd4bdb 2.45.0.2
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2023-01-08 20:16:24 +03:00
R4SAS f0132e9847 fix permissions asker activity start on some android 11+ devices
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2023-01-08 20:14:17 +03:00
R4SAS 06b567d910 2.45.0.1
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2023-01-07 15:01:54 +00:00
R4SAS dd17608af9 fix permissions API level
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2023-01-07 17:38:18 +03:00
R4SAS 2e10678278 add MANAGE_EXTERNAL_STORAGE permission for API 30+
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2023-01-07 17:33:10 +03:00
12 changed files with 125 additions and 73 deletions
+7 -1
View File
@@ -71,4 +71,10 @@ Download Android SDK command line tools for Windows, unpack and install it repla
`ANDROID_SDK_ROOT` variable must point to SDK using linux-way path, like `/c/dev/android-sdk` when SDK installed to `C:\dev\android-sdk`.
Gradle can be called with `./gradlew` command inside project root, or you can install it using `pacman` and call `gradle` like on linux.
Gradle can be called with `./gradlew` command inside project root, or you can install it using `pacman` and call `gradle` like on linux.
## Release signing
Current releases signed with certificate fingerprint (SHA-256):
`FC:C3:C7:34:9E:22:6A:77:B3:70:46:BB:00:FD:04:BB:A5:30:32:21:01:F8:62:F3:6D:8C:3D:B0:EB:B6:35:20`
+7 -6
View File
@@ -3,19 +3,19 @@ plugins {
}
dependencies {
implementation 'androidx.core:core:1.6.0'
implementation 'androidx.core:core:1.9.0'
implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.1.0'
}
android {
compileSdkVersion 32
compileSdkVersion 33
defaultConfig {
applicationId "org.purplei2p.i2pd"
targetSdkVersion 32
targetSdkVersion 33
minSdkVersion 16
versionCode 2450000
versionName "2.45.0"
versionCode 2450100
versionName "2.45.1"
archivesBaseName += "-$versionName"
ndkVersion "23.2.8568313"
@@ -73,6 +73,7 @@ android {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}
namespace 'org.purplei2p.i2pd'
}
ext.abiCodes = ['armeabi-v7a': 1, 'x86': 2, 'arm64-v8a': 3, 'x86_64': 4]
@@ -83,7 +84,7 @@ android.applicationVariants.all { variant ->
def baseAbiVersionCode = project.ext.abiCodes.get(output.getFilter(OutputFile.ABI))
if (baseAbiVersionCode != null) {
output.versionCodeOverride = baseAbiVersionCode * 10 + variant.versionCode
output.versionCodeOverride = baseAbiVersionCode + variant.versionCode
}
}
}
+10 -5
View File
@@ -1,12 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.purplei2p.i2pd"
xmlns:tools="http://schemas.android.com/tools"
android:installLocation="auto">
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"
android:maxSdkVersion="29" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"
android:maxSdkVersion="29" />
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE"
tools:ignore="ScopedStorage" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
@@ -41,13 +45,14 @@
android:label="NetworkChangeReceiver"
android:exported="true" >
<intent-filter>
<action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
<action android:name="android.net.conn.CONNECTIVITY_CHANGE"
tools:ignore="BatteryLife" />
</intent-filter>
</receiver>
<activity
android:name=".I2PDPermsAskerActivity"
android:exported="false" >
android:exported="true" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
@@ -1,5 +1,7 @@
package org.purplei2p.i2pd;
import static android.app.PendingIntent.FLAG_IMMUTABLE;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
@@ -139,19 +141,19 @@ public class ForegroundService extends Service {
// The PendingIntent to launch our activity if the user selects this notification
PendingIntent contentIntent = PendingIntent.getActivity(this, 0,
new Intent(this, I2PDActivity.class), 0);
new Intent(this, I2PDActivity.class),
Build.VERSION.SDK_INT >= Build.VERSION_CODES.M ? FLAG_IMMUTABLE : 0);
// If earlier version channel ID is not used
// https://developer.android.com/reference/android/support/v4/app/NotificationCompat.Builder.html#NotificationCompat.Builder(android.content.Context)
String channelId = Build.VERSION.SDK_INT >= 26 ? createNotificationChannel() : "";
String channelId = Build.VERSION.SDK_INT >= Build.VERSION_CODES.O ? createNotificationChannel() : "";
// Set the info for the views that show in the notification panel.
NotificationCompat.Builder builder = new NotificationCompat.Builder(this, channelId)
.setOngoing(true)
.setSmallIcon(R.drawable.ic_notification_icon); // the status icon
if (Build.VERSION.SDK_INT >= 16)
builder = builder.setPriority(Notification.PRIORITY_DEFAULT);
if (Build.VERSION.SDK_INT >= 21)
builder = builder.setPriority(Notification.PRIORITY_DEFAULT);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
builder = builder.setCategory(Notification.CATEGORY_SERVICE);
Notification notification = builder
.setTicker(text) // the status text
@@ -20,6 +20,7 @@ import android.net.ConnectivityManager;
import android.net.Uri;
import android.os.Bundle;
import android.os.Build;
import android.os.Environment;
import android.os.IBinder;
import android.os.PowerManager;
import android.preference.PreferenceManager;
@@ -126,11 +127,17 @@ public class I2PDActivity extends Activity {
daemon.addStateChangeListener(daemonStateUpdatedListener);
daemonStateUpdatedListener.daemonStateUpdate(DaemonWrapper.State.uninitialized, daemon.getState());
// request permissions
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
if(!Environment.isExternalStorageManager()) {
Log.e(TAG, "MANAGE_EXTERNAL_STORAGE perm declined, stopping i2pd");
i2pdStop();
}
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
new String[] { Manifest.permission.WRITE_EXTERNAL_STORAGE },
MY_PERMISSION_REQUEST_WRITE_EXTERNAL_STORAGE);
}
}
@@ -4,7 +4,11 @@ import android.Manifest;
import android.app.Activity;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.provider.Settings;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
@@ -16,6 +20,7 @@ import java.lang.reflect.Method;
public class I2PDPermsAskerActivity extends Activity {
private static final int PERMISSION_WRITE_EXTERNAL_STORAGE = 0;
private static final int PERMISSION_MANAGE_EXTERNAL_STORAGE = 0;
private Button button_request_write_ext_storage_perms;
private TextView textview_retry;
@@ -24,7 +29,7 @@ public class I2PDPermsAskerActivity extends Activity {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//if less than Android 6, no runtime perms req system present
if (android.os.Build.VERSION.SDK_INT < 23) {
if (android.os.Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
startMainActivity();
return;
}
@@ -48,57 +53,66 @@ public class I2PDPermsAskerActivity extends Activity {
textview_retry.setVisibility(TextView.GONE);
button_request_write_ext_storage_perms.setVisibility(Button.GONE);
Method methodCheckPermission;
Method method_shouldShowRequestPermissionRationale;
Method method_requestPermissions;
try {
methodCheckPermission = getClass().getMethod("checkSelfPermission", String.class);
method_shouldShowRequestPermissionRationale =
getClass().getMethod("shouldShowRequestPermissionRationale", String.class);
method_requestPermissions =
getClass().getMethod("requestPermissions", String[].class, int.class);
} catch (NoSuchMethodException e) {
throw new RuntimeException(e);
}
Integer resultObj;
try {
resultObj = (Integer) methodCheckPermission.invoke(
this, Manifest.permission.WRITE_EXTERNAL_STORAGE);
} catch (Throwable e) {
throw new RuntimeException(e);
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
if(!Environment.isExternalStorageManager()) {
showExplanation();
} else {
startMainActivity();
}
} else {
Method methodCheckPermission;
Method method_shouldShowRequestPermissionRationale;
Method method_requestPermissions;
if (resultObj != PackageManager.PERMISSION_GRANTED) {
// Should we show an explanation?
Boolean aBoolean;
try {
aBoolean = (Boolean) method_shouldShowRequestPermissionRationale.invoke(this,
Manifest.permission.WRITE_EXTERNAL_STORAGE);
} catch (Exception e) {
methodCheckPermission = getClass().getMethod("checkSelfPermission", String.class);
method_shouldShowRequestPermissionRationale =
getClass().getMethod("shouldShowRequestPermissionRationale", String.class);
method_requestPermissions =
getClass().getMethod("requestPermissions", String[].class, int.class);
} catch (NoSuchMethodException e) {
throw new RuntimeException(e);
}
if (aBoolean) {
// Show an explanation to the user *asynchronously* -- don't block
// this thread waiting for the user's response! After the user
// sees the explanation, try again to request the permission.
Integer resultObj;
showExplanation();
} else {
// No explanation needed, we can request the permission.
try {
resultObj = (Integer) methodCheckPermission.invoke(
this, Manifest.permission.WRITE_EXTERNAL_STORAGE);
} catch (Throwable e) {
throw new RuntimeException(e);
}
if (resultObj != PackageManager.PERMISSION_GRANTED) {
// Should we show an explanation?
Boolean aBoolean;
try {
method_requestPermissions.invoke(this,
new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
PERMISSION_WRITE_EXTERNAL_STORAGE);
aBoolean = (Boolean) method_shouldShowRequestPermissionRationale.invoke(this,
Manifest.permission.WRITE_EXTERNAL_STORAGE);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
} else startMainActivity();
if (aBoolean) {
// Show an explanation to the user *asynchronously* -- don't block
// this thread waiting for the user's response! After the user
// sees the explanation, try again to request the permission.
showExplanation();
} else {
// No explanation needed, we can request the permission.
try {
method_requestPermissions.invoke(this,
new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
PERMISSION_WRITE_EXTERNAL_STORAGE);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
} else startMainActivity();
}
}
@Override
@@ -136,6 +150,7 @@ public class I2PDPermsAskerActivity extends Activity {
}
private static final int SHOW_EXPLANATION_REQUEST = 1; // The request code
private static final int APP_STORAGE_ACCESS_REQUEST_CODE = 2;
private void showExplanation() {
Intent intent = new Intent(this, I2PDPermsExplanationActivity.class);
@@ -144,11 +159,14 @@ public class I2PDPermsAskerActivity extends Activity {
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
// Check which request we're responding to
if (requestCode == SHOW_EXPLANATION_REQUEST) {
// Make sure the request was successful
if (resultCode == RESULT_OK) {
// Request the permission
super.onActivityResult(requestCode, resultCode, data);
// Check which request we're responding to and make sure the request was successful
if (requestCode == SHOW_EXPLANATION_REQUEST && resultCode == RESULT_OK) {
// Request the permission
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
Intent intentManageAccess = new Intent(Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION, Uri.parse("package:" + BuildConfig.APPLICATION_ID));
startActivityForResult(intentManageAccess, APP_STORAGE_ACCESS_REQUEST_CODE);
} else {
Method method_requestPermissions;
try {
method_requestPermissions =
@@ -163,9 +181,19 @@ public class I2PDPermsAskerActivity extends Activity {
} catch (Exception e) {
throw new RuntimeException(e);
}
} else {
finish(); //close the app
}
} else if (requestCode == APP_STORAGE_ACCESS_REQUEST_CODE && resultCode == RESULT_OK) {
if (Environment.isExternalStorageManager()) {
startMainActivity();
} else {
textview_retry.setText(R.string.permDenied);
textview_retry.setVisibility(TextView.VISIBLE);
button_request_write_ext_storage_perms.setVisibility(Button.VISIBLE);
finish();
}
} else {
finish(); // close the app
}
}
}
+3 -3
View File
@@ -1,17 +1,17 @@
buildscript {
repositories {
jcenter()
mavenCentral()
google()
}
dependencies {
classpath 'com.android.tools.build:gradle:7.1.3'
classpath 'com.android.tools.build:gradle:7.3.1'
}
}
allprojects {
repositories {
google()
jcenter()
mavenCentral()
}
}
@@ -0,0 +1 @@
* Fix storage access issue on Android 11+
@@ -0,0 +1 @@
* Fix installation and start on some Android 11+ devices
@@ -0,0 +1 @@
* Updated codebase to 2.45.1
+2 -2
View File
@@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionSha256Sum=f581709a9c35e9cb92e16f585d2c4bc99b2b1a5f85d2badbd3dc6bff59e1e6dd
distributionUrl=https\://services.gradle.org/distributions/gradle-7.2-bin.zip
distributionSha256Sum=8cc27038d5dbd815759851ba53e70cf62e481b87494cc97cfd97982ada5ba634
distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists