2

In the AndroidManifest.xml of my app I specified a target API to 26:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.javasrv"
android:minSdkVersion="23"
android:targetSdkVersion="26"
android:versionCode="6"
android:versionName="1.0.0">
    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

But when I am running the app on Android x86 8.1 and disabling the permission for storage access through system menu it says that "This app was designed for an older version of Android. Denying permission may cause it to no longer function as intended."

How can it be?

Also I am having a problem with runtime permissions check: it always deems that the access is granted even though I disabled it in the system settings:

if (ContextCompat.checkSelfPermission(LoaderActivity.this, permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
    Toast.makeText(LoaderActivity.this, "PERMISSION_DENIED", Toast.LENGTH_SHORT).show();
    Log.d("*** Loader::onCreate ***", "PERMISSION_DENIED");
    if (ActivityCompat.shouldShowRequestPermissionRationale(this, permission.WRITE_EXTERNAL_STORAGE)) {
    } else {
    }
    ActivityCompat.requestPermissions(this, new String[]{permission.WRITE_EXTERNAL_STORAGE}, 0);
} else {
    Toast.makeText(LoaderActivity.this, "PERMISSION_GRANTED", Toast.LENGTH_SHORT).show();
    Log.d("*** Loader::onCreate ***", "PERMISSION_GRANTED");
}

Again, it is unclear how can it be. Any ideas?

Edit: I am using android api v26 and android support library v23.

The compilation script:

file=javasrv.apk

# export CLASSPATH=/opt/android-sdk/platforms/android-26/android.jar:/opt/android-sdk/extras/android/support-library/23.2.1/android-support-v4.jar
#
rm -f com/javasrv/*.class
javac -cp $CLASSPATH -source 1.8 -target 1.8 com/javasrv/*.java
#dx --dex --output classes.dex com/javasrv/*.class
dx --dex --output classes.dex com/javasrv/*.class android/support/v4/app/*.class android/support/v4/content/*.class

#aapt package -f -m -F "$file" -M AndroidManifest.xml -S res -I "$CLASSPATH"
#aapt add "$file" classes.dex
rm -rf build && mkdir build
find ./res -type f  | grep -vE '\.sw.$' | xargs -I{} aapt2 compile -o build "{}" --no-crunch
aapt2 link -R build/* --manifest AndroidManifest.xml $(echo "$CLASSPATH" | tr -d '\n' | xargs -d':' -L1 -I{} echo " -I {} ") -o "$file" --auto-add-overlay
zip -uj "$file" classes.dex

zipalign -f 4 "$file" "$file.aligned"
mv -f "$file.aligned" "$file"
apksigner sign --ks-pass pass:pwd --ks javasrv.keystore "$file"

Edit2: Here is another may be related to this one problem concerning aapt2. If I specify compileSdkVersion in AndroidManifest.xml it throws an error:

AndroidManifest.xml:2: error: attribute android:compileSdkVersion not found.
error: failed processing manifest.

I simply ignored it by removing compileSdkVersion from the manifest. I wonder now if I should not...

Edit3: As related to logcat of that permission check. I only have access to /data/log.txt. But it should be enough. No?

08-16 19:24:39.236 18965 18965 E /system/bin/webview_zygote32: Failed to make and chown /acct/uid_99182: Permission denied
08-16 19:24:39.236 18965 18965 E Zygote  : createProcessGroup(99182, 0) failed: Permission denied
08-16 19:24:39.239  2219  2900 I am_proc_start: [0,18965,99182,com.android.chrome:sandboxed_process0,webview_service,com.javasrv/org.chromium.content.app.SandboxedProcessService0]
08-16 19:24:39.239  2219  2900 I ActivityManager: Start proc 18965:com.android.chrome:sandboxed_process0/u0i182 for webview_service com.javasrv/org.chromium.content.app.SandboxedProcessService0
08-16 19:24:39.255 18965 18965 W /system/bin/webview_zygote32: Unexpected CPU variant for X86 using defaults: x86_64
08-16 19:24:39.256 18931 18931 I auditd  : type=1400 audit(0.0:3392): avc: denied { read } for comm="com.javasrv" name="vmstat" dev="proc" ino=4026531858 scontext=u:r:untrusted_app_25:s0:c512,c768 tcontext=u:object_r:proc:s0 tclass=file permissive=1
08-16 19:24:39.256 18931 18931 I com.javasrv: type=1400 audit(0.0:3392): avc: denied { read } for name="vmstat" dev="proc" ino=4026531858 scontext=u:r:untrusted_app_25:s0:c512,c768 tcontext=u:object_r:proc:s0 tclass=file permissive=1
08-16 19:24:39.256 18931 18931 I auditd  : type=1400 audit(0.0:3393): avc: denied { open } for comm="com.javasrv" path="/proc/vmstat" dev="proc" ino=4026531858 scontext=u:r:untrusted_app_25:s0:c512,c768 tcontext=u:object_r:proc:s0 tclass=file permissive=1
08-16 19:24:39.256 18931 18931 I com.javasrv: type=1400 audit(0.0:3393): avc: denied { open } for path="/proc/vmstat" dev="proc" ino=4026531858 scontext=u:r:untrusted_app_25:s0:c512,c768 tcontext=u:object_r:proc:s0 tclass=file permissive=1
08-16 19:24:39.263 18959 18959 W zygote  : Unexpected CPU variant for X86 using defaults: x86_64
08-16 19:24:39.281  1022  1022 I auditd  : type=1400 audit(0.0:3395): avc: denied { read } for comm="loop0" path="/mnt/android-8.1-r2/system.img" dev="vda2" ino=1422631 scontext=u:r:kernel:s0 tcontext=u:object_r:unlabeled:s0 tclass=file permissive=1
08-16 19:24:39.281  1022  1022 I loop0   : type=1400 audit(0.0:3395): avc: denied { read } for path="/mnt/android-8.1-r2/system.img" dev="vda2" ino=1422631 scontext=u:r:kernel:s0 tcontext=u:object_r:unlabeled:s0 tclass=file permissive=1
08-16 19:24:39.289  2671  2691 D SubscriptionController: [getPhoneId] asked for default subId=-1
08-16 19:24:39.290  2671  2691 D SubscriptionController: [getSubId]- invalid slotIndex=-1
08-16 19:24:39.336 18931 18931 D *** Loader::onCreate ***: PERMISSION_GRANTED
08-16 19:24:39.336 18931 18931 D *** getListFiles ***: [W]/sdcard/Download/FDroid.apk
08-16 19:24:39.336 18931 18931 D *** getListFiles ***: [W]/sdcard/Download/javasrv.apk

Edit4: This is how the activity from which I am requesting permissions gets started:

Intent intent = new Intent(this, LoaderActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
// If set in an Intent passed to Context.startActivity(), this flag will cause any existing task that would be associated with the activity to be cleared before the activity is started. That is, the activity becomes the new root of an otherwise empty task, and any old activities are finished. This can only be used in conjunction with FLAG_ACTIVITY_NEW_TASK.
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(intent);

Edit 5: Holy cow! I just decompiled the resulted apk and noticed that somehow my android:versionCode and android:versionName became platformbuildversioncode and platformbuildversionname respectively. This is nuts! I wonder how the hell it happened. Added: Uh oh. It is somehow related to the version of aapt2. I used from build-tools 28.0.3. In changed it to 26.0.2 and it behaved without that insanity.

Edit 6: Due to the bugs with aapt2, I reverted back to aapt. At least it doesn't messing up the manifest too much:

<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:minSdkVersion="23" android:targetSdkVersion="26" package="com.javasrv" platformBuildVersionCode="26" platformBuildVersionName="8.0.0">

For some reason it excised my app custom version number and version code though. But at least that should not affect the work of an app. What I am still struggling with though is that I cannot specify compileSdkVersion due to the same error that compileSdkVersion was not found in the package android.

Edit 7: Alright. Here is the head of the manifest that I decompiled from the final apk(which I built with aapt2 v26):

<?xml version="1.0" encoding="utf-8" standalone="no"?><manifest xmlns:android="http://schemas.android.com/apk/res/android" android:minSdkVersion="23" android:targetSdkVersion="26" package="com.javasrv">
    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

So the only thing is missing is compileSdkVersion. I still can't figure out how to make aapt2 put that value into the manifest. But I tested that apk and the bug with runtime permissions still persist. Very strange.

Edit 8: Installed the latest aapt2 version. From here: https://dl.google.com/dl/android/maven2/com/android/tools/build/aapt2/3.6.0-alpha11-5720371/aapt2-3.6.0-alpha11-5720371-linux.jar Still the same thing - it would not insert compileSdkVersion.

Edit 9: Actually it is pretty clear that compiledSdkVersion isn't present in the namespace I am using. I also cannot find it anywhere in the docs: https://developer.android.com/guide/topics/manifest/uses-sdk-element It appears to me that I should not use it at all - and actually I don't see any purpose in it. Who the hell cares with what version I compiled my app, if I can just specify the minimum and target versions? So the bug should be somewhere else.

Edit 10: Updated up to 24.1.1 version of Android Support Library. Stilll no luck with the check of runtime permissions.

Edit 11: Tried to call requestPermissions even though it falsily detects it as GRANTED and got a runtime error: that classs android.support.v4.app.ActivityCompatApi23 was not found. Interesting... Hm. Apparently I should've used Android Support Library the same version as my SDK. But it is unclear for me how to get a jar of the latest version of a support library (see Install latest android support library CLI ) So yeah. Probably it was a bad idea just to extract the jar file from 24.1.1's aar - apparently it wasn't the whole library but just a patch. So I decided to use jar 23.2.1 which some guy compiled: https://github.com/pbakondy/cordova-plugin-android-support-v4-jar

Edit 12: With v23.2.1 android support library back in place I decided to call requestPermissions right after I called Log.d with PERMISSION_GRANTED message. Here is the output:

08-17 12:50:15.132 28837 28837 D *** Loader::onCreate ***: PERMISSION_GRANTED
08-17 12:50:15.136 28837 28891 I com.javasrv: android::hardware::configstore::V1_0::ISurfaceFlingerConfigs::hasWideColorDisplay retrieved: 0
08-17 12:50:15.139  2219  2600 I ActivityManager: START u0 {act=android.content.pm.action.REQUEST_PERMISSIONS pkg=com.google.android.packageinstaller cmp=com.google.android.packageinstaller/com.android.packageinstaller.permission.ui.GrantPermissionsActivity (has extras)} from uid 10081
08-17 12:50:15.141  2219  2600 I wm_task_moved: [179,1,6]
08-17 12:50:15.142  2219  2600 I am_create_activity: [0,28890900,179,com.google.android.packageinstaller/com.android.packageinstaller.permission.ui.GrantPermissionsActivity,android.content.pm.action.REQUEST_PERMISSIONS,NULL,NULL,8388608]
08-17 12:50:15.147  2219  2600 I am_pause_activity: [0,43511476,com.javasrv/.LoaderActivity]
08-17 12:50:15.182  2446  2446 V StatusBar: setLightsOn(true)
08-17 12:50:15.183 28837 28837 I am_on_resume_called: [0,com.javasrv.LoaderActivity,LAUNCH_ACTIVITY]
08-17 12:50:15.254 28837 28873 W cr_media: Requires BLUETOOTH permission
08-17 12:50:15.273 28837 28837 I am_on_paused_called: [0,com.javasrv.LoaderActivity,handlePauseActivity]
08-17 12:50:15.284  2219  2259 I am_restart_activity: [0,28890900,179,com.google.android.packageinstaller/com.android.packageinstaller.permission.ui.GrantPermissionsActivity]
08-17 12:50:15.285  2219  2259 I am_set_resumed_activity: [0,com.google.android.packageinstaller/com.android.packageinstaller.permission.ui.GrantPermissionsActivity,minimalResumeActivityLocked]
08-17 12:50:15.291  2219  2298 I sysui_count: [window_time_0,3]
08-17 12:50:15.291  2219  2298 I sysui_multi_action: [757,803,799,window_time_0,802,3]
08-17 12:50:15.297  2446  2446 V StatusBar: setLightsOn(true)
08-17 12:50:15.304  2219  5022 I am_finish_activity: [0,28890900,179,com.google.android.packageinstaller/com.android.packageinstaller.permission.ui.GrantPermissionsActivity,app-request]
08-17 12:50:15.305  2219  5022 I am_pause_activity: [0,28890900,com.google.android.packageinstaller/com.android.packageinstaller.permission.ui.GrantPermissionsActivity]
08-17 12:50:15.308  2219  2298 I sysui_count: [window_time_0,0]
08-17 12:50:15.308  2219  2298 I sysui_multi_action: [757,803,799,window_time_0,802,0]
08-17 12:50:15.439  2219  2259 I am_set_resumed_activity: [0,com.javasrv/.LoaderActivity,resumeTopActivityInnerLocked]
08-17 12:50:15.446  2219  2259 I am_resume_activity: [0,43511476,179,com.javasrv/.LoaderActivity]
08-17 12:50:15.457  2219  2298 I sysui_count: [window_time_0,0]
08-17 12:50:15.457  2219  2298 I sysui_multi_action: [757,803,799,window_time_0,802,0]
08-17 12:50:15.557  2446  2446 I chatty  : uid=10030(com.android.systemui) identical 5 lines
08-17 12:50:15.594  2446  2446 V StatusBar: setLightsOn(true)

No dialog appeared. It looks like the system makes the app think that the permission was granted.

I wonder why ... there must be something wrong with the manifest, but what?

I will output the whole manifest via apkanalyzer:

<?xml version="1.0" encoding="utf-8"?>
<manifest
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:minSdkVersion="23"
    android:versionCode="6"
    android:versionName="1.0.0"
    android:targetSdkVersion="26"
    package="com.javasrv">

    <uses-permission
        android:name="android.permission.RECEIVE_BOOT_COMPLETED" />

    <uses-permission
        android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

    <application
        android:label="@ref/0x7f060000"
        android:icon="@ref/0x7f020000">

        <activity
            android:theme="@ref/0x010300f0"
            android:label="@ref/0x7f060000"
            android:name="com.javasrv.MainActivity">

            <intent-filter>

                <action
                    android:name="android.intent.action.MAIN" />

                <category
                    android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

        <activity
            android:theme="@ref/0x010300f0"
            android:label="@ref/0x7f060000"
            android:name="com.javasrv.LoaderActivity">

            <intent-filter>

                <action
                    android:name="android.intent.action.MAIN" />

                <category
                    android:name="android.intent.category.DEFAULT" />
            </intent-filter>
        </activity>

        <activity
            android:theme="@ref/0x01030011"
            android:label="@string/0xb"
            android:icon="@ref/0x7f010000"
            android:name="com.javasrv.TestActivity"
            android:screenOrientation="1">

            <intent-filter>

                <action
                    android:name="android.intent.action.MAIN" />

                <category
                    android:name="android.intent.category.DEFAULT" />
            </intent-filter>
        </activity>

        <service
            android:name=".MyTestService" />

        <service
            android:name=".MyJobService"
            android:permission="android.permission.BIND_JOB_SERVICE" />

        <receiver
            android:name="Boot">

            <intent-filter
                android:priority="100">

                <action
                    android:name="android.intent.action.BOOT_COMPLETED" />
            </intent-filter>
        </receiver>
    </application>
</manifest>

Any ideas?

THE PROBLEM HAS BEEN SOLVED

reardenlife
  • 317
  • 4
  • 15
  • user this liberary https://github.com/ParkSangGwon/TedPermission. It will help you handle permissions very easily. – Faisal Sep 12 '19 at 23:53
  • Try reinstalling the app – Kyle Emmanuel Sep 12 '19 at 23:58
  • and what is `permission` ?? – Martin Zeitler Sep 13 '19 at 00:03
  • @Kyle Emmanuel trying reinstall (before posting this question). No luck. – reardenlife Sep 13 '19 at 00:04
  • @Martin Zeitler I made import android.Manifest.*; in my code, so it is just a string from that package. – reardenlife Sep 13 '19 at 00:05
  • @Faisal thanks. But I believe it will just mask the problem. I think something is wrong with my code somewhere. – reardenlife Sep 13 '19 at 00:08
  • @reardenlife almost thought so, just to make sure those string match. it's just uncommon not to build with Gradle - but the build.script does not matter too much... but the logcat of that permission check would be interesting. – Martin Zeitler Sep 13 '19 at 00:08
  • @Martin Zeitler, I only have an access to /data/log.txt right now. See Edit3. Usually it was enough. LMK if it you want to see logcat. – reardenlife Sep 13 '19 at 00:47
  • @Martin Zeitler, holy cow dude. Apparently there is a bug somewhere with platformbuildversioncode & platformbuildversionname somewhere in my project. – reardenlife Sep 13 '19 at 03:19
  • It reads "PERMISSION_GRANTED". while AAPT2 is generally pretty stable, at least while not having illegal entries in the resources, which were only tolerated and ignored previously. The OS can likely not determine which API level is being targeted, explaining the one error message. Migration to Gradle might be the most easy way to get the project back on track. – Martin Zeitler Sep 13 '19 at 03:58
  • @Martin Zeitler, I updated the main post. I tried to use aapt and aapt2 of version 26, which apparently doesn't have the bug I described. But it didn't solve the problem. :)) Same thing basically. minSdkVersion & targetSdkVersion are written into the manifest just like in my original one. So the OS should understand everything correctly. But it doesn't. I wonder if the problem is connected with the fact that I cannot put compileSdkVersion into the manifest.. – reardenlife Sep 13 '19 at 04:08
  • @Martin Zeitler > "It reads "PERMISSION_GRANTED"." Huh? Where? I am not sure what it reads. I just grepped the output by what my java code outputs ("PERMISSION_GRANTED") and dumped the lines with the events that occured at the same second. There are some " avc: denied " .. not sure what they are. – reardenlife Sep 13 '19 at 04:19
  • @Martin Zeitler, I described the current state of affairs in my last edit. Apparently the bug could be due to missing compileSdkVersion in the manifest. That's probably the only option. I am not sure what to do at this point. It is either figure out why aapt2 doesn't pick up compileSdkVersion or figure out how to put my own AndroidManifest.xml into the final apk. – reardenlife Sep 13 '19 at 04:22
  • @Martin Zeitler plz see edit 12. :) – reardenlife Sep 13 '19 at 18:07

3 Answers3

0

May be this can help you.

Just make your in your app gradle you have compileSdkVersion and targetSdkVersion as 26.

Suman Kumar Dash
  • 681
  • 5
  • 19
  • I am not using gradle. I am using bash (see above). – reardenlife Sep 13 '19 at 00:02
  • For some reason, I could not specify compileSdkVersion in the AndroidManifest due to very strange aapt2 error. Is it really necessary? – reardenlife Sep 13 '19 at 00:03
  • those entries in the `AndroidManifest.xml` are somewhat useless, because Gradle will overwrite them, when merging the manifests. – Martin Zeitler Sep 13 '19 at 00:04
  • @Martin Zeitler, sure. For that reason I am not using gradle. I am using bash. :) – reardenlife Sep 13 '19 at 00:07
  • I updated the question. Added Edit2 with compileSdkVersion problem. – reardenlife Sep 13 '19 at 00:17
  • @reardenlife before I wrote a little bash script for JDK setup, but in general it is more convenient to work with Gradle, because the IDE has some useful code-inspection features (which occasionally find issues one might otherwise overlook). – Martin Zeitler Sep 13 '19 at 00:18
  • @Martin Zeitler, yeah, I know, I know. :) But I am working on smartphone right now and all I have is an access to the server via SSH where I am using vim with syntax highlight to write some java code. And I have another VPS where Android x86 is installed as a testing platform. And another VPS where Android Emulator is installed just in case. :) This is nuts, but it works. – reardenlife Sep 13 '19 at 00:50
  • Can you please add android:compileSdkVersion=" your compile sdk version" in Manifest. – Suman Kumar Dash Sep 13 '19 at 00:53
  • @Suman Dash, I tried. It causes the error I described in Edit2.. But you right. Let me see how I can fix that bug first.. – reardenlife Sep 13 '19 at 00:58
  • Tried to decompiled via apktool 2.4.0, edit the manifest and writing compileSdkVersion manually. No luck. Somehow it just doesn't accept it (removed a folder build with a compiled manifest version of course). Tried to specify api version with apktool's --api option. No luck. I should probably figure out how to do it properly with aapt2. Hmm.. – reardenlife Sep 13 '19 at 01:50
  • @Suman Dash, I thought it over (see Edit 9). I think I should leave compileSdkVersion alone. It must be some kind of Gradle-specific feature. – reardenlife Sep 13 '19 at 15:48
  • And BTW, the contents of the manifest embedded into apk can be viewed via *apkanalyzer manifest print* – reardenlife Sep 13 '19 at 18:06
0

If checkpermission is not working you can try the dialog permission

When your app receives PERMISSION_DENIED from checkSelfPermission(), you need to prompt the user for that permission. Android provides several methods you can use to request a permission, such as requestPermissions().

  ActivityCompat.requestPermissions(this,
                    new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
                    1);

Then override the method

  @Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    switch (requestCode) {
        case 1: {
            // If request is cancelled, the result arrays are empty.
            if (grantResults.length > 0
                    && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                // permission was granted

            } else {
                // permission denied

                Toast.makeText(BiggerScreen.this, "Permission denied to write your External storage", Toast.LENGTH_SHORT).show();
            }
            return;
        }
        // other 'case' lines to check for other
        // permissions this app might request
    }
}
Cyrille Con Morales
  • 918
  • 1
  • 6
  • 21
0

Wow. All that time the problem was with AndroidManifest.xml. I specified minSdkVersion in the wrong place. I should've done that in uses-sdk xml tag, not in manifest tag, just like on the Android Developer website is written: https://developer.android.com/guide/topics/manifest/uses-sdk-element

I don't know where I picked up an idea that these attributes should be written in manifest tag. Perhaps this is what gradle is doing - it transfers the attributes when compiling the apk..

Edit: In addition, one have to restart the app after permission has been granted. Otherwise, checkSelfPermission will inform that acccess has been granted, but the app will not have any access to the files: Writing external storage doesn't work until I restart the application on Android M

reardenlife
  • 317
  • 4
  • 15