Android - Použití externích JAR na příkladu sériové komunikace přes FTDI

vložil Radek Červinka 30. prosince 2014 22:50

V Delphi XE7 byla vylepšena podpora použití externích JAR knihoven Androidu. Jako příklad použití (předem říkám, že nekompletní, ale principiálně to nejdůležitější zde je, snad to někdo dotáhne do konce) bych ukázat jak na sériovou komunikaci přes USB (a FTDI konvertor - pokud to nevíte, tak FTDI je prakticky etalon pro převodníky USB na serial).

XE7 Android Library

Jako externí knihovnu jsem vybral usb-serial-for-android, je dostatečně jednoduchý, ale zvládá širší spektrum čipů než některé jiné. Také se jedná o userspace driver, tj. nepotřebuje root jako oficiální driver od FTDI.

V čem se liší XE7 od předchůdců? a) byl rozšířen o možnost přímo přidat do projektu požadovanou knihovnu b) Embarcadero vydalo nástroj na použití JAR souborů pro použití přes JNI (předtím bylo několik jiných pokusů od jiných autorů), ale tohle je oficiální.

Java2OP

Pokud to někomu nedošlo, to OP je Object Pascal. Tento nástroj, tedy Java2OP.exe je ke stažení pro majitele XE7, návod je Java2OP.exe,_the_Native_Bridge_File_Generator_for_Android, ale nám bude stačit jen:

  • mít nainstalovanou JAVU (já vím, je to blé)
  • vytvořit si bat soubor (nebo i bez něho)
SET PATH=%PATH%;c:\Program Files (x86)\Java\jdk1.7.0_45\bin
JAVA2OP.EXE -unit Androidapi.JNI.usbserial.pas -jar usb-serial-for-android-v010.jar  

Toto nám po nějakých 10s vyplivne soubor Androidapi.JNI.usbserial.pas ,což sice není moc košer název (protože namespace Androidapi je pro ApiAndroidu) a měl by být podle namespace toho jar, ale to je jedno.

Začlenění do projektu

Jak vidíte na screenshotu na začátku článku, přidáte JAR (to zní jak návod na mytí nádobí) do projektu a Delphi během kompilace vytvoří v adresáři Debug (nebo release) soubor usb-serial-for-android-v010-dexed.jar, který pak vloží do balíčku Androida. Pozn. u XE5 nebo XE6 je to nutno zařídit modifikací classes.dex.

Tímto tedy máme knihovnu, nyní jen ji nějak použít.

Autor píše tři kroky:

3. Copy device_filter.xml to your project's res/xml/ directory.

4. Configure your AndroidManifest.xml to notify your app when a device is attached (see Android USB Host documentation for help).

<activity
    android:name="…"
    …>
  <intent-filter>
    <action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" />
  </intent-filter>
  <meta-data
      android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" 
      android:resource="@xml/device_filter" />
</activity>

5. Use it! Example code snippet:

// Get UsbManager from Android.
UsbManager manager = (UsbManager) getSystemService(Context.USB_SERVICE);

// Find the first available driver.
UsbSerialDriver driver = UsbSerialProber.acquire(manager);

if (driver != null) {
  driver.open();
  try {
    driver.setBaudRate(115200);
    
    byte buffer[] = new byte[16];
    int numBytesRead = driver.read(buffer, 1000);
    Log.d(TAG, "Read " + numBytesRead + " bytes.");
  } catch (IOException e) {
    // Deal with error.
  } finally {
    driver.close();
  } 
}

Takže device_filter.xml: v deployment manager se přidá soubor device_filter.xml a specifikuje se cesta.

deploy

Druhý bod by měl být jasný, upraví se AndroidManifest.template.xml.

A teď vlastní kód, Java varianta je výše:

implementation
uses
  Androidapi.JNI.GraphicsContentViewText, Androidapi.Helpers, FMX.Helpers.Android,  Androidapi.JNIBridge,
  Androidapi.JNI.usbserial, Androidapi.JNI.JavaTypes;

{$R *.fmx}


function SharedUSBManager: JUsbManager;
var
  USBManagerService: JObject;
begin
  USBManagerService := SharedActivityContext.getSystemService(TJContext.JavaClass.USB_SERVICE);
  Result := TJUsbManager.Wrap((USBManagerService as ILocalObject).GetObjectID);
end;

procedure THeaderFooterForm.Button1Click(Sender: TObject);
var
  USBManager: JUsbManager;
  UsbSerialDriver: TJUsbSerialProber;
  Driver: JUsbSerialDriver;
  TempArray: TJavaArray<Byte>;
begin
  USBManager := SharedUSBManager;

  // Find the first available driver.
  Driver := TJUsbSerialProber.JavaClass.acquire(USBManager);

  if (Driver <> nil) then
  begin
    Driver.open;
    try
      Driver.setBaudRate(115200);
      TempArray := TJavaArray<Byte>.Create(10);
      driver.write(TempArray, 10);

{      byte buffer[] = new byte[16];
      int numBytesRead = driver.read(buffer, 1000);
      Log.d(TAG, "Read " + numBytesRead + " bytes.");}
    finally
      Driver.Close;
    end;
  end;

end;

demo download - je to polotovar, pokud s tím někdo pohne, budu rád. Šlo mi primárně o návod jak na to, ale zrovna tohle by za to stálo to doladit.

Jak to ladit? Jelikož na USB je připojen ten FTDI konvertor, je nutno použít ladění přes WIFI.

Pozn.: Všimněte si v kodu toho .JavaClass., to mi chvilku trvalo - tím se dostanete na statické metody třídy.

Pozn2: NFC v Delphi Android - velmi inspirativní a kompletní článek, může to pomoci.


Nabízíme Delphi školení a konzultace na různá témata, primárně ve Vaší firmě.

Tagy: , , ,

Návody

Komentování ukončeno

Naše nabídka

Partial English version.

MVP
Ing. Radek Červinka - Embarcadero MVP
profil na linkedin, Twitter:@delphicz

Nabízím placené poradenství a konzultace v oblasti programování a vývoje SW.
Dále nabízíme i vývoj speciálního software na zakázku.

Neváhejte nás kontaktovat (i ohledně reklamy nebo burzy práce).

Pokud chcete podpořit tento server libovolnou částkou, můžete použít PayPal. Moc děkuji.

Delphi Certified Developer

O Delphi.cz

Delphi je jediný moderní RAD nástroj podporující tvorbu nativních aplikací pro platformu Win32, Win64 , Mac OSX a na iPhone a Android (s výhledem na další platformy díky FireMonkey) na současném trhu (včetně Windows 8.1).

V současnosti je světová komunita přes dva miliónů vývojářů.

Delphi.cz je nezávislý portál pro uživatele Delphi. Portál není koncipován pro úplné začátečníky, i když i ti se zde nebudou nudit, ale spíše na programátory, kteří již něco znají a chtějí své znalosti dále rozvíjet a sledovat novinky.

Anketa

Poslední komentáře

Comment RSS