Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 33 additions & 2 deletions android_notify/an_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from .config import (
get_python_activity_context, app_storage_path,ON_ANDROID,
BitmapFactory, BuildVersion, Bundle,
NotificationManagerClass,AndroidNotification
NotificationManagerClass,AndroidNotification,Intent, Settings, Uri, String, Manifest
)

if ON_ANDROID:
Expand Down Expand Up @@ -143,7 +143,6 @@ def get_package_path():
return os.path.dirname(os.path.abspath(__file__))

def get_bitmap_from_path(img_full_path):
Uri = autoclass('android.net.Uri')
uri = Uri.parse(f"file://{img_full_path}")
return BitmapFactory.decodeStream(context.getContentResolver().openInputStream(uri))

Expand All @@ -156,3 +155,35 @@ def icon_finder(icon_name):
# Fallback if pkg_resources not available
package_dir = get_package_path()
return os.path.join(package_dir, "fallback-icons", icon_name)

def can_show_permission_request_popup():
"""
Check if we can show permission request popup for POST_NOTIFICATIONS
:return: bool
"""
if not ON_ANDROID or BuildVersion.SDK_INT < 33:
return False

return context.shouldShowRequestPermissionRationale(Manifest.POST_NOTIFICATIONS)

def open_settings_screen():
intent = Intent()
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
package_name = String(context.getPackageName()) # String() is very important else fails silently with a toast
# saying "The app wasn't found in the list of installed apps" - Xiaomi or "unable to find application to perform this action" - Samsung and Techno

if BuildVersion.SDK_INT >= 26: # Android 8.0 - android.os.Build.VERSION_CODES.O
intent.setAction(Settings.ACTION_APP_NOTIFICATION_SETTINGS)
intent.putExtra(Settings.EXTRA_APP_PACKAGE, package_name)
elif BuildVersion.SDK_INT >= 22: # Android 5.0 - Build.VERSION_CODES.LOLLIPOP
intent.setAction("android.settings.APP_NOTIFICATION_SETTINGS")
intent.putExtra("app_package", package_name)
intent.putExtra("app_uid", context.getApplicationInfo().uid)
else: # Last Retort is to open App Settings Screen
intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS)
intent.addCategory(Intent.CATEGORY_DEFAULT)
intent.setData(Uri.parse("package:" + package_name))

context.startActivity(intent)

# https://stackoverflow.com/a/45192258/19961621
3 changes: 3 additions & 0 deletions android_notify/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,9 @@ def get_activity_class_name():
NotificationChannel = autoclass('android.app.NotificationChannel')
RemoteViews = autoclass('android.widget.RemoteViews')
AndroidNotification = autoclass("android.app.Notification")
Settings = autoclass("android.provider.Settings")
Uri = autoclass("android.net.Uri")
Manifest = autoclass('android.Manifest$permission')

ON_ANDROID = bool(RemoteViews)
except Exception as e:
Expand Down
27 changes: 18 additions & 9 deletions android_notify/core.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
""" Non-Advanced Stuff """
import random
import os, traceback
from .config import get_python_activity
from .config import get_python_activity, Manifest
ON_ANDROID = False

def on_flet_app():
Expand Down Expand Up @@ -37,6 +37,8 @@ def on_flet_app():
traceback.print_exc()
print("Error importing notification styles")

from .an_utils import can_show_permission_request_popup, open_settings_screen


def get_app_root_path():
path = ''
Expand All @@ -55,18 +57,25 @@ def asks_permission_if_needed(no_androidx=False):
"""
Ask for permission to send notifications if needed.
"""
if BuildVersion.SDK_INT < 33 or not ON_ANDROID:
return True

if not can_show_permission_request_popup():
print("""android_notify- Permission to send notifications has been denied permanently. Please enable it from settings.
This happens when the user denies permission twice from the popup.""")
open_settings_screen()
return


if on_flet_app() or no_androidx:
Activity = autoclass("android.app.Activity")
Manifest = autoclass("android.Manifest$permission")
PackageManager = autoclass("android.content.pm.PackageManager")
VERSION_CODES = autoclass('android.os.Build$VERSION_CODES')

if BuildVersion.SDK_INT >= 33:
permission = Manifest.POST_NOTIFICATIONS
granted = context.checkSelfPermission(permission)

permission = Manifest.POST_NOTIFICATIONS
granted = context.checkSelfPermission(permission)

if granted != PackageManager.PERMISSION_GRANTED:
context.requestPermissions([permission], 101)
if granted != PackageManager.PERMISSION_GRANTED:
context.requestPermissions([permission], 101)
else: # android package is from p4a which is for kivy
try:
from android.permissions import request_permissions, Permission,check_permission # type: ignore
Expand Down
29 changes: 23 additions & 6 deletions android_notify/sword.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
from .an_types import Importance
from .an_utils import can_accept_arguments, get_python_activity_context, \
get_android_importance, generate_channel_id, get_img_from_path, setLayoutText, \
get_bitmap_from_url, add_data_to_intent, get_sound_uri, icon_finder, get_bitmap_from_path
get_bitmap_from_url, add_data_to_intent, get_sound_uri, icon_finder, get_bitmap_from_path, can_show_permission_request_popup, open_settings_screen


from .config import from_service_file, get_python_activity,get_notification_manager,ON_ANDROID,on_flet_app
from .config import (Bundle, String, BuildVersion,
Expand All @@ -18,7 +19,7 @@
from .config import (AndroidNotification, NotificationCompatBuilder,
NotificationCompatBigTextStyle,NotificationCompatBigPictureStyle,
NotificationCompatInboxStyle,
Color
Color, Manifest
)
from .styles import NotificationStyles
from .base import BaseNotification
Expand Down Expand Up @@ -1081,13 +1082,29 @@ def asks_permission(cls,callback=None):
Ask for permission to send notifications if needed.
Passes True to callback if access granted
"""
if cls.__requesting_permission or not ON_ANDROID:
if cls.__requesting_permission:
return True

if BuildVersion.SDK_INT < 33: # Android 12 below
print("android_notify- On android 12 or less don't need permission")
if callback:
callback(True)

if not ON_ANDROID or BuildVersion.SDK_INT < 33: # Android 12 below:
try:
if callback:
if can_accept_arguments(callback, True):
callback(True)
else:
callback()
except Exception as request_permission_error:
print('Exception: ',request_permission_error)
print('Permission response callback error: ',traceback.format_exc())

return

if not can_show_permission_request_popup():
print("""android_notify- Permission to send notifications has been denied permanently. Please enable it from settings.
This happens when the user denies permission twice from the popup.""")
open_settings_screen()
return

def on_permissions_result(permissions, grants):
Expand Down