Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Cross-Platform-Entwicklung (https://www.delphipraxis.net/91-cross-platform-entwicklung/)
-   -   Android: OnNewIntent implementieren (https://www.delphipraxis.net/185946-android-onnewintent-implementieren.html)

DeddyH 21. Jul 2015 08:55

Android: OnNewIntent implementieren
 
Nachdem ich mit der EMDK-API nicht weiterkomme, versuche ich es doch noch einmal über den Intent-Weg. Mittlerweile habe ich es hinbekommen, dass die App nicht mehr direkt nach dem Start abschmiert, allerdings bekomme ich das gewünschte Ereignis OnNewIntent immer noch nicht mit. Ich habe mich an diese Anweisung gehalten, scheinbar funktioniert das so aber nur mit XE 7. Zum Hintergrund: wenn ich per Intent einen Scan auslöse, muss dieser anscheinend zwingend als neuer Intent per Broadcast verschickt werden, sonst passiert nichts. In der Beispielanwendung für Android Studio ist das auch so, nur haben die eben das Event zur Verfügung. Hat schon jemand diese Vorgehensweise, die FMX-Activity entsprechend zu erweitern, unter XE 8 erfolgreich hinbekommen? Für den einen oder anderen Tipp wäre ich sehr dankbar, ich sitze nun schon seit gestern morgen an diesem Mist und komme auf keinen grünen Zweig :evil:

Uwe Raabe 21. Jul 2015 10:11

AW: Android: OnNewIntent implementieren
 
Da der Link auf die Anweisung aktuell nicht aufgelöst werden kann, fehlt jetzt natürlich eine Menge an Informationen. Ich stochere daher mal im Trüben.
  • Machst du Änderungen am AndroidManifest Template?
  • Wie sieht dein Ausgabepfad für das Projekt aus?

DeddyH 21. Jul 2015 10:34

AW: Android: OnNewIntent implementieren
 
Bei mir geht der Link zwar, aber es ist ja recht schnell beschrieben: zunächst die Java-Datei.
Code:
package de.deddyh.someactivity;

import android.os.Bundle;
import android.content.Intent;

public class MyActivity extends com.embarcadero.firemonkey.FMXNativeActivity {

  static final String TAG = "MyIntent";

   @Override
   protected void onNewIntent(Intent intent) {
      super.onNewIntent(intent);
      onMyIntent(intent);
   }

   public native void onMyIntent(Intent intent);
}
Die habe ich kompiliert und zu einer Jar-Bibliothek (de.deddyh.someactivity.MyActivity.jar) verschnürt, hat nach einigen Anläufen funktioniert. Diese Bibliothek habe ich dann dem Projekt hinzugefügt. Anschließend wurde das XML-Template dahingehend geändert, dass die Activity auf meine umgebogen wird (Auszug).
Code:
        <!-- Our activity is a subclass of the built-in NativeActivity framework class.
             This will take care of integrating with our NDK code. -->
        <activity android:name="de.deddyh.someactivity.MyActivity"
                android:label="%activityLabel%"
                android:configChanges="orientation|keyboard|keyboardHidden"
                android:launchMode="singleTask">
So, nun muss der Delphi-Code auch noch entsprechend erweitert werden (auch Auszug).
Delphi-Quellcode:
type
  TOnMyIntent = procedure(Env: PJNIEnv; This: JNIObject; Intent: JNIObject); cdecl;
 
procedure RegisterMyIntent(OnMyIntent: TOnMyIntent);

procedure RegisterMyIntent(OnMyIntent: TOnMyIntent);
var
  JniEnv: PJNIEnv;
  ActivityClass: JNIClass;
  NativeMethod: JNINativeMethod;
begin
    NativeMethod.Name := 'onMyIntent';
    NativeMethod.Signature := '(Landroid/content/Intent;)V';
    NativeMethod.FnPtr := @OnMyIntent;

    JniEnv := TJNIResolver.GetJNIEnv;
    ActivityClass := JniEnv^.GetObjectClass(JniEnv, PANativeActivity(System.DelphiActivity).clazz);
    JniEnv^.RegisterNatives(JniEnv, ActivityClass, @NativeMethod, 1);
    JniEnv^.DeleteLocalRef(JniEnv, ActivityClass);
end;

procedure MyIntent(Env: PJNIEnv; This: JNIObject; Intent: JNIObject); cdecl;
begin
  TThread.Queue(nil,
    procedure
    begin
      Form1.OnNewIntent(TJIntent.Wrap(Intent));
    end);
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  RegisterMyIntent(MyIntent);
end;

procedure TForm1.OnNewIntent(Intent: JIntent);
begin
  SharedActivity.setIntent(Intent);
  ShowMessage('New Intent');
end;
Der Zugriff auf die globale Form-Variable gefällt mir zwar auch nicht, aber zuerst muss es erst einmal funktionieren, bevor man sich da etwas anderes überlegt.
Zum Schluss noch der auslösende Code:
Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
var
  Intent: JIntent;
begin
  Intent := TJIntent.JavaClass.init;
  Intent.setAction
    (StringToJString
    ('com.motorolasolutions.emdk.datawedge.api.ACTION_SOFTSCANTRIGGER'));
  Intent.putExtra
    (StringToJString
    ('com.motorolasolutions.emdk.datawedge.api.EXTRA_PARAMETER'),
    StringToJString('TOGGLE_SCANNING'));
  SharedActivity.sendBroadcast(Intent);
end;
Prinzipiell funktioniert das, nur wird eben das OnNewIntent nicht ausgelöst.

[edit] Nachtrag: eine Fummellösung mit einem Edit, das sich neben der Form befindet, den Fokus hat und per Timer "überwacht" wird, funktioniert zwar prinzipiell, ist aber mehr als unschön, alleine schon deshalb, weil die virtuelle Tastatur natürlich hochklappt und man nicht sieht, wieso eigentlich. [/edit]

Uwe Raabe 21. Jul 2015 11:03

AW: Android: OnNewIntent implementieren
 
Die Frage nach dem Ausgabepfad hatte schon eine Bedeutung: In XE8 gibt es einen Fehler, der das AndroidManifest.Template immer aus dem Verzeichnis zwei Stufen über dem Ausgabepfad nimmt - im Gegensatz zu der Beschreibung, die das Projektverzeichnis dafür nennt. Solange dein Ausgabepfad dem Standard ".\$(Plattform)\$(Config)" entspricht funktioniert das. Andernfalls gelangen deine Änderungen im Template nicht in die tatsächliche Manifest-Datei.

DeddyH 21. Jul 2015 11:07

AW: Android: OnNewIntent implementieren
 
Gerade schnell nachgeschaut, es ist .\$(Platform)\$(Config), daran wird es also wohl nicht liegen. Trotzdem Danke für den Tipp, es kann ja immer mal etwas in der Richtung schiefgehen.

microtronx 23. Mär 2016 10:51

AW: Android: OnNewIntent implementieren
 
Für alle die Daten vom Scanner per Intent abrufen wollen:

1.)
Ich verwende diesen Broadcastreceiver: brsatalay.blogspot.com.tr/2014/10/delphi-android-broadcast-receiver.html
den ich wie folgt aktiviere (einmalig):

Delphi-Quellcode:
mxBreceiver.RegisterReceive;
mxBreceiver.Add('org.mein.intent.name');
die Komponente hat einen onIntent Event, den ich wie folgt definiert habe:

Delphi-Quellcode:
procedure TmxBCD.mxBreceiverReceive(Context: JContext; Intent: JIntent);
var
  vInput:String;
begin
  if ansisametext(JStringToString(intent.getAction), 'org.mein.intent.name') then begin
    // jetzt haben wir etwas erhalten
    vInput:=JStringToString(intent.getStringExtra(Stri ngToJString(DATAWEDGE_DATA_STRING)));
    vInput:=trim(vInput);
    dolog('*receive*'+vinput+'*');  

    // jetzt prüfen, ist das was angekommen ist eine Funktion oder muss ich ein TExtfeld füllen?
  end else begin
    doLog('*unknown_action*'+JStringToString(Intent.ge tAction)+'*');
  end;
end;
Damit das ganze funktioniert musst Du die androidmanifest xml Datei in deinem Projektverzeichniss wie folgt erweitern:

Code:
...
<activity android:name="com.embarcadero.firemonkey.FMXNative Activity"
android:label="%activityLabel%"
android:configChanges="orientation|keyboard|keyboa rdHidden|screenSize"
android:launchMode="singleTask">
<!-- Tell NativeActivity the name of our .so -->
<meta-data android:name="android.app.lib_name"
android:value="%libNameValue%" />
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<action android:name="org.mein.intent.name" /> <!-- HIER die Erweiterung, Rest so belassen -->
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
...
So nun zum Problem bei Datawedge, in Datawedge ein Profil anlegen und nur folgendes aktivieren:

1. bei Verbundene Anwendung wählst Du deine app aus
2. Barcode-Eingabe = Aktiviert
3. MSR Eingabe = Aktiviert
4. Intent Ausgabe = Aktiviert
4.1 Intent-Aktion = org.mein.intent.name
4.2 Intent-Kategorie = LEER LASSEN, nichts eintragen, ist ein Bug von Datawedge
4.3 Intent-Übertragung = Intent Senden

Das wars, bei mir klappt es jetzt hervorragend. Mit dem Edit-Feld hatte ich so meine Probleme, da manchmal der Barcode abgeschnitten wurde usw.

Ich hoffe, ich konnte Dir helfen, kannst ja in deinen Beitrag reinsetzen, damit es auch andere Finden können

microtronx 24. Mär 2016 09:01

AW: Android: OnNewIntent implementieren
 
Noch ein Hinweis, innerhalb der mxBreceiverReceive müssen alle Verarbeitungen in einem Thread ausgeführt werden, sonst gibt es Probleme:

Delphi-Quellcode:
procedure TmxBCD.mxBreceiverReceive(Context: JContext; Intent: JIntent);
begin
    tThread.CreateAnonymousThread(procedure begin
        internal_mxBreceiverReceive(Context, Intent);
    end).start;
end;

procedure TmxBCD.internal_mxBreceiverReceive(Context: JContext; Intent: JIntent);
var
  vInput:String;
begin
  if ansisametext(JStringToString(intent.getAction), 'org.mein.intent.name') then begin
    // jetzt haben wir etwas erhalten
    vInput:=JStringToString(intent.getStringExtra(StringToJString(DATAWEDGE_DATA_STRING)));
    vInput:=trim(vInput);
    dolog('*receive*'+vinput+'*');

    // jetzt prüfen, ist das was angekommen ist eine Funktion oder muss ich ein Textfeld füllen?

  end else begin
    doLog('*unknown_action*'+JStringToString(Intent.getAction)+'*');
  end;
end;


Alle Zeitangaben in WEZ +1. Es ist jetzt 06:34 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz