I found that kivy is very nice framework to build cross platform application and I am very interested in kivy just to do android application as I think is easy and comfortable in kivy.
After trying few examples, I am interested to know how should handle android run time permission for the kivy app.
Actually I had searched on google, but no single working example out there. Should I go back to android / java or it possible with kivy and some other python libs.
pyjnius is the way to go. You have to port these instructions using pyjnius. This involves the following steps:
Unfortunately the api call to ContextCompat.checkSelfPermission is implemented in the android sdk support library which has to be downloaded seperately,
so get the .aar with the version best matching your android API level for example here.
copy it into your project dir and reference it from your buildozer.spec:
android.add_aars = support-v4-26.0.0-alpha1.aar
make sure jinius is in the requirements in buildozer.spec
use the following code snippet
Note: this is a blocking function which waits until the permissions dialog is answered. If the app already has the permission the function returns immediately. So for example if you want to get the permissions for writing to the SD card and for the camera, which are both "dangerous permissions", call:
perms = ["android.permission.READ_EXTERNAL_STORAGE",
"android.permission.WRITE_EXTERNAL_STORAGE",
"android.permission.CAMERA"]
haveperms = acquire_permissions(perms)
And here the function for acquiring the permissions:
import time
import functools
import jnius
def acquire_permissions(permissions, timeout=30):
"""
blocking function for acquiring storage permission
:param permissions: list of permission strings , e.g. ["android.permission.READ_EXTERNAL_STORAGE",]
:param timeout: timeout in seconds
:return: True if all permissions are granted
"""
PythonActivity = jnius.autoclass('org.kivy.android.PythonActivity')
Compat = jnius.autoclass('android.support.v4.content.ContextCompat')
currentActivity = jnius.cast('android.app.Activity', PythonActivity.mActivity)
checkperm = functools.partial(Compat.checkSelfPermission, currentActivity)
def allgranted(permissions):
"""
helper function checks permissions
:param permissions: list of permission strings
:return: True if all permissions are granted otherwise False
"""
return reduce(lambda a, b: a and b,
[True if p == 0 else False for p in map(checkperm, permissions)]
)
haveperms = allgranted(permissions)
if haveperms:
# we have the permission and are ready
return True
# invoke the permissions dialog
currentActivity.requestPermissions(permissions, 0)
# now poll for the permission (UGLY but we cant use android Activity's onRequestPermissionsResult)
t0 = time.time()
while time.time() - t0 < timeout and not haveperms:
# in the poll loop we could add a short sleep for performance issues?
haveperms = allgranted(permissions)
return haveperms
Probably the cleanest way would be to pimp p4a's PythonActivity.java to do that but this one does it for me for now.
Hi this question is old but you can use
request_permissions([Permission.WRITE_EXTERNAL_STORAGE])
#For requesting permission you can pass a list with all the permissions you need
check_permission('android.permission.WRITE_EXTERNAL_STORAGE')
#returns True if you have the permission
you can check: python-for-android example
you can check the code and the list of permission you can use with this method:
python-for-android code
python-for-android doesn't have any code for handling runtime permissions. I expect to look at it sooner rather than later, but there's no ETA for it.
You can probably add the code for it yourself if you're interested and know how. If you'd like to try it, such contributions would be very welcome.
i know this answer is a little late, but to get permissions you have to specify them before the build. E.g buildozer uses a buildozer.spec. In this file you can specify the permissions you need.
Related
I am using ionic 3.15 and trying to use the permissions plugin.
Using the code in the docs as mentioned here.
I have the code as shown in the docs but will mention it again here.
this.androidPermissions.checkPermission(this.androidPermissions.PERMISSION.CAMERA).then(
success => console.log('Permission granted'),
err => this.androidPermissions.requestPermission(this.androidPermissions.PERMISSION.CAMERA)
);
I always get hasPermission: false.
I do not get any prompt for turning the permissions on.
What is to be done here I am clueless.
Thanks.
You need to add something along the lines of:
this.androidPermissions.requestPermissions(
[
this.androidPermissions.PERMISSION.READ_EXTERNAL_STORAGE,
this.androidPermissions.PERMISSION.WRITE_EXTERNAL_STORAGE
]
);
You check to see if you have permissions, if it is false, then execute the above code to prompt the user to allow.
It seems like you have to make sure that you are using the permission you requested. Otherwise no prompt will be shown and the androidPermissions.requestPermissions will immediately return false.
From the docs:
Android 26 and above: due to Android 26's changes to permissions handling (permissions are requested at time of use rather than at runtime,) if your app does not include any functions (eg. other Ionic Native plugins) that utilize a particular permission, then requestPermission() and requestPermissions() will resolve immediately with no prompt shown to the user. Thus, you must include a function utilizing the feature you would like to use before requesting permission for it.
In my android App, there is an Activity which shows time string according to the System Time Format (12Hr. / 24Hr.).
I am writing espresso test to test this behavior whether the time displays gets changed as the System time format changes.
In order to achieve this, i want to change my System time format through my Instrumentation test for pure testing purpose. and i've added permission in test project's manifest, like this
<uses-permission android:name="android.permission.WRITE_SETTINGS"/>
and wrote the following code to change system time format
Context context = InstrumentationRegistry.getContext();
Settings.System.putString(context.getContentResolver(),Settings.System.TIME_12_24, "12");
and it is throwing Permission Denial error. (you can use below link to see the stack trace)
Error StackTrace Screenshot
i am not able to understand, since the code which is trying to change the system time format in the test project itself and it has permission to change the system time setting,
I verified Using this command
adb shell dumpsys package com.my.app.package | grep permission
Please tell me, what i am missing here ?
I've already found an explanation to your issue. Here is it:
The user application does not have permission to change the device
time. Please read the answer by cashbash in the following post
for the alternate option.
Copying here for quick reference:
According to this thread, user apps cannot set the time,
regardless of the permissions we give it. Instead, the best approach
is to make the user set the time manually. We will use:
startActivity(new Intent(android.provider.Settings.ACTION_DATE_SETTINGS));
Unfortunately, there is no way to link them directly to the time
setting (which would save them one more click). By making use of
ellapsedRealtime, we can ensure that the user sets the time correctly.
From: Set Android's date/time programmatically
Try also instead of using Espresso, use uiatomator as that instrumentation test framework can perform actions with Dialogs, Marshmallow permissions or lockscreen.
It works perfectly with Espresso.
Check this site: http://qathread.blogspot.com/2015/05/espresso-uiautomator-perfect-tandem.html
Hope it help
I had earlier written a standalone daemon to access a custom device (/dev/mydev0). Looking at AOSP source, I figured I needed setup policies in following files to make it work:
new file device.te containing:
type mydev_device, dev_type;
new file mydevsrvc.te containing
# service flash_recovery in init.rc
type mydevsrvc_type, domain;
type mydevsrvc_type_exec, exec_type, file_type;
init_daemon_domain(mydevsrvc_type)
allow mydevsrvc_type mydev_device:chr_file rw_file_perms;
edited file_contexts to add:
/dev/mydev[0-9]* u:object_r:mydev_device:s0
edited service_contexts to add:
mydevsrvc u:object_r:mydevsrvc_type:s0
And started the daemon by editing init.flo.rc to include these lines:
service mydevsrvc /system/bin/mydevsrvc
class main
user system
group system
seclabel u:r:mydevsrvc_type:s0
oneshot
Now, I need to access the device in android apps, so I must change the daemon into an android system service.
I can startup the service (thread) using BOOT_COMPLETED intent as explained in a previous question
I am not able to figure out how to setup SELinux policies so that this java service is also able to access the dev file.
[Update] I have continued using privileged daemon for this purpose. My java service connects to daemon through sockets. I don't have a better solution.
I finally figured out the answer. Posting it here, because there sure will be SEPolicy noobs like me looking for similar answers.
For this work, I needed to be able to access my device file from my java app that implements my service.
I needed to add following rule in my sepolicy directory, in a new file:
allow system_app mydev_device:chr_file rw_file_perms;
Also, needed to make my service app run in system_app domain. For this, I need to:
Install in priv_app during Android build.
Sign it with platform key
Declare shared user id in manifest: android.uid.system. I found that without this, app runs in platform-app domain and wasn't able to access my device file even with corresponding change in SEPolicy rule. Not sure why though, I didn't bother to debug.
It might also be possible to run my Service app in mydevsrvc_type domain. I didn't find out how to do that, or whether that will work.
Here is a brief summary of the steps needed to implement SELinux on your Android device:
Add SELinux support in the kernel and configuration.
Grant each service (process or daemon) started from init its own domain.
Identify these services by:
Reviewing the init..rc file and finding all services.
Examining warnings of the form init: Warning! Service name needs a SELinux domain defined; please fix! in dmesg output.
Checking ps -Z | grep init output to see which services are running in the init domain.
Label all new processes, drivers, sockets, etc. All objects need to be labeled properly to ensure they interact properly with the policies you apply. See the labels used in AOSP for examples to follow in label name creation.
Institute security policies that fully cover all labels and restrict permissions to their absolute minimum.
Ideally, OEMs start with the policies in the AOSP and then build upon them for their own customizations.
for more https://source.android.com/security/selinux/implement.html
In response of your question to start service from init rc
you can just write one rc file like below. Where it will start your service on receiving of boot_completed
on property:sys.boot_completed=1
start mydevsrvc
for reference http://androidxref.com/9.0.0_r3/xref/device/generic/qemu/init.ranchu.rc#60
Possibly add a line in your ueventd.rc file or project specific to give the permission
I want to modify my viber database on my app.
i use this code:
File f = new File("/data/data/com.viber.voip/databases/viber_messages");
boolean b1 = f.setExecutable(true, false);
boolean b2 = f.setWritable(true, false);
but b1,b2 are false.How can it be done?
i use "android.permission.WRITE_EXTERNAL_STORAGE" permission
You can't modify other apps. Your app is sandboxed, that prevents it from modifying other apps. To quote the docs here:
true if and only if the operation succeeded. If the user does not have permission to change the access permissions of this abstract pathname the operation will fail. If the underlying file system does not support execute permission and the value of executable is false, this operation will fail.
The permission "WRITE_TO_EXTERNAL_STORAGE" allows you to write to e.g. the SD card or other spaces that are "user- visible".
To modify other apps it's required that your phone is rooted and you must use something like a shell. Take a look a libsuperuser here. It gives you the option to create a superuser shell (su permissions). You could copy the db into the directory of your app to modify it (remember to set the required permissions).
Let's say I have taken over development of an Android app, and my boss asks me why our app requires certain permissions to be displayed to users who buy the app on the Android Market.
Are there any tools or tricks I can use to determine what code triggers each permission, so I can figure out why our app functionally needs those permissions? In particular, I am interested in these permissions:
Phone Calls - Read phone status and identity
System Tools - Retrieve running applications - Allows app to retrieve information about currently and recently running tasks, May allow malicious apps to discover private information about other apps.
The app is a GPS tracking app, and it's not obvious why this permission might be needed.
It would also be helpful to get any tips on why this permission might be needed, even if you can't tell me how to directly analyze the code to find out.
Here is how I would track these down.
Step 1 - Find the manifest permissions declared in your AndroidManifest.xml
Basically everything inside the <uses-permission /> tags e.g.:
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
Step 2 - Search developer.android.com for classes that use these permissions
Let's take the case of READ_PHONE_STATE, the goal is to find which packages require this permission. A simple search on the dev portal for "READ_PHONE_STATE" starts our search, we are looking for classes here, in the top 5 search results I see the following classes:
TelephonyManager
PhoneStateListener
Click on the classes and get their package names:
android.telephony.TelephonyManager
android.telephony.PhoneStateListener
Step 3 Find classes in your project that import these packages
A simple grep will do, or a Ctrl-H in eclipse, File Search -> Containing text
Step 4 Comment out the import and see what breaks
These are likely candidates for why the permission is required. Confirm the methods in question by looking at the dev portal to validate that the permission is indeed required by that method.
Finally you should be able to tell your boss, READ_PHONE_STATE is required because we call function XYZ which gives us UVW.
Remove a permission and see where the app fails. The answer will be in the logcat output.
That's not an ideal solution though, since you might not know what you need to do in the app to trigger that permission.
I suspect "Read phone status and identity" means that the app is using the device IMEI or similar identifying information to uniquely identify the device to ensure that the app is only being run on a registered device. Or it might just be used as a sort of cookie to track the owner. Look for that code. And remove it, because that's the wrong way to do it. If you need to identify a specific android device, use ANDROID_ID from the Settings.Secure class. http://developer.android.com/reference/android/provider/Settings.Secure.html
As for "Retrieve running applications", I find that one somewhat suspicious. A very common way to implement GPS tracking is to launch a separate service in its own process. This way, if the app should crash, the service will keep going and can be re-attached. In this case, it's possible that the app is using the "Retrieve running applications" to identify and kill the service process. But if so, it's a clumsy way to do it.
With the latest build tools, you can run lint check which will highlight for you all the android SDK method calls which are requiring permissions.
See announcement here http://android-developers.blogspot.com/2015/07/get-your-hands-on-android-studio-13.html and documentation here https://developer.android.com/tools/debugging/annotations.html#permissions .
This is based on android annotations and after some adoption time 3rd party libraries can integrate permission annotations also
The answer for your boss is "because certain API features/calls/methods we use in our app require calee to hold certain permissions. It is for security reasons, and that's the way Android works". As for mentioned permissions - you have to check the code to see if these permissions are really required. Read phone status and identity may indicate your app try to get IMEI or something like this to uniquely identify device. Retrieve running applications - see no reason for GPS tracking app to hold this. But maybe you use 3rd party lib/code that uses this.