DELPHI XE Android 开发笔记

第一次编译时,设定android SDK:

F:\RAD Studio XE6\PlatformSDKs\adt-bundle-windows-x86-20131030\sdk

F:\RAD Studio XE6\PlatformSDKs\android-ndk-r9c

C:\Program Files\Java\jdk1.7.0_40

SDK更新代理

XE6 不支持JStringToString、StringTojString、StrToJURI:use Androidapi.Helpers

//Splash Image

Delphi XE5,XE6,XE7编译的程序在Android下启动会有一段时间黑屏,以前需要用Java扩展Activity增加Splash显示,
现在Delphi XE7增加了Splash Image显示功能了。
步骤:
1.鼠标右键点击工程,选择Options,
2.进入Application分页
3.勾选Include Splash Image
4.选择您的Splash Image文件
5.设置Splash Tile mode和Splash Gravity
Splash Tile Mode
disabled -按图片尺寸大小显示,显示位置有Splash Gravity设置
clamp - 图形边框适应屏幕大小
repeat - 屏幕水平,竖立方向重复填充满Splash Image
mirror - 跟repeat差不多,图片是镜像的。
Gravity 设置比屏幕小的图片在屏幕中的位置,只有当Splash Title Mode为Disable时有效,
参数大家一看便知道什么意思了,我就不提了。

带文件发布

菜单 project ->deployment->然后点击增加按钮,选择中sqlite数据 test.s3db,

remote path 填写 assets\internal\

应用显示中文名(工程不能为中文否则会编译出错)

菜单 project ->Option->Version Info->label

FMX.Consts汉化(需要更改单元)

{ Dialog Strings }

//  SMsgDlgWarning = 'Warning';

//  SMsgDlgError = 'Error';

//  SMsgDlgInformation = 'Information';

//  SMsgDlgConfirm = 'Confirm';

//  SMsgDlgYes = 'Yes';

//  SMsgDlgNo = 'No';

//  SMsgDlgOK = 'OK';

//  SMsgDlgCancel = 'Cancel';

//  SMsgDlgHelp = 'Help';

//  SMsgDlgHelpNone = 'No help available';

//  SMsgDlgHelpHelp = 'Help';

//  SMsgDlgAbort = 'Abort';

//  SMsgDlgRetry = 'Retry';

//  SMsgDlgIgnore = 'Ignore';

//  SMsgDlgAll = 'All';

//  SMsgDlgNoToAll = 'No to All';

//  SMsgDlgYesToAll = 'Yes to &All';

//  SMsgDlgClose = 'Close';

//

//  SWindowsVistaRequired = '%s requires Windows Vista or later';

//

//  SUsername = '&Username';

//  SPassword = '&Password';

//  SDomain = '&Domain';

//  SLogin = 'Login';

SMsgDlgWarning = '警告';

SMsgDlgError = '错误';

SMsgDlgInformation = '信息';

SMsgDlgConfirm = '确认';

SMsgDlgYes = '是的';

SMsgDlgNo = '不是';

SMsgDlgOK = '确定';

SMsgDlgCancel = '取消';

SMsgDlgHelp = '帮助';

SMsgDlgHelpNone = '没有提供帮助';

SMsgDlgHelpHelp = '帮助';

SMsgDlgAbort = '放弃';

SMsgDlgRetry = '重试';

SMsgDlgIgnore = '忽略';

SMsgDlgAll = '全部';

SMsgDlgNoToAll = '全选“不是”';

SMsgDlgYesToAll = '全选“是”';

SMsgDlgClose = '关闭';

SWindowsVistaRequired = '%s 需要 Windows Vista 或以上操作系统';

SUsername = '&用户名';

SPassword = '&密码';

SDomain = '&域名';

SLogin = '登录';

临时文件路径(支持安卓、IOS)

function GeFileName(const AFileName: string): string;

begin

{$IFDEF ANDROID}

Result := TPath.GetTempPath + '/' + AFileName;

{$ELSE}

{$IFDEF IOS}

Result := TPath.GetHomePath + '/Documents/' + AFileName;

{$ELSE}

Result := AFileName;

{$ENDIF}

{$ENDIF}

end;

IOUtils文件说明

路径类

TPath.GetTempPath; {获取临时文件夹路径}

TPath.GetTempFileName; {获取一个临时文件名}

TPath.GetPathRoot(); {提取盘符, 如: c:\}

TPath.GetDirectoryName(); {提取路径}

TPath.GetFileName(); {提取文件名}

TPath.GetExtension(); {提取扩展名}

TPath.GetFileNameWithoutExtension(); {提取无扩展名的文件名}

TPath.ChangeExtension(); {更换扩展名}

TPath.DriveExists(); {检查路径中的驱动器是否存在}

TPath.GetFullPath(); {根据相对路径给出全路径}

TPath.HasExtension(); {判断是否有扩展名}

TPath.IsPathRooted(); {判断是否是绝对路径}

TPath.Combine(); {结合路径}

TPath.GetRandomFileName; {产生一个随机文件名}

TPath.GetGUIDFileName(); {用于产生一个唯一的文件名, 布尔参数 决定名称中是否包含 -}

TPath.IsValidPathChar(); {判断给定的字符是否能用于路径名}

TPath.IsValidFileNameChar(); {判断给定的字符是否能用于文件名}

TPath.AltDirectorySeparatorChar; {Windows 下是 "\"}

TPath.AltDirectorySeparatorChar; {Windows 下是 "/"}

TPath.ExtensionSeparatorChar; {Windows 下是 "."}

TPath.PathSeparator; {Windows 下是 ";"}

TPath.VolumeSeparatorChar; {Windows 下是 ":"}

//目录类

TDirectory.CreateDirectory(); {建立新目录}

TDirectory.Exists(); {判断文件夹是否存在}

TDirectory.IsEmpty(); {判断文件夹是否为空}

TDirectory.Copy(); {复制文件夹}

TDirectory.Move(); {移动文件夹}

TDirectory.Delete(); {删除文件夹, 第二个参数为 True 可删除 非空文件夹}

TDirectory.GetDirectoryRoot(); {获取目录的根盘符, 如: C:\}

TDirectory.GetCurrentDirectory; {获取当前目录}

TDirectory.SetCurrentDirectory(); {设置当前目录}

TDirectory.GetLogicalDrives; {获取驱动器列表; 下有举例}

TDirectory.GetAttributes(); {获取文件夹属性, 譬如只读、存档等; 下有举例}

TDirectory.SetAttributes(); {设置文件夹属性; 下有举例}

//文件类

TFile.Exists();//判断指定的文件是否存在

TFile.Copy();//复制文件

TFile.Move();//移动文件

TFile.Delete();//删除文件

TFile.Replace();//替换文件

MotionSensor1: TMotionSensor; 加速传感器

MotionSensor1.Sensor(AngleAccelX、AngleAccelY、AngleAccelZ)加速度

procedure TAccelerometerForm.Timer1Timer(Sender: TObject);

var

LProp: TCustomMotionSensor.TProperty;

begin

for LProp in MotionSensor1.Sensor.AvailableProperties do

begin

{ get the data from the sensor }

case LProp of

TCustomMotionSensor.TProperty.AccelerationX:

begin

lbAccelerationX.Visible := True;

lbAccelerationX.Text := Format('Acceleration X: %6.2f', [MotionSensor1.Sensor.AccelerationX]);

end;

end;

end;

OrientationSensor1: TOrientationSensor;方位传感器

OrientationSensor1.Sensor(TiltX,TiltY,TiltZ)

procedure TOrientationSensorForm.Timer1Timer(Sender: TObject);

begin

{ get the data from the sensor }

lbTiltX.Text := Format('Tilt X: %f', [OrientationSensor1.Sensor.TiltX]);

lbTiltY.Text := Format('Tilt Y: %f', [OrientationSensor1.Sensor.TiltY]);

lbTiltZ.Text := Format('Tilt Z: %f', [OrientationSensor1.Sensor.TiltZ]);

lbHeadingX.Text := Format('Heading X: %f', [OrientationSensor1.Sensor.HeadingX]);

lbHeadingY.Text := Format('Heading Y: %f', [OrientationSensor1.Sensor.HeadingY]);

lbHeadingZ.Text := Format('Heading Z: %f', [OrientationSensor1.Sensor.HeadingZ]);

end;

TSensorManager传感器管理器(包含上述两种传感器,Samples\Object Pascal\Mobile Samples\Device Sensors and Services\SensorInfo)

TSensorCategory = (Location, Environmental, Motion, Orientation, Mechanical, Electrical, Biometric, Light, Scanner);

位置传感器,环境传感器,运动传感器,方向传感器,机械传感器,电传感器,生物传感器,光繁传感器,扫描仪传感器

TActionList组件可以添加标准事件(New Standard Action)

TakePhotoFromCameraAction1: TTakePhotoFromCameraAction; // 通过手机摄像头获取图片

TakePhotoFromLibraryAction1: TTakePhotoFromLibraryAction; //获取手机已存在图片

ShowShareSheetAction1: TShowShareSheetAction;//用其它程序分享图片(Bitmap.Assign();)

获取麦克风设置   FMX.Media

FMicrophone: TAudioCaptureDevice;

FMicrophone := TCaptureDeviceManager.Current.DefaultAudioCaptureDevice;

FMicrophone.FileName 设置路径

FMicrophone.State = TCaptureDeviceState.Capturing 设备状态

FMicrophone.StartCapture; //开始录音

FMicrophone.StopCapture; // 结束录音

MediaPlayer: TMediaPlayer; 媒体播放器

MediaPlayer.FileName 设置路径

MediaPlayer.Play; // 开始播放

MediaPlayer.Stop; // 结束播放

获取手机摄像头

Camera: TCameraComponent;

Camera.Active := True; //打开

Camera.Active := False; //停止

Camera.SampleBufferToBitmap(imgCameraView.Bitmap, True); //保存图片

TThread.Synchronize(TThread.CurrentThread, GetImage); //线程保存图片

Camera.Quality 图像质量

Camera.HasFlash 是否有闪光灯

Camera.TorchMode := TTorchMode.ModeOn; //打开闪光灯 Camera.FlashMode := FMX.Media.TFlashMode.fmFlashOff;

Camera.TorchMode := TTorchMode.ModeOff;//关闭闪光灯 Camera.FlashMode := FMX.Media.TFlashMode.fmFlashOn;

Camera.Kind := FMX.Media.TCameraKind.ckFrontCamera;//前置摄像头

Camera.Kind := FMX.Media.TCameraKind.ckBackCamera;//后置摄像头

获取设备信息

lbDeviceType.Text := Format('Device Type: %s', [JStringToString(TJBuild.JavaClass.MODEL)]);

lbOSName.Text := Format('OS Name: %s', [GetCodename(JStringToString(TJBuild_VERSION.JavaClass.RELEASE))]);

lbOSVersion.Text := Format('OS Version: %s', [JStringToString(TJBuild_VERSION.JavaClass.RELEASE)]);

GestureManager1: TGestureManager; 手势识别组件(igiRotate|旋转、igiZoom|缩放、igiLongTap|长按)

组件关联GestureManager1(Touch.GestureManager,Getures.Standard可以直接添加事件)

procedure TPinchZoom.FormGesture(Sender: TObject;   const EventInfo: TGestureEventInfo; var Handled: Boolean);

var

LObj: IControl;

LImage: TImage;

LImageCenter: TPointF;

begin

if EventInfo.GestureID = igiZoom then

begin

LObj := Self.ObjectAtPoint(ClientToScreen(EventInfo.Location));

if LObj is TImage then

begin

if (not(TInteractiveGestureFlag.gfBegin in EventInfo.Flags)) and

(not(TInteractiveGestureFlag.gfEnd in EventInfo.Flags)) then

begin

{ zoom the image }

LImage := TImage(LObj.GetObject);

LImageCenter := LImage.Position.Point + PointF(LImage.Width / 2,

LImage.Height / 2);

LImage.Width := LImage.Width + (EventInfo.Distance - FLastDistance);

LImage.Height := LImage.Height + (EventInfo.Distance - FLastDistance);

LImage.Position.X := LImageCenter.X - LImage.Width / 2;

LImage.Position.Y := LImageCenter.Y - LImage.Height / 2;

end;

FLastDistance := EventInfo.Distance;

end;

end;

end;

获取地理信息

LocationSensor1: TLocationSensor;//定位

LocationSensor1.Active := swLocationSensorActive.IsChecked; //开始

NewLocation.Latitude //经度

NewLocation.Longitude //纬度

FGeocoder: TGeocoder;//地理编码

procedure TLocationForm.LocationSensor1LocationChanged(Sender: TObject;
  const OldLocation, NewLocation: TLocationCoord2D);
const
  LGoogleMapsURL: String = 'https://maps.google.com/maps?q=%s,%s';
var
  ENUSLat, ENUSLong: String; // holders for URL strings
begin
  ENUSLat := NewLocation.Latitude.ToString(ffGeneral, 5, 2, TFormatSettings.Create('en-US'));
  ENUSLong := NewLocation.Longitude.ToString(ffGeneral, 5, 2, TFormatSettings.Create('en-US')); 
  { convert the location to latitude and longitude }
  lbLatitude.Text := 'Latitude: ' + ENUSLat;
  lbLongitude.Text := 'Longitude: ' + ENUSLong;

{ and track the location via Google Maps }
  WebBrowser1.Navigate(Format(LGoogleMapsURL, [ENUSLat, ENUSLong]));

// Setup an instance of TGeocoder

try

if not Assigned(FGeocoder) then

begin

if Assigned(TGeocoder.Current) then

FGeocoder := TGeocoder.Current.Create;

if Assigned(FGeocoder) then

FGeocoder.OnGeocodeReverse := OnGeocodeReverseEvent;

end;

except

ListBoxGroupHeader1.Text := 'Geocoder service error.';

end;

// Translate location to address

if Assigned(FGeocoder) and not FGeocoder.Geocoding then

FGeocoder.GeocodeReverse(NewLocation);
end;

//地理信息

procedure TLocationForm.OnGeocodeReverseEvent(const Address: TCivicAddress);

begin

ListBoxItemAdminArea.ItemData.Detail       := Address.AdminArea; //省份

ListBoxItemCountryCode.ItemData.Detail     := Address.CountryCode; //国家编码 CN

ListBoxItemCountryName.ItemData.Detail     := Address.CountryName; //国家

ListBoxItemFeatureName.ItemData.Detail     := Address.FeatureName; //镇

ListBoxItemLocality.ItemData.Detail        := Address.Locality; //市

ListBoxItemPostalCode.ItemData.Detail      := Address.PostalCode; //邮政编码

ListBoxItemSubAdminArea.ItemData.Detail    := Address.SubAdminArea;//子级省

ListBoxItemSubLocality.ItemData.Detail     := Address.SubLocality;//子级市

ListBoxItemSubThoroughfare.ItemData.Detail := Address.SubThoroughfare;//街道

ListBoxItemThoroughfare.ItemData.Detail    := Address.Thoroughfare;//子街道

end;

获取本机信息

FMX.Android.DeviceInfo.GetInformation;

Memo1.Lines.Add('ID:'+FMX.Android.DeviceInfo.ID);

Memo1.Lines.Add('IMEI:'+FMX.Android.DeviceInfo.IMEI);

Memo1.Lines.Add('User:'+FMX.Android.DeviceInfo.User);

Memo1.Lines.Add('Host:'+FMX.Android.DeviceInfo.Host);

Memo1.Lines.Add('Tags:'+FMX.Android.DeviceInfo.Tags);

Memo1.Lines.Add('Time:'+FMX.Android.DeviceInfo.Time);

Memo1.Lines.Add('AType:'+FMX.Android.DeviceInfo.AType);

Memo1.Lines.Add('Board:'+FMX.Android.DeviceInfo.Board);

Memo1.Lines.Add('Radio:'+FMX.Android.DeviceInfo.Radio);

Memo1.Lines.Add('Brand:'+FMX.Android.DeviceInfo.Brand);

Memo1.Lines.Add('Model:'+FMX.Android.DeviceInfo.Model);

Memo1.Lines.Add('Serial:'+FMX.Android.DeviceInfo.Serial);

Memo1.Lines.Add('Device:'+FMX.Android.DeviceInfo.Device);

Memo1.Lines.Add('CpuABI:'+FMX.Android.DeviceInfo.CpuABI);

Memo1.Lines.Add('CpuABI2:'+FMX.Android.DeviceInfo.CpuABI2);

Memo1.Lines.Add('Display:'+FMX.Android.DeviceInfo.Display);

Memo1.Lines.Add('Product:'+FMX.Android.DeviceInfo.Product);

Memo1.Lines.Add('Hardware:'+FMX.Android.DeviceInfo.Hardware);

Memo1.Lines.Add('Bootloader:'+FMX.Android.DeviceInfo.Bootloader);

Memo1.Lines.Add('FingerPrint:'+FMX.Android.DeviceInfo.FingerPrint);

Memo1.Lines.Add('Manufacturer:'+FMX.Android.DeviceInfo.Manufacturer);

MapView1: TMapView;//地图足迹

WebBrowser1: TWebBrowser; //浏览器

WebBrowser1.Navigate('www.baidu.com'); //打开网页

WebBrowser1.URL := '';//打开网页

WebBrowser1.GoForward; //前进

WebBrowser1.GoBack;//后退

ShowMessage、MessageDlg、InputQuery //对话框很方便

消息提醒(从手机屏幕顶部向下滑动,出现的提示消息)

NotificationC: TNotificationCenter;

procedure TNotificationsForm.btnSendNotificationImmediatelyClick(

Sender: TObject);

var

Notification: TNotification;

begin

{ verify if the service is actually supported }

if NotificationC.Supported then

begin

Notification := NotificationC.CreateNotification;

try

Notification.Name := 'MyNotification';

Notification.AlertBody := 'Delphi for Mobile is here!';

Notification.FireDate := Now; //可修改发送消息时间

{ Send notification in Notification Center }

NotificationC.ScheduleNotification(Notification);

{ also this method is equivalent }

// NotificationService.PresentNotification(Notification);

finally

Notification.DisposeOf;

end;

end

end;

if NotificationC.Supported then

NotificationC.CancelNotification('MyNotification'); //取消消息

NotificationC.CancelAll; //取消所有消息

程序事件服务

var

FMXApplicationEventService: IFMXApplicationEventService;

begin

if TPlatformServices.Current.SupportsPlatformService (IFMXApplicationEventService, IInterface(FMXApplicationEventService)) then

FMXApplicationEventService.SetApplicationEventHandler(HandleAppEvent)

else

flag := false;

end;

function TForm1.HandleAppEvent(AAppEvent: TApplicationEvent; AContext: TObject)   : boolean;

begin

if flag = false then

exit;

case AAppEvent of

TApplicationEvent.aeEnteredBackground:

begin

//当程序后台运行了

end;

end;

Result := true;

end;

电话信息(Call拨号)

PhoneDialerService: IFMXPhoneDialerService;

获取电话服务信息

procedure TPhoneDialerForm.btnGetCarrierInfoClick(Sender: TObject);

var

PhoneDialerService: IFMXPhoneDialerService;

begin

{ test whether the PhoneDialer services are supported }

if TPlatformServices.Current.SupportsPlatformService(IFMXPhoneDialerService, IInterface(PhoneDialerService)) then

begin

{ if yes, then update the labels with the retrieved information }

CarrierNameItem.ItemData.Detail := PhoneDialerService.GetCarrier.GetCarrierName;

CountryCodeItem.ItemData.Detail := PhoneDialerService.GetCarrier.GetIsoCountryCode;

NetworkCodeItem.ItemData.Detail := PhoneDialerService.GetCarrier.GetMobileCountryCode;

MobileNetworkItem.ItemData.Detail := PhoneDialerService.GetCarrier.GetMobileNetwork;

end

else

ShowMessage('PhoneDialer service not supported');

end;

拨号

procedure TPhoneDialerForm.btnMakeCallClick(Sender: TObject);

var

PhoneDialerService: IFMXPhoneDialerService;

begin

{ test whether the PhoneDialer services are supported }

if TPlatformServices.Current.SupportsPlatformService(IFMXPhoneDialerService, IInterface(PhoneDialerService)) then

begin

{ if the Telephone Number is entered in the edit box then make the call, else

display an error message }

if edtTelephoneNumber.Text <> '' then

PhoneDialerService.Call(edtTelephoneNumber.Text)

else

begin

ShowMessage('Please type in a telephone number.');

edtTelephoneNumber.SetFocus;

end;

end

else

ShowMessage('PhoneDialer service not supported');

end;

Intent :TJIntent

uses

Androidapi.JNI.GraphicsContentViewText, FMX.Helpers.Android, Androidapi.JNI.Net, Androidapi.Helpers;

procedureCall_URI(constAAction : JString;constAURI: string);

var

uri: Jnet_Uri;

Intent: JIntent;

begin

uri := StrToJURI(AURI);

Intent := TJIntent.JavaClass.init(AAction, uri);

{Intent.putExtra()

//短信

Call_URI(TJIntent.JavaClass.ACTION_SENDTO, 'smsto:137114553XX');

Intent.putExtra(StringToJString('sms_body'), StringToJString('测试短信'));

如果是要发短信等复杂的应用,需要传递各种其他的参数.要用到Intent.putExtra()传递多个参数.

这里只封装最简单的,具体Intent.putExtra()的用法,可以查询Java的资料.大把的

}

SharedActivityContext.startActivity(Intent);

end;

//使用例子:

//打电话

Call_URI(TJIntent.JavaClass.ACTION_CALL, 'tel:137114553XX');

//打开地图显示某个坐标点

Call_URI(TJIntent.JavaClass.ACTION_VIEW, 'geo:38.899533,-77.036476');

//打开网页

Call_URI(TJIntent.JavaClass.ACTION_VIEW, 'www.baidu.com');

//发送电子邮件

Call_URI(TJIntent.JavaClass.ACTION_SENDTO, 'mailto:wr960204@126.com');

//播放音乐

Call_URI(TJIntent.JavaClass.ACTION_VIEW, 'file:///sdcard/download/最炫民族风.mp3');

回到主画面
procedure TForm1.Button3Click(Sender: TObject);
var
  Intent: JIntent;
begin
  Intent:= TJIntent.Create;
  Intent.setAction(TJIntent.JavaClass.ACTION_MAIN);
  Intent.addCategory(TJIntent.JavaClass.CATEGORY_HOME);
  Intent.setFlags(TJIntent.JavaClass.FLAG_ACTIVITY_NEW_TASK);
  MainActivity.startActivity(Intent);
end;

条码扫描(需要安装zxing)

procedure TINVMCForm.btnSCANClick(Sender: TObject);
var
  uri: Jnet_Uri;       //引用Androidapi.JNI.Net
  Intent: JIntent;    //引用Androidapi.JNI.GraphicsContentViewText
  jstr:JString;
begin
  inherited;
  uri := StrToJURI('com.google.zxing.client.android.SCAN');  //引用FMX.Helpers.Android

//Intent := TJIntent.JavaClass.init(jstring(('com.google.zxing.client.android.SCAN');
  Intent := TJIntent.JavaClass.init(StringToJString('com.google.zxing.client.android.SCAN'));
  SharedActivityContext.startActivity(Intent);
end;

function GetZXingIntent: JIntent;

const

GOOGLE_ZXING = 'com.google.zxing.client.android.SCAN';

GOOGLE_ZXING_PACKAGE = 'com.google.zxing.client.android';

begin

Result := TJIntent.JavaClass.init(StringToJString(GOOGLE_ZXING));

Result.setPackage(StringToJString(GOOGLE_ZXING_PACKAGE));

end;

//是否存在对应

function IsIntentCallable(const AIntent: JIntent): Boolean;

var

LJPackageManager: JPackageManager;

begin

Result := False;

if Assigned(AIntent) then

begin

LJPackageManager := SharedActivityContext.getPackageManager;

Result := LJPackageManager.queryIntentActivities(AIntent,

TJPackageManager.JavaClass.MATCH_DEFAULT_ONLY).size <> 0;

end;

end;

获取手机信息

function GetPhoneInfo(): string;

Var

TelephonyManager: JTelephonyManager;
  TelephonyServiceNative: JObject;
begin

result := '';
  TelephonyServiceNative := SharedActivityContext.getSystemService
    (TJContext.JavaClass.TELEPHONY_SERVICE);
  if Assigned(TelephonyServiceNative) then
    TelephonyManager := TJTelephonyManager.Wrap
      ((TelephonyServiceNative as ILocalObject).GetObjectID);
  result := JStringToString(TelephonyManager.getLine1Number);//取得手机号

//TelephonyManager.getDeviceId 取IMEI

//TelephonyManager.getLine1Number 取MSISDN  手机号,大部分SIM卡中不会写入这个信息

//TelephonyManager.getSimSerialNumber 取ICCID

//TelephonyManager.getSubscriberId 取IMSI  运营商实际上是用这个查询的

end;

手机振动

uses  FMX.Helpers.Android,  Androidapi.JNI.App,  Androidapi.JNI.Os,  Androidapi.JNIBridge, FMX.StdCtrls;

procedure TForm1.Button2Click(Sender: TObject);

function GetVibratorArray(const AintArr:array of int64):TJavaArray<int64>;//震动规律函数
var
  Lindex:integer;
begin
  Result:=TJavaArray<int64>.Create(Length(AintArr));
  for Lindex:=Low(AintArr) to High(AintArr) do
      Result.Items [Lindex]:= AintArr[Lindex];
end;
var
   LVibrator:JVibrator;

LJavaArray:TJavaArray<int64>;
begin
   LVibrator:=TJVibrator.Wrap((SharedActivity.getSystemService(TJActivity.javaClass.VIBRATOR_SERVICE ) as iLocalObject).GetObjectID );//引用震动

if not LVibrator.hasVibrator then
   begin
     showmessage('手机不支持震动');
     exit;
   end;

LVibrator.vibrate(200);//震动200ms

LVibrator.cancel ;//立刻停止震动

LJavaArray:=GetVibratorArray([200,1000,3000,5000]);//调用震动规律
   LVibrator.vibrate(LJavaArray,-1);//不重复,  震动一 次

LJavaArray:=GetVibratorArray([200,1000,3000,5000]);//调用震动规律
   LVibrator.vibrate(LJavaArray,0);//v不停重复,大于0的参数,可以指定震动次数
end;

网络传送文件(类似Server/Client)

TTetheringManager|设备管理、TTetheringAppProfile|文件发送

蓝牙

System.Bluetooth单元中主要包含一下几个类

TBluetoothManager、TBluetoothDeviceList、TBluetoothAdapter、TBluetoothDevice、TBluetoothService、
TBluetoothServiceList、TBluetoothSocket

TBluetoothManager是蓝牙管理器,用于蓝牙设备管理,包括发现蓝牙设备,获取配对设备,处理远程配对请求等功能

TBluetoothDeviceList是蓝牙设备列表,TBluetoothDeviceList = class(TObjectList<TBluetoothDevice>),可以通过TBluetoothManager.GetPairedDevices获得配对设备列表

TBluetoothAdapter本机蓝牙设备,实现配对、取消配对等功能,可通过TBluetoothManager.CurrentAdapter得到当前蓝牙设备

TBluetoothDevice远端蓝牙设备,每个远端设备可以提供若干个服务(TBluetoothService),

TBluetoothService远端蓝牙设备服务,包括服务名和UUID

TBluetoothServiceList服务列表 = class(TList<TBluetoothService>);可通过TBluetoothDevice.GetServices获得远端设备服务列表

TBluetoothSocket蓝牙通讯套接字,通过 TBluetoothDevice.CreateClientSocket(StringToGUID(ServiceGUI), True/False)创建

TimeEdit1: TTimeEdit;//时间选择

HorzScrollBox1: THorzScrollBox;横拉组件

MultiView1: TMultiView;//多余视图(Mode主明细表,可更改弹出方式)

EMSProvider: TEMSProvider;//企业移动服务

BBAS Client(组件组TKinveyProvider、TParseProvider);移动客户端数据连接组件

TabItem1: TTabItem;//多页

退出键不退出程序

procedure TPForm.FormKeyUp(Sender: TObject; var Key: Word; var KeyChar: Char;

Shift: TShiftState);

begin

if Key = vkHardwareBack then

begin

{$IFDEF ANDROID}

MessageDlg('确认退出吗?', System.UITypes.TMsgDlgType.mtInformation,

[

System.UITypes.TMsgDlgBtn.mbYes,

//System.UITypes.TMsgDlgBtn.mbNo,

System.UITypes.TMsgDlgBtn.mbCancel

], 0, System.UITypes.TMsgDlgBtn.mbCancel,

procedure(const AResult: TModalResult)

begin

if AResult = mrYES then

MainActivity.finish; { 退出程序 }   // use FMX.Platform.Android

end);

{$ENDIF ANDROID}

//close;

Key := 0;

exit;

end;

end;

Application.FormFactor.Orientations := [TFormOrientation.Landscape]; //坚屏

Application.FormFactor.Orientations := [TFormOrientation.Portrait];//横屏

当前网络状态(Androidapi.JNI.Network.pas)

IsConnected|连接,IsWiFiConnected|Wifi是否连接,IsMobileConnected|移动网络是否连接

剪贴版FClipboardService: IFMXClipboardService;

TPlatformServices.Current.SupportsPlatformService(IFMXClipboardService,    IInterface(FClipboardService));

FClipboardService.SetClipboard(Tvalue(Edit1.Text));  //复制

FClipboardService.GetClipboard.ToString;  //粘贴

键盘FService: IFMXVirtualKeyboardToolbarService;

if TPlatformServices.Current.SupportsPlatformService (IFMXVirtualKeyboardToolbarService, IInterface(FService)) then

begin

FService.SetToolbarEnabled(true);

FService.SetHideKeyboardButtonVisibility(true);

end;

添加桌面快捷方式

procedure Tform1.Button1Click(Sender: TObject);

{$IFDEF ANDROID}

var

ShortcutIntent: JIntent;

addIntent: JIntent;

wIconIdentifier : integer;

wIconResource : JIntent_ShortcutIconResource;

{$ENDIF}

begin

{$IFDEF ANDROID}

ShortcutIntent := TJIntent.JavaClass.init(SharedActivityContext, SharedActivityContext.getClass);

ShortcutIntent.setAction(TJIntent.JavaClass.ACTION_MAIN);

addIntent := TJIntent.Create;

addIntent.putExtra(TJIntent.JavaClass.EXTRA_SHORTCUT_INTENT, TJParcelable.Wrap((shortcutIntent as ILocalObject).GetObjectID));

addIntent.putExtra(TJIntent.JavaClass.EXTRA_SHORTCUT_NAME, StringToJString(Application.Title));

addIntent.setAction(StringToJString('com.android.launcher.action.INSTALL_SHORTCUT'));

// get icon resource identifier

wIconIdentifier := SharedActivity.getResources.getIdentifier(StringToJString('ic_launcher'), StringToJString('drawable'), StringToJString('com.embarcadero.Project1'));

wIconResource := TJIntent_ShortcutIconResource.JavaClass.fromContext(SharedActivityContext, wIconIdentifier);

// set icon for shortcut

addIntent.putExtra(TJIntent.JavaClass.EXTRA_SHORTCUT_ICON_RESOURCE, TJParcelable.Wrap((wIconResource as ILocalObject).GetObjectID));

SharedActivityContext.sendBroadcast(addIntent);

{$ENDIF}

end;

截取屏幕图片

function MakeScaleScreenshot(Sender: TControl): TBitmap;

function GetScreenScale: Single;

var

ScreenService: IFMXScreenService;

begin

Result := 1;

if TPlatformServices.Current.SupportsPlatformService(IFMXScreenService,  IInterface(ScreenService)) then

begin

Result := ScreenService.GetScreenScale;

end;

end;

var

fScreenScale: Single;

begin

fScreenScale := GetScreenScale;

Result := TBitmap.Create(Round(Sender.Width * fScreenScale),

Round(Sender.Height * fScreenScale));

Result.Clear(0);

if Result.Canvas.BeginScene then

try

Sender.PaintTo(Result.Canvas, RectF(0, 0, Result.Width, Result.Height));

finally

Result.Canvas.EndScene;

end;

end;

DELPHI XE Android 开发笔记相关推荐

  1. 《ArcGIS Runtime SDK for Android开发笔记》——离在线一体化技术:概述

    1.前言 数据生产和数据展示是常见的两大专业级移动GIS应用场景,这里我们针对数据生产环节的ArcGIS的离在线一体化技术给大家做一个基本的介绍和梳理. 使用ArcGIS离在线一体化技术首先需要以下基 ...

  2. 《ArcGIS Runtime SDK for Android开发笔记》——离在线一体化技术:离线矢量数据同步...

    1.前言 上一篇文章中我们实现了离线要素的编辑操作,这一篇中主要介绍离在线一体化技术中最后一个环节离线数据的同步功能,通过对数据的上传,服务器端的版本化管理,实现数据生产管理的整个流程. 转载请注明出 ...

  3. 《ArcGIS Runtime SDK for Android开发笔记》——离在线一体化技术:离线矢量数据编辑...

    1.前言 在上一篇我们已经实现了离线地理数据库的下载,这一篇我们着重介绍离线数据库的加载与编辑. 由于ArcGIS Runtime SDK for Android 10.2.X版本并没提供要素绘制功能 ...

  4. 《ArcGIS Runtime SDK for Android开发笔记》——离在线一体化技术:离线矢量数据下载...

    1.前言 1.1.环境准备: ArcGIS for Desktop 10.4.1(10.2.1以上版本即可) ArcGIS for Server 10.4.1 (10.2.1以上版本即可) Postg ...

  5. 《ArcGIS Runtime SDK for Android开发笔记》——(7)、示例代码arcgis-runtime-samples-android的使用...

    1.前言 学习ArcGIS Runtime SDK开发,其实最推荐的学习方式是直接看官方的教程.示例代码和帮助文档,因为官方的示例一般来说都是目前技术最新,也是最详尽的.对于ArcGIS Runtim ...

  6. 《ArcGIS Runtime SDK for Android开发笔记》

    开发笔记之基础教程 ArcGIS Runtime SDK for Android 各版本下载地址 <ArcGIS Runtime SDK for Android开发笔记>--(1).And ...

  7. Android开发笔记(序)写在前面的目录

    知识点分类 一方面写写自己走过的弯路掉进去的坑,避免以后再犯:另一方面希望通过分享自己的经验教训,与网友互相切磋,从而去芜存菁进一步提升自己的水平.因此博主就想,入门的东西咱就不写了,人不能老停留在入 ...

  8. Android开发笔记(一百七十九)避免方法数过多的问题

    一个大规模的App工程,往往引入了数量繁多的第三方开发库,其中既有官方的Jetpack库,也有第三方厂商的开源包.有时候运行这种App会报错"Cannot fit requested cla ...

  9. Android开发笔记(一百七十八)更安全的数据仓库DataStore

    虽然SharedPreferences用起来比较方便,但是在一些特殊场景会产生问题.比如共享参数保存的数据较多时,初始化共享参数会把整个文件加载进内存,加载耗时可能导致主线程堵塞.又如调用apply方 ...

最新文章

  1. MySQL分库分表环境下全局ID生成方案
  2. 如何用纯 CSS 创作一个摇摇晃晃的 loader
  3. Java实现反向输出链表
  4. 【Android开发学习笔记之一】5大布局方式详解
  5. Windows7IIS7.5部署Discuz全攻略
  6. datagrid中使用dropdownlist编辑模版时遇到问题
  7. Ubuntu上可使用的15个桌面环境
  8. 100道Java中高级面试题汇总+详细拆解
  9. LuoguP2680 运输计划
  10. MySQL(一):MySQL中的事务
  11. PHP的HashTable实现
  12. TOP100summit:【分享实录-QQ空间】10亿级直播背后的技术优化
  13. sublime配置python开发环境_【教程】把Sublime Text 2用作Python的IDE去实现Python的开发...
  14. mui项目php,基于h5+的app 开发介绍、hui、mui介绍、项目部署
  15. Win10系统无法使用VGAPlayer软件播放asf格式和VGA文件
  16. 腾讯互娱AMS | 我的打包我做主——浅析前端构建
  17. java面试题2019最新
  18. 扒一扒Kotlin协程的底裤
  19. 开题报告:基于java在线教育视频学习点播系统 毕业设计论文开题报告模板
  20. hexo 添加图片,音乐,链接,视频

热门文章

  1. XenApp负载管理规则列表
  2. 浪潮服务器安装文档,浪潮服务器系统安装.doc
  3. java家用电器springboot家电销售网站管理系统
  4. CSS文字前面有不同颜色的圆
  5. 量化交易 学习笔记
  6. 使用kindeditor插件选择字体乱码
  7. 科技项目进行验收测试有什么注意事项?验收测试报告费用标准
  8. 将Word文档转换为PDF时出现“PDFmaker文件遗失,要在修复模式下运行安装程序吗?”的提示
  9. Error (176310): Can't place multiple pins assigned to pin location Pin_F16 (IOPAD_X41_Y19_N14)关于nCEO
  10. 联想i微型计算机怎么拆,联想B325I一体机怎么拆