是否可以使用delphi读取android上其他应用程序的通知? [英] Is it possible to read the notifications of other applications on android with delphi?

查看:90
本文介绍了是否可以使用delphi读取android上其他应用程序的通知?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试从Rad Studio XE7 for android中制作的应用程序读取其他应用程序的通知。
查找,我发现在Java中,您可以访问NotificationListenerService,但如果使用delphi则不能访问此服务。可以做到吗?

I'm trying to read notifications from other applications on an application made in Rad Studio XE7 for android. Looking up, I saw that in java, you can access the NotificationListenerService, but not if with delphi could access this service. Can it be done?

推荐答案

您可以使用 NotificationListenerService阅读其他应用程序的通知,这就是方法

You can read the notifications of other Apps with the use of the NotificationListenerService, and here is how


  • 在项目文件夹中创建一个名为Java的文件夹

  • In your project folder create a folder called Java

现在在该文件夹中创建一个名为src的文件夹,并在其中创建一个文件夹结构,即与您的Apps软件包名称相同:例如src / com / embarcadero / $ yourapp

Now inside that folder create a folder called src and inside it create a folder structure that is the same as your Apps package name E.g : src/com/embarcadero/$yourapp

在src / com / embarcadero内部/ $ yourapp将以下Java文件添加为 NotificationService.java

inside src/com/embarcadero/$yourapp add the following Java file as NotificationService.java

package com.embarcadero.$Yourapp;

import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.service.notification.NotificationListenerService;
import android.service.notification.StatusBarNotification;
import android.util.Log;
import android.support.v4.content.LocalBroadcastManager;


public class NotificationService extends NotificationListenerService {

    static final String TAG = "NotificationService";

    Context context;

    @Override
    public void onCreate() {
        super.onCreate();
        context = getApplicationContext();
        Log.d(TAG,"Service has been started!");
    }
    @Override

    public void onNotificationPosted(StatusBarNotification sbn) {
    Log.d(TAG,"Notification Posted!");
        String pack = sbn.getPackageName();
        Bundle extras = sbn.getNotification().extras;
        String title = extras.getString("android.title");
        String text = extras.getCharSequence("android.text").toString();
        String id = sbn.getTag();

        Log.i("Package", pack);
        Log.i("Title",title);
        Log.i("Text",text);
        if (id != null){
            Log.i("Key", id);
        }
        Intent msgrcv = new Intent("Msg");
        msgrcv.putExtra("package", pack);
        msgrcv.putExtra("key", id);
        msgrcv.putExtra("title", title);
        msgrcv.putExtra("text", text);
        LocalBroadcastManager.getInstance(context).sendBroadcast(msgrcv);

    }

    @Override

    public void onNotificationRemoved(StatusBarNotification sbn) {
        Log.d(TAG,"Notification Removed");

    }
}

并将以下文件添加到Java文件夹:android-support-v4.jar(在您的SDK路径下找到:android-sdk-windows\extras\android\support\v4)

and Add the following files to the Java folder : android-support-v4.jar (Found under your SDK Path : android-sdk-windows\extras\android\support\v4)

添加以下批处理文件 build.bat

@echo off

setlocal

REM Set the your paths as needed 
SET PATH=%PATH%;C:\Users\Public\Documents\Embarcadero\Studio\17.0\PlatformSDKs\android-sdk-windows\build-tools\23.0.1
if x%ANDROID% == x set ANDROID=C:\Users\Public\Documents\Embarcadero\Studio\17.0\PlatformSDKs\android-sdk-windows
set ANDROID_PLATFORM=%ANDROID%\platforms\android-23
set DX_LIB=%ANDROID%\build-tools\23.0.1\lib
set EMBO_DEX="C:\Program Files (x86)\Embarcadero\Studio\17.0\lib\android\debug\classes.dex"
set PROJ_DIR=C:\Users\PJJ\Documents\allesbeste\Mobiletest\java
REM the PROJ_DIR must point to your Java Folder inside your project folder
set VERBOSE=0
set JAVA="C:\Program Files\Java\jdk1.7.0_71\bin"

echo.
echo Compiling the Java service activity source files
echo.
mkdir output 2> nul
mkdir output\classes 2> nul
if x%VERBOSE% == x1 SET VERBOSE_FLAG=-verbose
javac %VERBOSE_FLAG% -source 1.7 -target 1.7 -Xlint:deprecation -cp %ANDROID_PLATFORM%\android.jar;%EMBO_LIB%\fmx.jar;%PROJ_DIR%\android-support-v4.jar -d output\classes src\com\embarcadero\AllesbesteToep\NotificationService.java

echo.
echo Creating jar containing the new classes
echo.
mkdir output\jar 2> nul
if x%VERBOSE% == x1 SET VERBOSE_FLAG=v
jar c%VERBOSE_FLAG%f output\jar\Delphi_Service.jar -C output\classes com

echo.
echo Converting from jar to dex...
echo.
mkdir output\dex 2> nul
if x%VERBOSE% == x1 SET VERBOSE_FLAG=--verbose
call dx --dex %VERBOSE_FLAG% --output=%PROJ_DIR%\output\dex\test_classes.dex --positions=lines %PROJ_DIR%\output\jar\Delphi_Service.jar

echo.
echo Merging dex files
echo.
java -cp %DX_LIB%\dx.jar com.android.dx.merge.DexMerger %PROJ_DIR%\output\dex\classes.dex %PROJ_DIR%\output\dex\test_classes.dex %EMBO_DEX%

echo Tidying up
echo.
REM Just change these as needed
del output\classes\com\embarcadero\AllesbesteToep\NotificationService.class
del output\dex\test_classes.dex
rmdir output\classes\com\embarcadero\AllesbesteToep
rmdir output\classes\com\embarcadero
rmdir output\classes\com
rmdir output\classes
pause

echo.
echo Now we have the end result, which is output\jar\Delphi_Service.jar

:Exit

endlocal

添加位于C:\Program Files(x86)\Embarcadero\的默认classes.dex文件\Studio\17.0\lib\android\debug

Add the default classes.dex file located at C:\Program Files (x86)\Embarcadero\Studio\17.0\lib\android\debug

添加 fmx.jar也位于C:\Program Files (x86)\Embarcadero\Studio\17.0\lib\android\debug

Add the fmx.jar also located at C:\Program Files (x86)\Embarcadero\Studio\17.0\lib\android\debug

然后将其重命名为 classes.jar

所以您的Java文件夹结构现在看起来像这样

So your Java folder structure now looks like this


  • src //具有正确的文件夹结构,并且您的NotificationService.java位于内部

  • src //with the correct folder structure and your NotificationService.java inside

android-support-v4

android-support-v4

如果在构建文件中正确设置了所有变量,则可以运行build.bat生成输出文件夹(特别感谢Brian Long最初创建的文件夹)

if all your variables are set correctly in the build file you can now run build.bat to generate the output folder (Special thanks to Brian Long who initially created it)

现在您的输出文件夹中将有2个文件夹,其中一个名为dex,另一个为jar,现在您将拥有一个新的classes.dex文件和Delphi_Service可执行文件

You will now have 2 folders inside your output folder one called dex and the other jar, Now you will have a new classes.dex file and Delphi_Service executable

让您的应用使用新的classes.dex文件
http://docwiki.embarcadero.com/RADStudio/XE8/en/Creating_and_Deploying_a_classes.dex_File_Manually

将Delphi_Service jar文件添加到您的应用
http://docwiki.embarcadero.com/RADStudio/XE8/en/Adding_A_Java_Library_to_Your_Application_Using_the_Project_Manager

在您的项目文件中添加以下单元 Android.JNI .LocalBroadcastMan

In your project file add the following unit Android.JNI.LocalBroadcastMan

//Created with the Java2OP tool
unit Android.JNI.LocalBroadcastMan;

interface

uses
  Androidapi.JNIBridge,
  Androidapi.JNI.JavaTypes,
  Androidapi.JNI.GraphicsContentViewText,
  Androidapi.JNI.Util,
  Androidapi.JNI.Os,
  Androidapi.JNI.Net;

type
// ===== Forward declarations =====

  JLocalBroadcastManager = interface;//android.support.v4.content.LocalBroadcastManager

// ===== Interface declarations =====

  JLocalBroadcastManagerClass = interface(JObjectClass)
    ['{03179F7E-C439-4369-93CC-AA2BADC54398}']
    {class} function getInstance(context: JContext): JLocalBroadcastManager; cdecl;
  end;

  [JavaSignature('android/support/v4/content/LocalBroadcastManager')]
  JLocalBroadcastManager = interface(JObject)
    ['{6C255CD6-D94E-40BC-A758-EC4965A40725}']
    procedure registerReceiver(receiver: JBroadcastReceiver; filter: JIntentFilter); cdecl;
    function sendBroadcast(intent: JIntent): Boolean; cdecl;
    procedure sendBroadcastSync(intent: JIntent); cdecl;
    procedure unregisterReceiver(receiver: JBroadcastReceiver); cdecl;
  end;
  TJLocalBroadcastManager = class(TJavaGenericImport<JLocalBroadcastManagerClass, JLocalBroadcastManager>) end;

implementation

procedure RegisterTypes;
begin
  TRegTypes.RegisterType('Android.JNI.LocalBroadcastMan.JLocalBroadcastManager', TypeInfo(Android.JNI.LocalBroadcastMan.JLocalBroadcastManager));
end;

initialization
  RegisterTypes;
end.

下载来自 http://www.fmxexpress.com/free-broadcast-接收器组件,用于delphi-xe7-firemonkey-on-android /

安装该组件,现在添加BroadcastReceiver随它一起添加到您的项目中,并在 BroadcastReceiver 中添加以下代码:

Install the component, now add the BroadcastReceiver unit that come with it to your Project and add the following code in BroadcastReceiver:

添加到您的用途:Android .JNI.LocalBroadcastMan

更改 TBroadcastReceiver.Add 过程为

procedure TBroadcastReceiver.Add(Value: String);
{$IFDEF ANDROID}
var
  Filter: JIntentFilter;
  locMan : JLocalBroadcastManager;
{$ENDIF}
begin
  {$IFDEF ANDROID}
  if (FListener = nil) or (FReceiver = nil) then
  begin
    Raise Exception.Create('First use RegisterReceive!');
    Exit;
  end;
  {$ENDIF}

  if FItems <> nil then
    if FItems.IndexOf(Value) = -1 then
    begin
    {$IFDEF ANDROID}
      filter := TJIntentFilter.Create;
      filter.addAction(StringToJString(Value));
      SharedActivityContext.registerReceiver(FReceiver,filter);
      locMan := TJLocalBroadcastManager.JavaClass.getInstance(SharedActivityContext);
      locMan.registerReceiver(FReceiver,Filter);
    {$ENDIF}
      FItems.Add(Value);
    end;
end;

添加以下过程 unRegisterReceive

procedure TBroadcastReceiver.unRegisterReceive;
var
    locMan : JLocalBroadcastManager;
begin
    locMan := TJLocalBroadcastManager.JavaClass.getInstance(SharedActivityContext);
    locMan.unregisterReceiver(FReceiver);
end;

添加以下过程重新使用

procedure TBroadcastReceiver.regagain;
var
    locMan : JLocalBroadcastManager;
    filter : JIntentFilter;
begin
    filter := TJIntentFilter.Create;
    filter.addAction(StringToJString('Msg'));
    locMan := TJLocalBroadcastManager.JavaClass.getInstance(SharedActivityContext);
    locMan.registerReceiver(FReceiver,Filter);
end;

在项目目录中编辑AndroidManifest.template.xml以包含服务

Edit your AndroidManifest.template.xml in your project dir to inlcude the service

<service android:name="com.embarcadero.$Yourapp.NotificationService"
                 android:label="%label%"
          android:permission="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE">
             <intent-filter>
                 <action android:name="android.service.notification.NotificationListenerService" />
             </intent-filter>
   </service>



步骤2:将它们放在一起



在您的项目中添加一个广播接收器组件,然后

Step 2 : Putting it all together

Add a broadcastreciever component to your project and

在您的项目中添加以下过程

Add the following procedure to your project

procedure startService
var
    ServiceIntent: JIntent;
begin
    BroadcastReceiver1.RegisterReceive;
    BroadcastReceiver1.Add('Msg');
    ServiceIntent := TJIntent.JavaClass.init(SharedActivityContext,
      TJLang_Class.JavaClass.forName(
     StringToJString('com.embarcadero.$yourapp.NotificationService'),True,SharedActivity.getClassLoader));
    SharedActivity.startService(serviceIntent)
end;

BroadcastReceiver onReceive 事件,一旦localBroadcastManager通过 onNotificationPosted 方法广播意图后将触发该事件

The BroadcastReceiver has a onReceive event which will get triggered once the localBroadcastManager broadcasts the intent from the onNotificationPosted method

因此,在 onReceive 中,您现在可以根据自己的意图进行操作,例如

Thus in onReceive you can now do with that intent whatever it is you want such as

var
    NoteName,NoteTitle,pack : String;
begin
//Do whatever you want with the intent
    NoteName := JStringToString(Intent.getStringExtra(StringToJString('key')));
    NoteTitle := JStringToString(Intent.getStringExtra(StringToJString('title')));
    pack := JStringToString(Intent.getStringExtra(StringToJString('package')));
    ShowMessage('Notification: '+NoteName+' Title :'+ NoteTitle+' package :'+pack);
end;

现在,我们需要编写一些代码来处理您的App不在其中时的localBroadcastManager的生命周期前景或重新进入前景时

Now we need to write some code to handle the life cycle of the localBroadcastManager when your App is not in the foreground or when it re-enters the foreground

如果您不使用Appevents,请先在此处 http://www.fmxexpress.com/handle-android-and-ios-lifecycle- events-in-delphi-xe5-firemonkey /

If you don't use Appevents first take a look here http://www.fmxexpress.com/handle-android-and-ios-lifecycle-events-in-delphi-xe5-firemonkey/

现在响应 EnteredBackground Appevent添加 unRegisterReceive 过程: BroadcastReceiver1.unRegisterReceive;

Now in response to EnteredBackground Appevent add the unRegisterReceive procedure : BroadcastReceiver1.unRegisterReceive;

WillBecomeForeground Appevent中,添加 regagain 过程: BroadcastReceiver1.regagain;

In response to WillBecomeForeground Appevent add the regagain procedure : BroadcastReceiver1.regagain;

最后,为了使您的应用程序能够读取其他应用程序的通知,您需要明确授予它这样做的权限。

Lastly in order for your App to be able to read the notifications of other Apps you need to explicitly give it permission to do so.

转到您的手机设置并搜索通知访问权限,您会看到其中列出了您的应用,只需说出允许即可

Go to your phones Settings and search for Notification Access and you will see your App listed there, simply say it is allowed

更新1:

添加了处理应用程序生命周期的代码,应用程序现在应该愉快地在前台和后台之间切换并继续工作

Added code to handle the App life cycle, the App should now happily go between foreground and background and continue working

这篇关于是否可以使用delphi读取android上其他应用程序的通知?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆