Sure thing. I'm still a bit new to all of this still and had to sort of 'brute force' test things to get it working but hopefully it'll work for you as well. So just for reference, all of the java code I more or less just copy/pasted from here
https://developer.android.com/training/permissions/requesting#java , with some minor edits to get it working how I needed it to.
Also, these steps assume you have been successful in getting your apk built for API 26.
So first off, you'll be primarily editing the PythonActivity.java file, which can be found wherever your p4a source directory is located. There will be a few of the files, but I believe the one you want is the one located in ...bootstraps/sdl2/build/src/main/java/org/kivy/android/. Prior to building the apk, after you make the edits to PythonActivity.java you'll need to clear out your dists directory (can be found in the .buildozer directory where you have your app being built from: .buildozer/android/platform/build/dists/your_app) that contains the current build of your apk. This directory contains other PythonActivity.java files (which are created from the one in the p4a directory mentioned earlier) and buildozer will not replace them if it finds the files already there (so the edits made to the template PythonActivity.java would not be inserted). This is why the current build of your app in the dists directory needs to be removed.
Alternatively, if you're worried that clearing the dists directory would break something else like I was :) you can just edit the PythonActivity.java files found in the .buildozer directory where your app files are. This just means you'll need to make the same edits to multiple PythonActivity.java files. These files should be located at:
.buildozer/android/platform/build/dists/your_app/build/src/main/java/org/kivy/android
.buildozer/android/platform/build/build/bootstrap_builds/sdl2_gradle-python2/src/main/java/org/kivy/android
.buildozer/android/platform/build/dists/your_app/src/main/java/org/kivy/android
or similar paths, depending on how you've built your app. I'm not sure if it was entirely necessary of me to make the edits all of the ones that I did, but like I said, I just tried things out until it finally worked and that was good enough for me :)
Now, on to the edits. So with your PythonActivity.java file open, starting from the top you'll need to add a few imports:
import android.Manifest;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
Just tack those on to the bottom of the imports. Just below the imports you should see...
public class PythonActivity extends SDLActivity {
private static final String TAG = "PythonActivity";
Just under that you'll want to add:
private static final int MY_PERMISSIONS_REQUEST_WRITE_EXTERNAL_STORAGE = 0;
From my understanding, this is a constant that one of the permission requesting functions refers to. You can change the name of it to whatever makes sense for the permission you're requesting, just make sure it matches to what is edited later obviously.
Last step with the PythonActivity.java file is then is to scroll down to the onCreate() method, which will look like this:
@Override
protected void onCreate(Bundle savedInstanceState) {
Log.v(TAG, "My oncreate running");
resourceManager = new ResourceManager(this);
Log.v(TAG, "About to do super onCreate");
super.onCreate(savedInstanceState);
Log.v(TAG, "Did super onCreate");
this.mActivity = this;
this.showLoadingScreen();
new UnpackFilesTask().execute(getAppRoot());
and within this method is where you'll add the code that pops up the permission request when your app launches. Again, I pretty much just copy pasted from the android link at the beginning of this so obviously, change it to what you need, but here's the code that needs to be added to the onCreate method:
// Here, thisActivity is the current activity
if (ContextCompat.checkSelfPermission(mActivity,
Manifest.permission.WRITE_EXTERNAL_STORAGE)
!= PackageManager.PERMISSION_GRANTED) {
Log.v(TAG, "CHECKED PERMISSION");
// Permission is not granted
// Should we show an explanation?
if (ActivityCompat.shouldShowRequestPermissionRationale(mActivity,
Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
Log.v(TAG, "SHOW EXPLANATION");
// 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.
} else {
// No explanation needed; request the permission
ActivityCompat.requestPermissions(mActivity,
new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
MY_PERMISSIONS_REQUEST_WRITE_EXTERNAL_STORAGE);
Log.v(TAG, "REQUESTED PERMISSION");
// MY_PERMISSIONS_REQUEST_READ_CONTACTS is an
// app-defined int constant. The callback method gets the
// result of the request.
}
} else {
Log.v(TAG, "PERMISSION ALREADY GRANTED");
// Permission has already been granted
}
}
@Override
public void onRequestPermissionsResult(int requestCode,
String permissions[], int[] grantResults) {
switch (requestCode) {
case MY_PERMISSIONS_REQUEST_WRITE_EXTERNAL_STORAGE: {
// If request is cancelled, the result arrays are empty.
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// permission was granted, yay! Do the
// contacts-related task you need to do.
Log.v(TAG, "PERMISSION GRANTED!");
} else {
Log.v(TAG, "PERMISSION DENIED");
// permission denied, boo! Disable the
// functionality that depends on this permission.
}
return;
}
// other 'case' lines to check for other
// permissions this app might request.
}
}
A couple final things to do:
In your buildozer.spec add 'com.android.support:appcompat-v7:26.1.0' to your android.gradle_dependencies.
And finally, open up your_p4a_source_directory/bootstraps/sdl2/build/templates/build.tmpl.gradle and edit the top 22 lines to look like this:
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:2.3.1'
}
}
allprojects {
repositories {
jcenter()
mavenCentral()
maven {
url "https://maven.google.com"
}
flatDir {
dirs 'libs'
}
}
}
Make sure the file(s) are saved and try building your apk again. If I haven't forgotten any steps then hopefully it will work! If you run into any errors feel free to show me and I'll see if I can help. Also, the procedure for this is essentially the same as what's found here
http://quadropoly.com.au/kivy-and-admob-for-android-api-27/ just adapted for the runtime permissions code. On that page, mind_writer helped me a bunch to get things working for me and you might run into some of the same errors that are mentioned in his tutorial there, or in the comments below if you read through them.
Hopefully these instructions are clear enough and will help, or at least get you pointed in the right direction, but again if you run into any issues feel free to post them and I'll see if I can help.