123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353 |
- {*******************************************************}
- { }
- { Helpers for Android }
- { }
- { Copyright (C) 2020 KngStr }
- { }
- { Some Code from }
- { Kastri Free of DelphiWorlds }
- { QDAC of swish }
- { Thanks }
- { }
- {*******************************************************}
- unit ksAndroid.Helpers;
- interface
- uses
- System.SysUtils,
- Androidapi.JNI.GraphicsContentViewText, Androidapi.JNI.App,
- Androidapi.JNI.JavaTypes, Androidapi.JNI.Net;
- type
- TAndroidHelperEx = record
- private
- class function GetJActivity: JActivity; static;
- class function GetJContext: JContext; static;
- class function GetJActivityManager: JActivityManager; static;
- public
- const
- ICE_CREAM_SANDWICH = 14;
- ICE_CREAM_SANDWICH_MR1 = 15;
- JELLY_BEAN = 16;
- JELLY_BEAN_MR1 = 17;
- JELLY_BEAN_MR2 = 18;
- KITKAT = 19;
- KITKAT_MR1 = 20;
- LOLLIPOP = 21;
- LOLLIPOP_MR1 = 22;
- MARSHMALLOW = 23;
- NOUGAT = 24;
- NOUGAT_MR1 = 25;
- OREO = 26;
- OREO_MR1 = 27;
- PIE = 28;
- Q = 29;
- /// <summary>
- /// Checks if both build and target are greater or equal to the tested value
- /// </summary>
- class function CheckBuildAndTarget(const AValue: Integer): Boolean; static;
- /// <summary>
- /// Returns the equivalent of "AndroidClass.class"
- /// </summary>
- class function GetClass(const APackageClassName: string): Jlang_Class; static;
- /// <summary>
- /// Returns the application default icon ID
- /// </summary>
- class function GetDefaultIconID: Integer; static;
- /// <summary>
- /// Returns a URI to the notification sound
- /// </summary>
- class function GetDefaultNotificationSound: Jnet_Uri; static;
- /// <summary>
- /// Returns target Sdk version
- /// </summary>
- class function GetTargetSdkVersion: Integer; static;
- /// <summary>
- /// Returns installed Sdk version
- /// </summary>
- class function GetBuildSdkVersion: Integer; static;
- /// <summary>
- /// Returns whether the activity is running foreground
- /// </summary>
- /// <remarks>
- /// Useful from within a service to determine whether or not the service needs to run in foreground mode
- /// </remarks>
- class function IsActivityForeground: Boolean; static;
- /// <summary>
- /// Converts file to uri, using FileProvider if target API >= 24
- /// </summary>
- /// <remarks>
- /// Use this only when accessing files with an "external" URI
- /// </remarks>
- class function UriFromFile(const AFile: JFile; const AAuthority: string = ''): Jnet_Uri; overload; static;
- /// <summary>
- /// Converts filename to uri, using FileProvider if target API >= 24
- /// </summary>
- /// <remarks>
- /// Use this only when accessing files with an "external" URI
- /// </remarks>
- class function UriFromFile(const AFileName: string; const AAuthority: string = ''): Jnet_Uri; overload; static;
- /// <summary>Returns Java Application Context</summary>
- class property Context: JContext read GetJContext;
- /// <summary>Returns Java Application Activity</summary>
- /// <remarks>An exception will be launched if there is no activity, for example a Service</remarks>
- class property Activity: JActivity read GetJActivity;
- /// <summary>Returns Java Application Activity Manager</summary>
- class property ActivityManager: JActivityManager read GetJActivityManager;
- /// <remarks>Need reorder tasks permission</remarks>
- class procedure BringAppToFront; static;
- /// <remarks>Need reorder tasks permission</remarks>
- class procedure SendAppToBack; static;
- /// <summary>Call a Java Activity</summary>
- class function StartActivity(Intent: JIntent; const Code: Integer = -1): Boolean; static;
- /// <summary>Returns Application package name</summary>
- class function GetPackageName: string; static;
- /// <summary>Returns MimeType from filename</summary>
- class function GetMimeType(AFileName: string): JString; static;
- /// <summary>Checks if there is at least one application capable of receiving the intent.</summary>
- class function HasAssocApp(const URI: string): Boolean; overload; static;
- /// <summary>Checks if there is at least one application capable of receiving the intent.</summary>
- class function HasAssocApp(const Intent: JIntent): Boolean; overload; static;
- /// <summary>Install an android package: xxx.apk</summary>
- /// <remarks>
- /// <uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES"/>
- /// </remarks>
- class function InstallPackage(const AFileName: string; const AAuthority: string = ''): Boolean; static;
- /// <summary>Check if an application is installed</summary>
- class function IsAppInstalled(const APackage: string): Boolean; static;
- /// <summary>Add/Cear FLAG_KEEP_SCREEN_ON</summary>
- class function KeepScreen(AOn: Boolean): Boolean; static;
- end;
- implementation
- uses
- Androidapi.JNIBridge, Androidapi.JNI.Os, Androidapi.JNI.Support,
- Androidapi.JNI.Media, Androidapi.JNI.Provider, Androidapi.JNI.Webkit,
- FMX.Helpers.Android, Androidapi.Helpers;
- { TAndroidHelperEx }
- class procedure TAndroidHelperEx.BringAppToFront;
- begin
- ActivityManager.moveTaskToFront(Activity.getTaskId, TJIntent.JavaClass.FLAG_ACTIVITY_NEW_TASK);
- end;
- class function TAndroidHelperEx.CheckBuildAndTarget(const AValue: Integer): Boolean;
- begin
- Result := (GetBuildSdkVersion >= AValue) and (GetTargetSdkVersion >= AValue);
- end;
- class function TAndroidHelperEx.GetBuildSdkVersion: Integer;
- begin
- Result := TJBuild_VERSION.JavaClass.SDK_INT;
- end;
- class function TAndroidHelperEx.GetClass(const APackageClassName: string): Jlang_Class;
- begin
- Result := TJLang_Class.JavaClass.forName(StringToJString(APackageClassName), True, Context.getClassLoader);
- end;
- class function TAndroidHelperEx.GetDefaultIconID: Integer;
- begin
- Result := Context.getApplicationInfo.icon;
- end;
- class function TAndroidHelperEx.GetDefaultNotificationSound: Jnet_Uri;
- begin
- Result := TJRingtoneManager.JavaClass.getDefaultUri(TJRingtoneManager.JavaClass.TYPE_NOTIFICATION);
- end;
- class function TAndroidHelperEx.GetJActivity: JActivity;
- begin
- Result :=
- {$IF CompilerVersion > 27}
- TAndroidHelper.Activity
- {$ELSE}
- SharedActivity
- {$ENDIF}
- end;
- class function TAndroidHelperEx.GetJActivityManager: JActivityManager;
- var
- AService: JObject;
- begin
- AService := Context.getSystemService(TJContext.JavaClass.ACTIVITY_SERVICE);
- Result := TJActivityManager.Wrap((AService as ILocalObject).GetObjectID);
- end;
- class function TAndroidHelperEx.GetJContext: JContext;
- begin
- Result :=
- {$IF CompilerVersion > 27}
- TAndroidHelper.Context;
- {$ELSE}
- SharedActivityContext;
- {$ENDIF}
- end;
- class function TAndroidHelperEx.GetMimeType(AFileName: string): JString;
- var
- LExt: string;
- LTypeMap: JMimeTypeMap;
- begin
- Result := nil;
- if AFileName = '' then
- Exit;
- LExt := LowerCase(ExtractFileExt(AFileName));
- if Length(LExt) < 2 then
- Exit;
- LExt := Copy(LExt, 1);
- LTypeMap := TJMimeTypeMap.JavaClass.getSingleton();
- if LTypeMap = nil then
- Exit;
- Result := LTypeMap.getMimeTypeFromExtension(StringToJString(LExt));
- end;
- class function TAndroidHelperEx.GetPackageName: string;
- begin
- Result := JStringToString(Context.getPackageName);
- end;
- class function TAndroidHelperEx.GetTargetSdkVersion: Integer;
- var
- LApplicationInfo: JApplicationInfo;
- begin
- LApplicationInfo := Context.getPackageManager.getApplicationInfo(Context.getPackageName, 0);
- Result := LApplicationInfo.targetSdkVersion;
- end;
- class function TAndroidHelperEx.HasAssocApp(const Intent: JIntent): Boolean;
- begin
- Result := Activity.getPackageManager.queryIntentActivities(Intent,
- TJPackageManager.JavaClass.MATCH_DEFAULT_ONLY).size > 0;
- end;
- class function TAndroidHelperEx.HasAssocApp(const URI: string): Boolean;
- var
- Intent: JIntent;
- begin
- Result := False;
- Intent := TJIntent.Create;
- Intent.setData(TJnet_Uri.JavaClass.parse(StringToJString(URI)));
- Intent.setAction(StringToJString('android.intent.action.VIEW'));
- Result := HasAssocApp(Intent);
- end;
- class function TAndroidHelperEx.InstallPackage(const AFileName, AAuthority: string): Boolean;
- var
- LIntent: JIntent;
- begin
- Result := False;
- if Trim(AFileName) = '' then
- Exit;
- LIntent := TJIntent.Create;
- if CheckBuildAndTarget(OREO) then
- LIntent.setAction(TJIntent.JavaClass.ACTION_INSTALL_PACKAGE)
- else
- LIntent.setAction(TJIntent.JavaClass.ACTION_VIEW);
- // 没有这个也可以安装成功,但是安装成功后的成功页面,也就是,完成/打开 会无法显示
- LIntent.addFlags(TJIntent.JavaClass.FLAG_ACTIVITY_NEW_TASK);
- LIntent.setDataAndType(UriFromFile(AFileName, AAuthority),
- StringToJString('application/vnd.android.package-archive'));
- LIntent.addFlags(TJIntent.JavaClass.FLAG_GRANT_READ_URI_PERMISSION);
- Result := StartActivity(LIntent);
- end;
- class function TAndroidHelperEx.IsActivityForeground: Boolean;
- var
- LService: JObject;
- LRunningApps: JList;
- LAppInfo: JActivityManager_RunningAppProcessInfo;
- I: Integer;
- begin
- Result := False;
- LService := Context.getSystemService(TJContext.JavaClass.ACTIVITY_SERVICE);
- LRunningApps := TJActivityManager.Wrap(TAndroidHelper.JObjectToID(LService)).getRunningAppProcesses;
- for I := 0 to LRunningApps.size - 1 do begin
- LAppInfo := TJActivityManager_RunningAppProcessInfo.Wrap(TAndroidHelper.JObjectToID(LRunningApps.get(I)));
- if LAppInfo.importance = 100 then begin
- if LAppInfo.importanceReasonComponent <> nil then begin
- if LAppInfo.importanceReasonComponent.getPackageName.equals(Context.getPackageName) then
- Exit(True);
- end
- else if LRunningApps.size = 1 then
- Exit(True);
- end;
- end;
- end;
- class function TAndroidHelperEx.IsAppInstalled(const APackage: string): Boolean;
- begin
- Result := False;
- try
- //只有异常是可靠的,返回值判定不对
- Result := Context.getPackageManager.getPackageInfo(StringToJString(APackage),
- TJPackageManager.JavaClass.GET_ACTIVITIES) = nil;
- Result := True;
- except
- end;
- end;
- class function TAndroidHelperEx.KeepScreen(AOn: Boolean): Boolean;
- begin
- CallInUIThreadAndWaitFinishing(
- procedure begin
- if AOn then
- SharedActivity.getWindow.addFlags(
- TJWindowManager_LayoutParams.JavaClass.FLAG_KEEP_SCREEN_ON)
- else
- SharedActivity.getWindow.clearFlags(
- TJWindowManager_LayoutParams.JavaClass.FLAG_KEEP_SCREEN_ON);
- end);
- end;
- class procedure TAndroidHelperEx.SendAppToBack;
- begin
- //SharedActivityManager.moveTaskToBack(Activity.getTaskId, TJIntent.JavaClass.FLAG_ACTIVITY_NEW_TASK);
- Activity.moveTaskToBack(True);
- end;
- class function TAndroidHelperEx.StartActivity(Intent: JIntent; const Code: Integer): Boolean;
- begin
- Result := False;
- //Checks if there is at least one application capable of receiving the intent.
- if Activity.getPackageManager.queryIntentActivities(Intent,
- TJPackageManager.JavaClass.MATCH_DEFAULT_ONLY).size > 0 then begin
- if Code = -1 then
- Activity.startActivity(Intent)
- else
- Activity.startActivityForResult(Intent, Code);
- Result := True;
- end;
- end;
- class function TAndroidHelperEx.UriFromFile(const AFile: JFile; const AAuthority: string): Jnet_Uri;
- var
- LAuthority: JString;
- begin
- if CheckBuildAndTarget(NOUGAT) then begin
- if AAuthority <> '' then
- LAuthority := StringToJString(AAuthority)
- else
- LAuthority := Context.getApplicationContext.getPackageName.concat(StringToJString('.fileprovider'));
- Result := TJFileProvider.JavaClass.getUriForFile(Context, LAuthority, AFile);
- end
- else
- Result := TJnet_uri.JavaClass.fromFile(AFile);
- end;
- class function TAndroidHelperEx.UriFromFile(const AFileName, AAuthority: string): Jnet_Uri;
- begin
- Result := UriFromFile(TJFile.JavaClass.init(StringToJString(AFileName)), AAuthority);
- end;
- end.
|