DELPHI XE Android 开发笔记

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;

  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值