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).
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.
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.