如何将布尔值(或整数)传递给意图并读取意图(以检测我的活动是从Android AlarmManager启动的)? [英] How to pass boolean (or integer) to intent and read it (to detect that my activity was started from Android AlarmManager)?

查看:147
本文介绍了如何将布尔值(或整数)传递给意图并读取意图(以检测我的活动是从Android AlarmManager启动的)?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我可以将Android应用设置为使用Android AlarmManager在指定时间启动。效果很好,我使用了手册和论坛以获取详细信息(使用Google翻译)。



因此,我正在使用Java代码(从XE7创建DEX文件,您只需附加JAR 而不创建dex(!))。为了检测我的应用是否是从AlarmManager启动的,我决定使用 stackoverflow上的这本 Java手册,所以我在这行代码中添加了以下代码:

  TestLauncher.putExtra( StartedFromAM ,true); 

完整的Java代码,它将被编译为jar(或dex):

  package com.TestReceiver; 

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;

公共类AlarmReceiver扩展了BroadcastReceiver {
public void onReceive(Context context,Intent intent){
Intent TestLauncher = new Intent();

TestLauncher.setClassName(上下文, com.embarcadero.firemonkey.FMXNativeActivity);
TestLauncher.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
TestLauncher.putExtra( StartedFromAM,true);
context.startActivity(TestLauncher);
}
}

所以从理论上讲,我的Intent已经使用StartedFromAM参数。 / p>

它可以编译为dex文件,问题是我无法从Delphi代码中读取此布尔值-始终为0(假)。



我尝试过此操作:

  ShowMessage(SharedActivity.getIntent.getBooleanExtra(StringToJString('StartedFromAM' ),false).ToString); 

ShowMessage(MainActivity.getIntent.getBooleanExtra(StringToJString(’StartedFromAM’),false).ToString);

更新1



感谢Blong先生,我已经找到了正确的解决方案,该方法可以检测到我的活动是从Android AlarmManager启动的,此更新仅涉及Java代码中的PutExtra,并从Delphi的意图中读取了额外的价值。您可以根据需要跳过它。



现在,我知道我可以连接JAR文件(我的Berlin upd 2),而无需创建dex。
所以我创建了一个新的jar文件-上面显示了完整的Java代码。
然后我创建了一个新项目,并使用此代码设置了警报

 过程SetAlarmWakeUpAdnroid(aSeconds:integer); 

函数getTimeAfterInSecs(Seconds:Integer):Int64;
var
日历:JCalendar;
开始
日历:= TJCalendar.JavaClass.getInstance;
Calendar.add(TJCalendar.JavaClass.SECOND,秒);
结果:= Calendar.getTimeInMillis;
结尾;

var
Intent:JIntent;
PendingIntent:JPendingIntent;
vRes:布尔值;
开始
Intent:= TJIntent.Create;
Intent.setClassName(TAndroidHelper.Context,StringToJString(’com.embarcadero.firemonkey.FMXNativeActivity’));

PendingIntent:= TJPendingIntent.JavaClass.getActivity(TAndroidHelper.Context,1,Intent,0);

TAndroidHelper.AlarmManager。& set(TJAlarmManager.JavaClass.RTC_WAKEUP,getTimeAfterInSecs(30),
PendingIntent);
结尾;

过程TForm1.Button1Click(Sender:TObject);
开始
SetAlarmWakeUpAdnroid(30);
结尾;

然后我添加了OnFormCreate事件

 程序TForm1.FormCreate(Sender:TObject); 
begin
ShowMessage(’StartedFromAM =’+ TAndroidHelper.Activity.getIntent.getBooleanExtra(StringToJString(’StartedFromAM’),false).ToString);
ShowMessage(’EXTRA_ALARM_COUNT =’+ TAndroidHelper.Activity.getIntent.getIntExtra(TJIntent.JavaClass.EXTRA_ALARM_COUNT,0).ToString);
结尾;

当警报管理器启动我的应用程序时,我得到EXTRA_ALARM_COUNT = 1且StartedFromAM = 0。

解决方案

有几个要回答的问题:



1 )原理很好。如果Java代码已正确编译并正确链接,则当 AlarmManager 通过 BroadcastReceiver ,这样的代码将按您期望的方式运行:

 使用
Androidapi.Helpers,
Androidapi。 JNI.GraphicsContentViewText;
...
var
目的:JIntent;
...
Intent:= TAndroidHelper.Activity.getIntent;
如果Intent.getBooleanExtra(StringToJString('StartedFromAM'),为False),则
lblInfo.Text:='由警报管理器通过广播接收器启动';

2)Delphi包含Java .jar文件可能会引起麻烦。在没有任何其他证据的情况下,我将假定您在代码看起来可行但似乎无法正常工作的情况下遇到了这个问题。



使用.jar时文件包含在您的Delphi Android项目中,如果您更改或重建.jar文件,Delphi会令人讨厌地注意到它已被更新,因此仍然会链接到您最初添加的.jar版本中。



要解决此问题,您可以清理项目(在项目管理器树控件中右键单击项目名称,然后选择清理)。如果您想绝对肯定地解决了该问题,则应该:


  1. 清理项目(确保获取项目的Android输出目录)

  2. 从项目的Android库列表中删除.jar文件

  3. 在Delphi中关闭项目

  4. 重建您的.jar文件

  5. 在Delphi中重新打开项目

  6. 将.jar文件重新添加到项目的Android库列表中

我在查看此警报管理器场景时遇到了这个问题。



注意我指的是一个.jar文件。这就是您从 Delphi XE7起添加到项目中的内容。在XE6 您必须根据Delphi的classes.dex创建合并的classes.dex文件。以及您的.jar文件并使用该文件,并且由于问题涉及创建DEX文件,因此问题可能出在以下规定的步骤上?与向项目中添加.jar相比,这要麻烦得多。



3)链接的源文章涵盖了两个从 AlarmManager 。您已经研究了通过广播接收器执行的方法,该方法已经用Java实现了,这增加了创建过程的复杂性。



引用的另一种方法该文章中的 AlarmManager 直接触发了您的活动。现在您可能会说:当广播接收器不在画面中时,我怎么知道活动是否通过警报触发?答案是活动意图将自动包含一个称为 EXTRA_ALARM_COUNT



这意味着您可以编写这样的代码,例如在 OnCreate 事件处理程序,并完全避免使用自定义Java代码:

 使用
Androidapi.Helpers,
Androidapi.JNI.GraphicsContentViewText;
...
var
目的:JIntent;
...
Intent:= TAndroidHelper.Activity.getIntent;
如果Intent.getIntExtra(TJIntent.JavaClass.EXTRA_ALARM_COUNT,0)> 0,然后
lblInfo.Text:=由警报管理器通过FMX活动启动;

4)您会注意到我正在使用 TAndroidHelper.Activity 而不是 SharedActivity 。后者在西雅图的Delphi 10中更改为前者。


I can setup my android app to start at specified time with Android AlarmManager. It works nice, I used this manual and this forum for details (use google translator).

So I'm creating DEX file from Java code (from XE7 you can simply attach JAR without creating dex(!)). To detect if My app was started from AlarmManager I decided to put boolean var to intent, using this java manual from stackoverflow, so I added to java code this line:

TestLauncher.putExtra("StartedFromAM", true);

Full Java code, that will be compiled to jar (or dex):

package com.TestReceiver;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;

    public class AlarmReceiver extends BroadcastReceiver {
        public void onReceive(Context context, Intent intent) {
            Intent TestLauncher = new Intent();                        

                TestLauncher.setClassName(context, "com.embarcadero.firemonkey.FMXNativeActivity");
                TestLauncher.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
TestLauncher.putExtra("StartedFromAM", true);
                context.startActivity(TestLauncher);         
        }
    }

So now in theory my Intent has StartedFromAM argument.

It compiles to dex file ok, the problem is I can't read this boolean from Delphi code - it is always = 0 (false).

I tried this:

ShowMessage(SharedActivity.getIntent.getBooleanExtra(StringToJString('StartedFromAM'), false).ToString);

ShowMessage(MainActivity.getIntent.getBooleanExtra(StringToJString('StartedFromAM'), false).ToString);

Update 1

Thanks to Mr. Blong I already got right solution on how to detect that my activity was started from Android AlarmManager, this update is just about PutExtra in Java Code and reading extra value from intent from Delphi. You can skip it if you want.

Now I know that I can connect JAR files (I have Berlin upd 2), without creating dex. So I created new jar file - which full java code I showed above. Then I created new project, and setup alarm with this code

    procedure SetAlarmWakeUpAdnroid(aSeconds: integer);

      function getTimeAfterInSecs(Seconds: Integer): Int64;
      var
        Calendar: JCalendar;
      begin
        Calendar := TJCalendar.JavaClass.getInstance;
        Calendar.add(TJCalendar.JavaClass.SECOND, Seconds);
        Result := Calendar.getTimeInMillis;
      end;

    var
      Intent: JIntent;
      PendingIntent: JPendingIntent;
      vRes: boolean;
    begin
      Intent := TJIntent.Create;
      Intent.setClassName(TAndroidHelper.Context, StringToJString('com.embarcadero.firemonkey.FMXNativeActivity'));

      PendingIntent := TJPendingIntent.JavaClass.getActivity(TAndroidHelper.Context, 1, Intent, 0);

      TAndroidHelper.AlarmManager.&set(TJAlarmManager.JavaClass.RTC_WAKEUP, getTimeAfterInSecs(30),
        PendingIntent);
    end;

    procedure TForm1.Button1Click(Sender: TObject);
    begin
      SetAlarmWakeUpAdnroid(30);
    end;

Then I added OnFormCreate event

procedure TForm1.FormCreate(Sender: TObject);
begin
  ShowMessage('StartedFromAM =' +  TAndroidHelper.Activity.getIntent.getBooleanExtra(StringToJString('StartedFromAM'), false).ToString);
  ShowMessage('EXTRA_ALARM_COUNT = ' + TAndroidHelper.Activity.getIntent.getIntExtra(TJIntent.JavaClass.EXTRA_ALARM_COUNT, 0).ToString);
end;

When Alarm manager started my app, I got EXTRA_ALARM_COUNT = 1 and StartedFromAM = 0.

解决方案

There are a few things to say in reply to this question:

1) The principle works fine. If the Java code has been correctly compiled and correctly linked in, then when your activity is invoked by the AlarmManager via your BroadcastReceiver, code like this will operate as you expect:

uses
  Androidapi.Helpers,
  Androidapi.JNI.GraphicsContentViewText;
...
var
  Intent: JIntent;
...
  Intent := TAndroidHelper.Activity.getIntent;
  if Intent.getBooleanExtra(StringToJString('StartedFromAM'), False) then
    lblInfo.Text := 'Started by Alarm Manager through Broadcast Receiver';

2) There is a potential gotcha with Delphi's inclusion of Java .jar files. In the absence of any additional evidence I will assume you have hit this in your situation where your code looks viable but appears to not be functioning.

When working with a .jar file that is included into your Delphi Android project, if you change or rebuild the .jar file, Delphi has an irksome tendency to not notice it has been updated, and so still links in your originally added version of the .jar.

To overcome this you can clean the project (right click on the project name in the Project manager tree control and choose Clean). If you want to be absolutely definitely sure that you have addressed the issue you should:

  1. clean the project (ensuring the project's Android output directory gets removed)
  2. remove the .jar file from the project's Android, Libraries list
  3. close the project in Delphi
  4. rebuild your .jar file
  5. reopen the project in Delphi
  6. re-add the .jar file to the project's Android, Libraries list

I hit this problem myself while looking at this alarm manager scenario.

Note I refer to a .jar file. That is what you add to your project from Delphi XE7 onwards. In XE6 you must create a merged classes.dex file from Delphi's classes.dex and your .jar file and work with that, and since the question refers to creating a DEX file, maybe the issue comes in following the prescribed steps? This is a much more cumbersome exercise than adding a .jar to the project.

3) The linked source article covers 2 options for invoking your application from the AlarmManager. You've looked at the approach that goes via a broadcast receiver, which you have implemented in Java - that added complications for you to build that up.

The other approach cited in that article has the AlarmManager directly trigger your activity. Now you may say "Well how do I know if the activity was triggered through an alarm, when my broadcast receiver is out of the picture?" and the answer would be that the activity intent will automatically contain an integer extra called EXTRA_ALARM_COUNT.

This means you can write some code like this, say in your OnCreate event handler, and entirely avoid custom Java code:

uses
  Androidapi.Helpers,
  Androidapi.JNI.GraphicsContentViewText;
...
var
  Intent: JIntent;
...
  Intent := TAndroidHelper.Activity.getIntent;
  if Intent.getIntExtra(TJIntent.JavaClass.EXTRA_ALARM_COUNT, 0) > 0 then
    lblInfo.Text := 'Started by Alarm Manager through FMX Activity';

4) You'll note that I am using TAndroidHelper.Activity instead of SharedActivity. The latter changed over to the former in Delphi 10 Seattle.

这篇关于如何将布尔值(或整数)传递给意图并读取意图(以检测我的活动是从Android AlarmManager启动的)?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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