Delphi 监听安卓(Android)手机通知栏信息

Delphi 监听安卓(Android)手机通知栏信息

因为一些业务需要,我们有时候需要知道手机通知栏显示的信息,然后根据这些信息去处理一些相应的业务逻辑。如:自动监听收到的短信验证码,提取后自动填写到我们APP的验证码输入项中,减少使用者查看短信再记忆、再输入验证的过程,提升用户使用体验。除了短信,其他通知栏显示的信息我们可能也会有着其他较为实用的需要。

在使用这项功能前,我们需要了解一些基本知识。

安全问题

因为监听通知栏信息涉及到较为隐私的信息,出于安全考虑,Android并没有提供自动权限设置的功能,也就是只能通过机主以手工去确认是否允许该APP监听通知栏信息。通常多数手机也不能通过“设置”或其他菜单连接的方式找到并打开,他需要在APP中以代码方式打开并设置。
通知栏监听的权限设置
通常设置类似上图,手机不同会有细微差别。

主要开发过程

本文简单记录开发过程。
首先需要实现并注册NotificationListenerService服务。用于监听通知栏信息,其次需要实现对权限的判断与管理,最后是完成服务监听到信息的处理。

NotificationListenerService服务

我在实现过程中尝试过使用delphi来处理,目前暂时没有成功,只好使用JAVA完成服务功能的部分代码,然后通过服务将监听到的数据发送给delphi程序做后续处理。
需要用JAVA实现onNotificationPosted及onNotificationRemoved方法。并通过工具生成JNI单元文件,以便在delphi中可以使用。主要包括:

  [JavaSignature('com/tanqin/nlsapp/NLService')]
  JNLService = interface(JNotificationListenerService)
  //or JObject // SuperSignature: android/service/notification/NotificationListenerService
    ['{F7F3FEFD-FA30-4A7A-97D5-70643997C7F3}']

    procedure onNotificationPosted(sbn: JStatusBarNotification); cdecl;
    //(Landroid/service/notification/StatusBarNotification;)V
    procedure onNotificationRemoved(sbn: JStatusBarNotification); cdecl;
    //(Landroid/service/notification/StatusBarNotification;)V

  end;

  TJNLService = class(TJavaGenericImport<JNLServiceClass,JNLService>)
  end;

  JLocalBroadcastManagerClass = interface(JObjectClass)
    ['{3013CC6D-4E7D-44D9-9F61-E849944E1091}']

    {class} function getInstance(P1: JContext): JLocalBroadcastManager; cdecl;
    //(Landroid/content/Context;)Landroid/support/v4/content/LocalBroadcastManager;

  end;

服务注册

需要在“AndroidManifest.template.xml”文件中增加如下定义,其中android:name=”com.tanqin.nlsapp.NLService”行,指定了监听服务类名称,label用于显示监听服务名字,以便于识别。

        <service android:name="com.tanqin.nlsapp.NLService" 
            android:label="通知监听"
            android:permission="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE">
            <intent-filter>
                <action android:name="android.service.notification.NotificationListenerService" />
            </intent-filter>
        </service>   

初始化服务主要代码

  //初始化服务
  Fser := TJNLService.JavaClass.init;

  FNLS := TJIntent.JavaClass.init(SharedActivityContext,Fser.getClass);
  FNLS.setAction(StringToJString
    ('android.service.notification.NotificationListenerService'));

判断监听是否授权

只有被授权的APP才能监听通知栏信息。

  //判断通知监听是否被受权
  //通知的监听必须有特定的受权,没有这个受权,不能接收通知
  //该受权还必须是人工点击确认,这点非常重要
  CheckBox1.IsChecked := AnsiContainsText
    (JStringToString(TJSettings_Secure.JavaClass.getString
    (SharedActivityContext.getContentResolver,
    StringToJString('enabled_notification_listeners'))),'com.tanqin.nlsapp');

调用通知监听授权

以下代码及过调用通知监听授权功能,显示内容如上面第一张截图。

var
  ji: JIntent;
begin
  //打开授权管理

  //通知的监听必须有特定的授权没有这个授权,不能接收通知
  //该授权还必须是人工点击确认,这点非常重要

  //这里是启动手动受权确认功能
  ji := TJIntent.JavaClass.init
    (StringToJString('android.settings.ACTION_NOTIFICATION_LISTENER_SETTINGS'));
  SharedActivityContext.startActivity(ji);
end;

启动监听服务

启动监听服务前,先判断是否授权,如果没有授权则调用授权功能。

var
  vENL: Boolean;
begin
  //开户服务前判断通知监听是否被受权
  vENL := AnsiContainsText(JStringToString(TJSettings_Secure.JavaClass.getString
    (SharedActivityContext.getContentResolver,
    StringToJString('enabled_notification_listeners'))),'com.tanqin.nlsapp');

  CheckBox1.IsChecked := vENL;
  if vENL then
  begin
    //打开通知监听服务
    SharedActivityContext.startService(FNLS);
    CheckBox2.IsChecked := True;
  end
  else
  begin
    //转受权处理   {无受权,不能使用}

  end;

end;

APP完成后的演示

该APP演示了通过监听获取通知栏通知信息的程序包名(用于识别通知发送者)、通知标题、通知内容、通知时间、提交或清除事件。

下图是已经连续运行四天的监听截图。
已连续运行4天的监听程序

后续

该APP通过调整,可指定监听某些特定通知内容。

欢迎大家光临本人小店 :https://shop63778938.taobao.com/

发布了20 篇原创文章 · 获赞 29 · 访问量 6万+

猜你喜欢

转载自blog.csdn.net/tanqth/article/details/78658078
今日推荐