pythonhere 0.2.0__py3-none-any.whl → 0.2.2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- pythonhere/__init__.py +8 -1
- pythonhere/android_here.py +13 -6
- pythonhere/magic_here/prompts/README.md +49 -0
- pythonhere/magic_here/prompts/able.md +554 -0
- pythonhere/magic_here/prompts/android-media.md +130 -0
- pythonhere/magic_here/prompts/android-packages.md +69 -0
- pythonhere/magic_here/prompts/android-permissions.md +195 -0
- pythonhere/magic_here/prompts/android-runtime.md +34 -0
- pythonhere/magic_here/prompts/jnius.md +432 -0
- pythonhere/magic_here/prompts/kivy-kv.md +239 -0
- pythonhere/magic_here/prompts/kivy-runtime.md +306 -0
- pythonhere/magic_here/prompts/midi.md +243 -0
- pythonhere/magic_here/prompts/plyer.md +202 -0
- pythonhere/magic_here/prompts.py +37 -0
- pythonhere/main.py +9 -0
- pythonhere/server_here.py +1 -1
- pythonhere/version_here.py +1 -1
- {pythonhere-0.2.0.dist-info → pythonhere-0.2.2.dist-info}/METADATA +8 -4
- {pythonhere-0.2.0.dist-info → pythonhere-0.2.2.dist-info}/RECORD +22 -10
- {pythonhere-0.2.0.dist-info → pythonhere-0.2.2.dist-info}/WHEEL +0 -0
- {pythonhere-0.2.0.dist-info → pythonhere-0.2.2.dist-info}/licenses/LICENSE +0 -0
- {pythonhere-0.2.0.dist-info → pythonhere-0.2.2.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
## Android Media And Files
|
|
2
|
+
|
|
3
|
+
Use this section when the user asks to browse, display, scan, filter, or build a
|
|
4
|
+
gallery from Android photos, videos, downloads, `/sdcard`, DCIM, Pictures,
|
|
5
|
+
Movies, Music, or other shared-storage paths.
|
|
6
|
+
|
|
7
|
+
Permissions and storage access:
|
|
8
|
+
|
|
9
|
+
- Always check actual runtime permission state before assuming media or storage access exists.
|
|
10
|
+
- For Android 13+ media-library access, use granular media permissions such as
|
|
11
|
+
`android.permission.READ_MEDIA_IMAGES` and/or
|
|
12
|
+
`android.permission.READ_MEDIA_VIDEO`.
|
|
13
|
+
- For older Android versions, `READ_EXTERNAL_STORAGE` may still be relevant.
|
|
14
|
+
- Do not rely on `WRITE_EXTERNAL_STORAGE` for reading photos on modern Android.
|
|
15
|
+
- Do not call `check_permission("android.permission.MANAGE_EXTERNAL_STORAGE")`.
|
|
16
|
+
It is a special app-access setting, not a normal runtime permission.
|
|
17
|
+
- On Android 11+ broad all-files access can be checked with
|
|
18
|
+
`Environment.isExternalStorageManager()`, but a false result does not by
|
|
19
|
+
itself prove every media path is unreadable. Probe the requested path and
|
|
20
|
+
report both facts.
|
|
21
|
+
- Do not assume `MANAGE_EXTERNAL_STORAGE` is available just because it is present
|
|
22
|
+
in the manifest. The user usually must enable “All files access” in system
|
|
23
|
+
settings, and Play policy restricts this permission.
|
|
24
|
+
- Prefer privacy-friendly media access through MediaStore or the system photo
|
|
25
|
+
picker unless the user specifically asks for direct filesystem browsing.
|
|
26
|
+
- Store the error/status and show errors.
|
|
27
|
+
|
|
28
|
+
Path vs MediaStore access:
|
|
29
|
+
|
|
30
|
+
- For a concrete path such as `/sdcard/DCIM/Camera`, first probe that path
|
|
31
|
+
directly before deciding the app lacks access.
|
|
32
|
+
- For media-library/gallery access, prefer MediaStore queries.
|
|
33
|
+
- Do not depend on the MediaStore `_data` column. It can be missing, deprecated,
|
|
34
|
+
inaccessible, or point to a file path the app cannot decode directly.
|
|
35
|
+
- Prefer querying `_id`, building a `content://` URI with
|
|
36
|
+
`ContentUris.withAppendedId(...)`, and reading through
|
|
37
|
+
`context.getContentResolver().openInputStream(uri)`.
|
|
38
|
+
- Decode MediaStore images from a valid Android `Uri` or input stream, not from
|
|
39
|
+
guessed filesystem paths.
|
|
40
|
+
- If direct path access is used as a fallback, treat failure to read/decode as a
|
|
41
|
+
normal state and continue.
|
|
42
|
+
|
|
43
|
+
MediaStore querying:
|
|
44
|
+
|
|
45
|
+
- Always handle `cursor is None`.
|
|
46
|
+
- Always check `cursor.getCount()` and show an empty-state UI when it is zero.
|
|
47
|
+
- Use `moveToFirst()` safely before reading rows.
|
|
48
|
+
- Always close the cursor in `finally`.
|
|
49
|
+
- Avoid `while cursor.isAfterLast() is False`; prefer clearer logic such as:
|
|
50
|
+
`if cursor.moveToFirst(): ... while not cursor.isAfterLast(): ...`.
|
|
51
|
+
- Log counts separately:
|
|
52
|
+
- rows found
|
|
53
|
+
- thumbnails attempted
|
|
54
|
+
- thumbnails decoded
|
|
55
|
+
- thumbnails failed
|
|
56
|
+
- permission/access state
|
|
57
|
+
|
|
58
|
+
HEIC and thumbnails:
|
|
59
|
+
|
|
60
|
+
- Kivy `Image` may not load `.heic` directly on Android.
|
|
61
|
+
- Use Android image decoding APIs such as `android.graphics.BitmapFactory` or
|
|
62
|
+
`android.graphics.ImageDecoder` for HEIC thumbnails when available.
|
|
63
|
+
- Import nested Android classes with `$`. For bitmap decoding options, define
|
|
64
|
+
`BitmapFactoryOptions = autoclass("android.graphics.BitmapFactory$Options")`
|
|
65
|
+
and use `BitmapFactoryOptions()`. Do not access it as `BitmapFactory.Options()`.
|
|
66
|
+
- With `ImageDecoder` and a Java `File`, prefer:
|
|
67
|
+
`source = ImageDecoder.createSource(java_file)`.
|
|
68
|
+
- Do not call:
|
|
69
|
+
`ImageDecoder.createSource(context.getContentResolver(), java_file)`,
|
|
70
|
+
because the `ContentResolver` overload expects a `Uri`, not a `File`.
|
|
71
|
+
- If using a `ContentResolver` with `ImageDecoder`, pass a valid Android `Uri`,
|
|
72
|
+
not a filesystem path or Java `File`.
|
|
73
|
+
- Avoid `ImageDecoder.decodeBitmap(source, python_lambda)` unless a correct Java
|
|
74
|
+
listener interface is implemented. Through Pyjnius, prefer:
|
|
75
|
+
`bitmap = ImageDecoder.decodeBitmap(source)`,
|
|
76
|
+
then scale/compress the decoded bitmap.
|
|
77
|
+
- Import nested Android classes with `$`. For bitmap compression, define:
|
|
78
|
+
`CompressFormat = autoclass("android.graphics.Bitmap$CompressFormat")`
|
|
79
|
+
and use `CompressFormat.JPEG` or `CompressFormat.PNG`.
|
|
80
|
+
- Do not access compression format as `Bitmap.CompressFormat`.
|
|
81
|
+
- Do not assume Kivy `Image.source` accepts `data:image/...;base64,...` URIs.
|
|
82
|
+
Prefer writing thumbnails to small temporary files in the app cache directory
|
|
83
|
+
and setting `Image.source` to those file paths.
|
|
84
|
+
- Use `context.getCacheDir().getAbsolutePath()` for thumbnail cache files.
|
|
85
|
+
- Avoid writing into `/sdcard` unless the user asks for exported files.
|
|
86
|
+
- Keep Android bitmap dimensions as plain Python `int` pixel values.
|
|
87
|
+
- Do not pass Kivy `dp(...)` float values directly to Android bitmap APIs such
|
|
88
|
+
as `Bitmap.createScaledBitmap(...)`.
|
|
89
|
+
- Use separate constants for UI size and decode size, for example:
|
|
90
|
+
`THUMB_UI_DP = dp(120)` for widgets and `THUMB_PX = 240` for Android bitmap
|
|
91
|
+
scaling.
|
|
92
|
+
- Recycle Android `Bitmap` objects after thumbnail compression when possible.
|
|
93
|
+
|
|
94
|
+
Generated-code defaults:
|
|
95
|
+
|
|
96
|
+
- For “show my gallery/photos” code, default to:
|
|
97
|
+
MediaStore query → `_id` → content URI → openInputStream/decode → cache
|
|
98
|
+
thumbnail file → Kivy Image source = cache file path.
|
|
99
|
+
- Avoid defaulting to:
|
|
100
|
+
MediaStore `_data` → raw filesystem path → `BitmapFactory.decodeFile(...)`.
|
|
101
|
+
- Include a visible debug/status label during development.
|
|
102
|
+
- Include enough logging to distinguish:
|
|
103
|
+
permission not granted,
|
|
104
|
+
MediaStore returned no rows,
|
|
105
|
+
rows found but decode failed,
|
|
106
|
+
thumbnails decoded but widget display failed.
|
|
107
|
+
|
|
108
|
+
Android 14+ partial photo/video access:
|
|
109
|
+
|
|
110
|
+
- On Android 14+ (API 34+), photo/video access may be partial because the user
|
|
111
|
+
selected only some media. Generated gallery code must report whether access
|
|
112
|
+
appears full, partial, denied, or unknown when permission information is
|
|
113
|
+
available.
|
|
114
|
+
- If only partial access is available, continue with MediaStore and show the
|
|
115
|
+
accessible subset instead of treating the result as a failure.
|
|
116
|
+
- When the user wants to choose media rather than browse the whole library,
|
|
117
|
+
prefer a system picker/user-selection flow over broad storage/media
|
|
118
|
+
permissions.
|
|
119
|
+
- Keep the debug/status label explicit: distinguish `permission_denied`,
|
|
120
|
+
`partial_media_access`, `mediastore_empty`, `decode_failed`, and
|
|
121
|
+
`display_ready`.
|
|
122
|
+
|
|
123
|
+
Query defaults:
|
|
124
|
+
|
|
125
|
+
- For general gallery requests, query images first unless the user asked for
|
|
126
|
+
videos or audio too. Avoid scanning every media type by default.
|
|
127
|
+
- Limit initial thumbnail queries to a reasonable count such as 50-100 items,
|
|
128
|
+
store full metadata in a global, and render a small preview first.
|
|
129
|
+
- Do not assume an empty MediaStore result means there are no photos on the
|
|
130
|
+
device; report permission/access state and query filters too.
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
## Android Package Inventory
|
|
2
|
+
|
|
3
|
+
Use this addon when the user asks to list, inspect, filter, summarize, or export
|
|
4
|
+
installed Android apps, packages, APK files, package labels, versions, system-app
|
|
5
|
+
status, or requested permissions for installed packages.
|
|
6
|
+
|
|
7
|
+
PackageManager rules:
|
|
8
|
+
|
|
9
|
+
- Use `org.kivy.android.PythonActivity.mActivity`.
|
|
10
|
+
- Import `org.kivy.android.PythonService` inside the fallback block, not before
|
|
11
|
+
it is needed, because some apps do not package service support.
|
|
12
|
+
- Get a `PackageManager` from the Android context.
|
|
13
|
+
- Use `PackageManager.getInstalledPackages(...)` with `GET_PERMISSIONS`.
|
|
14
|
+
- In Pyjnius, import Android nested classes with `$`, not Python attribute
|
|
15
|
+
access. For SDK checks, define
|
|
16
|
+
`VERSION = autoclass("android.os.Build$VERSION")` and use
|
|
17
|
+
`VERSION.SDK_INT`. Do not use `Build.VERSION.SDK_INT`.
|
|
18
|
+
- On Android API 33+, call `PackageInfoFlags.of(...)`.
|
|
19
|
+
- On older Android versions, pass integer flags directly.
|
|
20
|
+
- In Pyjnius, the Android API 33 flags class must be imported as:
|
|
21
|
+
`PackageInfoFlags = autoclass("android.content.pm.PackageManager$PackageInfoFlags")`.
|
|
22
|
+
Then call `PackageInfoFlags.of(flags)`. Do not call
|
|
23
|
+
`PackageManager.PackageInfoFlags.of(...)`.
|
|
24
|
+
- Use `android.content.pm.ApplicationInfo.FLAG_SYSTEM` and
|
|
25
|
+
`FLAG_UPDATED_SYSTEM_APP` for system app detection.
|
|
26
|
+
- Do not use `android.content.pm.ActivityInfo` for installed application flags.
|
|
27
|
+
- Use `ApplicationInfo.sourceDir` and `splitSourceDirs` with `java.io.File` for
|
|
28
|
+
APK file sizes. Report `None` when a path is unavailable.
|
|
29
|
+
- Store APK size details separately, for example `base_apk_size_bytes`,
|
|
30
|
+
`split_apk_sizes_bytes`, and `total_apk_size_bytes`.
|
|
31
|
+
- Use `PackageInfo.requestedPermissions` plus
|
|
32
|
+
`PackageInfo.requestedPermissionsFlags`.
|
|
33
|
+
- A requested permission is granted when the matching flag has
|
|
34
|
+
`PackageInfo.REQUESTED_PERMISSION_GRANTED` set.
|
|
35
|
+
- Do not use `PackageManager.PERMISSION_GRANTED` or
|
|
36
|
+
`ActivityInfo.REQUESTED_PERMISSION_GRANTED` for requested permission flags.
|
|
37
|
+
- Import every Android class referenced in the code with `autoclass`.
|
|
38
|
+
If code uses `PackageInfo.REQUESTED_PERMISSION_GRANTED`, it must first define
|
|
39
|
+
`PackageInfo = autoclass("android.content.pm.PackageInfo")`.
|
|
40
|
+
- `requestedPermissions`, `requestedPermissionsFlags`, and `splitSourceDirs` are
|
|
41
|
+
Java arrays. In Pyjnius, handle them with `len(array)` and `array[index]`;
|
|
42
|
+
do not call `.size()` or `.get()` on them.
|
|
43
|
+
- Keep per-app permission records as dictionaries with at least `name` and
|
|
44
|
+
`granted`.
|
|
45
|
+
- Convert Java string-like fields such as package name, label, and version name
|
|
46
|
+
to Python strings or `None` before storing them.
|
|
47
|
+
- Keep preview output simple. If you compute `perms_granted`, print
|
|
48
|
+
`perms_granted`; do not reference a different variable name.
|
|
49
|
+
- Do not import `json`, `pathlib.Path`, or `pprint` unless the user explicitly
|
|
50
|
+
asks to export or pretty-print data.
|
|
51
|
+
- Do not import `os` unless the user explicitly asks for filesystem or
|
|
52
|
+
environment inspection.
|
|
53
|
+
- Do not import `cast`, `contextlib`, or other helpers unless the generated code
|
|
54
|
+
actually uses them.
|
|
55
|
+
|
|
56
|
+
Android 11+ package visibility:
|
|
57
|
+
|
|
58
|
+
- On Android 11+ (API 30+) package visibility filtering can make
|
|
59
|
+
`getInstalledPackages(...)` return a filtered set when the manifest does not
|
|
60
|
+
declare the needed package visibility queries or `QUERY_ALL_PACKAGES`.
|
|
61
|
+
- Do not promise a complete inventory of all installed apps on Android 11+
|
|
62
|
+
unless the app's manifest/package visibility allows it.
|
|
63
|
+
- Store and print a field such as `package_visibility_note` when results may be
|
|
64
|
+
filtered.
|
|
65
|
+
- If the user asks why some apps are missing, explain that Android package
|
|
66
|
+
visibility is manifest/policy controlled and cannot be fixed from a
|
|
67
|
+
runtime-only snippet.
|
|
68
|
+
- Do not request `QUERY_ALL_PACKAGES` at runtime; it is a manifest/policy
|
|
69
|
+
matter, not a dangerous runtime permission prompt.
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
## Android Permissions
|
|
2
|
+
|
|
3
|
+
Use this section when need to check, request, or explain permissions for
|
|
4
|
+
the running Android app.
|
|
5
|
+
|
|
6
|
+
Critical rules:
|
|
7
|
+
|
|
8
|
+
- Do not assume a runtime permission can be granted if it is missing from the
|
|
9
|
+
Android manifest. Runtime requests only work for permissions declared by the
|
|
10
|
+
app.
|
|
11
|
+
- Do not use installed-package permission metadata to decide whether this app has
|
|
12
|
+
a runtime permission. Use runtime permission APIs for the current app.
|
|
13
|
+
- Choose the Android access mechanism from the user's goal. Do not force every
|
|
14
|
+
access request through `request_permissions`.
|
|
15
|
+
- Use fully qualified Android permission strings for all permission APIs, for
|
|
16
|
+
example `"android.permission.CAMERA"`. Do not pass short names such as
|
|
17
|
+
`"CAMERA"`, `"READ_EXTERNAL_STORAGE"`, or `"WRITE_EXTERNAL_STORAGE"` to
|
|
18
|
+
`check_permission`, `request_permissions`, or `context.checkSelfPermission`.
|
|
19
|
+
- If storing display-friendly names, keep them separate from the full permission
|
|
20
|
+
strings used for Android API calls.
|
|
21
|
+
- When the user asks to "request", "enable", "grant", or "get access", generated
|
|
22
|
+
code must perform the appropriate request action immediately when possible. Do
|
|
23
|
+
not tell the user to ask again for the Settings-opening step.
|
|
24
|
+
- Do not call `raise SystemExit` or terminate the host app when context,
|
|
25
|
+
activity, or permission APIs are unavailable. Store an error result and print a
|
|
26
|
+
concise message instead.
|
|
27
|
+
|
|
28
|
+
Decision model:
|
|
29
|
+
|
|
30
|
+
- Dangerous runtime permissions: check with `check_permission(...)` or
|
|
31
|
+
`context.checkSelfPermission(...)`; request with
|
|
32
|
+
`android.permissions.request_permissions(...)` when the user asks to request.
|
|
33
|
+
Examples: camera, microphone, fine/coarse location, contacts, calendar,
|
|
34
|
+
nearby Bluetooth permissions, Android 13+ notifications.
|
|
35
|
+
- Normal permissions: do not request at runtime. Report that they are install-
|
|
36
|
+
time permissions.
|
|
37
|
+
- Signature/privileged permissions: do not request at runtime. Report that they
|
|
38
|
+
cannot be granted to ordinary apps unless the app is privileged or signed with
|
|
39
|
+
the platform key.
|
|
40
|
+
- Special app-access permissions: do not request with
|
|
41
|
+
`request_permissions(...)`. Check with the dedicated Android API when one
|
|
42
|
+
exists, and open the relevant Settings screen only when the user asks to
|
|
43
|
+
request/open/enable access.
|
|
44
|
+
- Storage and media access depends on Android API level and requested scope.
|
|
45
|
+
Do not treat "storage", "sdcard", "external storage", "photos", "media", or
|
|
46
|
+
"all files" as one generic permission.
|
|
47
|
+
|
|
48
|
+
Preferred Python-for-Android API:
|
|
49
|
+
|
|
50
|
+
- Prefer `from android.permissions import Permission, check_permission,
|
|
51
|
+
request_permissions` when the `android` package is available.
|
|
52
|
+
- Use `check_permission(permission_name)` to check one permission for the current
|
|
53
|
+
app.
|
|
54
|
+
- Use `request_permissions(permission_names, callback)` to request one or more
|
|
55
|
+
dangerous runtime permissions.
|
|
56
|
+
- Pass full permission strings to these functions. Prefer constants from
|
|
57
|
+
`android.permissions.Permission` when they are available and correct for the
|
|
58
|
+
target API; otherwise use full strings like
|
|
59
|
+
`"android.permission.ACCESS_FINE_LOCATION"`.
|
|
60
|
+
- The request callback should accept `(permissions, grants)` and store both the
|
|
61
|
+
raw arrays and a Python dictionary mapping permission name to granted boolean.
|
|
62
|
+
- Do not rely on `print(...)` inside the permission request callback as the only
|
|
63
|
+
result. The callback may run after notebook output capture has ended. Store the
|
|
64
|
+
result globally and update visible UI when appropriate.
|
|
65
|
+
- Do not convert grant values with `bool(grant)`. Android uses
|
|
66
|
+
`PackageManager.PERMISSION_GRANTED == 0` and
|
|
67
|
+
`PackageManager.PERMISSION_DENIED == -1`, so `bool(-1)` is wrong. Convert with
|
|
68
|
+
`grant == PackageManager.PERMISSION_GRANTED` when grant values are integers.
|
|
69
|
+
- Keep a global reference to the callback result, for example
|
|
70
|
+
`android_permission_request_result`, so later cells can inspect it.
|
|
71
|
+
|
|
72
|
+
Pyjnius fallback for checks:
|
|
73
|
+
|
|
74
|
+
- Get a current context from `org.kivy.android.PythonActivity.mActivity` or, only
|
|
75
|
+
as a fallback, `org.kivy.android.PythonService.mService`.
|
|
76
|
+
- Define `VERSION = autoclass("android.os.Build$VERSION")` and use
|
|
77
|
+
`VERSION.SDK_INT`. Do not use `Build.VERSION.SDK_INT`.
|
|
78
|
+
- Define `PackageManager = autoclass("android.content.pm.PackageManager")`.
|
|
79
|
+
- On API 23 and newer, call `context.checkSelfPermission(permission_name)` and
|
|
80
|
+
compare the result to `PackageManager.PERMISSION_GRANTED`.
|
|
81
|
+
- For permission request callbacks, use the same
|
|
82
|
+
`PackageManager.PERMISSION_GRANTED` constant to normalize grant results.
|
|
83
|
+
- On API levels below 23, runtime permission prompts do not exist. Treat declared
|
|
84
|
+
install-time permissions as already granted for runtime-check purposes, but
|
|
85
|
+
print that the result is pre-runtime-permission behavior.
|
|
86
|
+
|
|
87
|
+
Requesting permissions:
|
|
88
|
+
|
|
89
|
+
- For Kivy/Python-for-Android apps, use `android.permissions.request_permissions`
|
|
90
|
+
instead of calling `activity.requestPermissions(...)` directly.
|
|
91
|
+
- If the `android.permissions` module is unavailable, do not invent a Pyjnius
|
|
92
|
+
subclass or callback receiver for `activity.requestPermissions(...)`. Use
|
|
93
|
+
Pyjnius only to check current permission state, then report that requesting
|
|
94
|
+
runtime permissions requires the Python-for-Android permission helper or app
|
|
95
|
+
integration.
|
|
96
|
+
- Request only dangerous/runtime permissions. Normal permissions are granted at
|
|
97
|
+
install time and should be reported as not needing a runtime prompt.
|
|
98
|
+
- Do not request special app-access permissions as if they were normal runtime
|
|
99
|
+
permissions. Examples: `MANAGE_EXTERNAL_STORAGE`, notification listener
|
|
100
|
+
access, accessibility service access, overlay permission, battery optimization
|
|
101
|
+
exemption, usage access, and exact alarm access. If the user asked only to
|
|
102
|
+
check, report that they require a Settings screen flow. If the user asked to
|
|
103
|
+
request/enable/get access, open the correct Settings screen immediately when a
|
|
104
|
+
foreground activity is available.
|
|
105
|
+
- Android 13+ notification permission is
|
|
106
|
+
`android.permission.POST_NOTIFICATIONS`; request it only on API 33 and newer.
|
|
107
|
+
- If the activity is unavailable, do not attempt a permission request from a
|
|
108
|
+
service-only context. Print that a foreground activity is required.
|
|
109
|
+
|
|
110
|
+
Special app-access flows:
|
|
111
|
+
|
|
112
|
+
- If the user asks to request or enable a special app-access permission, open the
|
|
113
|
+
most specific Settings screen available for this app. Use `Intent`,
|
|
114
|
+
`Settings`, and `Uri.parse(f"package:{context.getPackageName()}")` where the
|
|
115
|
+
action supports an app-specific URI.
|
|
116
|
+
- Build Settings intents conservatively: create `intent = Intent(action)` and
|
|
117
|
+
then call `intent.setData(Uri.parse(f"package:{package_name}"))` for
|
|
118
|
+
app-specific Settings actions. This is more reliable through Pyjnius than
|
|
119
|
+
relying on overloaded Java constructors.
|
|
120
|
+
- Always store whether the Settings screen was opened, the action used, and the
|
|
121
|
+
current access state before opening Settings.
|
|
122
|
+
- Do not claim Settings access was granted immediately after opening Settings.
|
|
123
|
+
The user must return from Settings; tell them to rerun the check afterward.
|
|
124
|
+
- If `activity` is unavailable, do not call `startActivity`. Report that a
|
|
125
|
+
foreground activity is required to open Settings.
|
|
126
|
+
|
|
127
|
+
Storage and media access:
|
|
128
|
+
|
|
129
|
+
- For Android 13+ (API 33+), media permissions are split:
|
|
130
|
+
`READ_MEDIA_IMAGES`, `READ_MEDIA_VIDEO`, and `READ_MEDIA_AUDIO`. Use these
|
|
131
|
+
only for media-library access, not for arbitrary `/sdcard` file access.
|
|
132
|
+
- For Android 10-12 (API 29-32), `READ_EXTERNAL_STORAGE` may allow media/shared
|
|
133
|
+
storage reads, but scoped storage still limits arbitrary file access. Do not
|
|
134
|
+
promise full `/sdcard` traversal from this permission.
|
|
135
|
+
- `WRITE_EXTERNAL_STORAGE` is ignored or heavily limited on modern Android. Do
|
|
136
|
+
not rely on it for Android 10+ shared-storage writes.
|
|
137
|
+
- When generating runtime storage permission requests, request
|
|
138
|
+
`android.permission.WRITE_EXTERNAL_STORAGE` only for API 28 and lower. For API
|
|
139
|
+
29, do not request `WRITE_EXTERNAL_STORAGE` as a solution for broad storage
|
|
140
|
+
writes; explain the scoped-storage limitation instead.
|
|
141
|
+
- For Android 11+ (API 30+), broad "all files" access is the special access
|
|
142
|
+
`MANAGE_EXTERNAL_STORAGE`. Check it with
|
|
143
|
+
`Environment.isExternalStorageManager()`.
|
|
144
|
+
- To request Android 11+ all-files access, open Settings; do not call
|
|
145
|
+
`request_permissions(["android.permission.MANAGE_EXTERNAL_STORAGE"], ...)`.
|
|
146
|
+
Prefer `Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION` with
|
|
147
|
+
`Uri.parse(f"package:{context.getPackageName()}")`, and fall back to
|
|
148
|
+
`Settings.ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION` if the app-specific
|
|
149
|
+
action fails.
|
|
150
|
+
- For a broad `/sdcard` access request on Android 11+, do not additionally
|
|
151
|
+
request `READ_EXTERNAL_STORAGE` or `WRITE_EXTERNAL_STORAGE` as the primary
|
|
152
|
+
solution. Those permissions do not grant broad all-files access.
|
|
153
|
+
- For Android versions below 11, use runtime storage permissions only when they
|
|
154
|
+
match the user's requested scope, and explain that behavior differs by API
|
|
155
|
+
level and manifest settings.
|
|
156
|
+
- For creating or picking user-selected files, prefer Android's document/media
|
|
157
|
+
picker or Storage Access Framework when the user does not need broad all-files
|
|
158
|
+
access.
|
|
159
|
+
|
|
160
|
+
Output shape:
|
|
161
|
+
|
|
162
|
+
- For permission checks, use a global such as `android_permission_status`.
|
|
163
|
+
- For permission requests, use a global such as
|
|
164
|
+
`android_permission_request_result`.
|
|
165
|
+
- Print each permission with a short status such as `granted`, `denied`,
|
|
166
|
+
`not_requested_pre_23`, `normal_permission_no_runtime_prompt`, or
|
|
167
|
+
`requires_settings_flow`.
|
|
168
|
+
- For special Settings flows, include fields such as `access_name`,
|
|
169
|
+
`currently_granted`, `settings_opened`, `settings_action`, and
|
|
170
|
+
`rerun_check_after_return`.
|
|
171
|
+
|
|
172
|
+
Android 14+ selected media access:
|
|
173
|
+
|
|
174
|
+
- On Android 14+ (API 34+), users may grant partial access to selected
|
|
175
|
+
photos/videos. Treat this as a valid limited-access state, not a simple
|
|
176
|
+
denial.
|
|
177
|
+
- For media-gallery code on Android 14+, consider
|
|
178
|
+
`android.permission.READ_MEDIA_VISUAL_USER_SELECTED` alongside
|
|
179
|
+
`READ_MEDIA_IMAGES` and/or `READ_MEDIA_VIDEO` when the user wants to manage or
|
|
180
|
+
reselect partial media access.
|
|
181
|
+
- If the user only wants to pick one or a few files/photos, prefer a
|
|
182
|
+
picker/user-selection flow instead of broad media permissions.
|
|
183
|
+
- If partial media access is detected, explain through code comments or status
|
|
184
|
+
text that MediaStore results may include only the selected items.
|
|
185
|
+
|
|
186
|
+
Notification and special-access reminders:
|
|
187
|
+
|
|
188
|
+
- `android.permission.POST_NOTIFICATIONS` is a dangerous runtime permission only
|
|
189
|
+
on API 33+; below API 33, do not request it at runtime.
|
|
190
|
+
- Exact alarm, overlay, accessibility, notification listener, usage access,
|
|
191
|
+
battery optimization exemption, and all-files access are special settings
|
|
192
|
+
flows, not normal runtime permissions.
|
|
193
|
+
- For Settings flows, open the specific settings screen only when the user asked
|
|
194
|
+
to request, enable, or open access; otherwise only report the current state and
|
|
195
|
+
the needed flow.
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
## Android Runtime
|
|
2
|
+
|
|
3
|
+
The generated code runs inside the Android app's existing Python process.
|
|
4
|
+
Assume Python-for-Android/Kivy unless the user says otherwise.
|
|
5
|
+
|
|
6
|
+
Critical rules:
|
|
7
|
+
|
|
8
|
+
- Do not use `adb`.
|
|
9
|
+
- Do not use `subprocess`, shell commands, or host-side Android tools.
|
|
10
|
+
- Do not use legacy SL4A-style Android helper APIs. PythonHere is a
|
|
11
|
+
Kivy/Python-for-Android app, not an SL4A runtime.
|
|
12
|
+
- Do not write files unless the user explicitly asks for a file export.
|
|
13
|
+
- Prefer Android framework APIs through `jnius` over parsing command output.
|
|
14
|
+
- Use the already-running activity or service instead of starting one.
|
|
15
|
+
- If the code needs Android context, prefer
|
|
16
|
+
`org.kivy.android.PythonActivity.mActivity`.
|
|
17
|
+
- Import `org.kivy.android.PythonService` only inside a fallback block, because
|
|
18
|
+
some apps do not package service support.
|
|
19
|
+
- Import every Android class referenced in the code with `autoclass`.
|
|
20
|
+
- Import Android nested classes with `$`, not Python attribute access.
|
|
21
|
+
- For SDK checks, define `VERSION = autoclass("android.os.Build$VERSION")` and
|
|
22
|
+
use `VERSION.SDK_INT`. Do not use `Build.VERSION.SDK_INT`.
|
|
23
|
+
- Convert Java string-like fields to Python strings or `None` before storing
|
|
24
|
+
them.
|
|
25
|
+
- Java arrays are Python-indexable in Pyjnius. Use `len(array)` and
|
|
26
|
+
`array[index]`; do not call `.size()` or `.get()` unless the object is a Java
|
|
27
|
+
`List`.
|
|
28
|
+
- Do not import `json`, `pathlib.Path`, `pprint`, `os`, `cast`, `contextlib`, or
|
|
29
|
+
other helpers unless the generated code actually uses them.
|
|
30
|
+
|
|
31
|
+
HTTPS requests:
|
|
32
|
+
- Always use certifi, `context = ssl.create_default_context(cafile=certifi.where())`
|
|
33
|
+
- Never use urlopen() directly for https:// URLs.
|
|
34
|
+
- Never disable SSL verification.
|