|
@@ -0,0 +1,209 @@
|
|
|
+{*******************************************************}
|
|
|
+{ }
|
|
|
+{ Helpers for Android }
|
|
|
+{ }
|
|
|
+{ Copyright (C) 2020 KngStr }
|
|
|
+{ }
|
|
|
+{ Some Code from Kastri Free of DelphiWorlds, Thanks }
|
|
|
+{ }
|
|
|
+{*******************************************************}
|
|
|
+
|
|
|
+unit ksAndroid.Helpers;
|
|
|
+
|
|
|
+interface
|
|
|
+
|
|
|
+uses
|
|
|
+ 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;
|
|
|
+ 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): Jnet_Uri; 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 UriFromFileName(const AFileName: string): Jnet_Uri; 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 Application package name</summary>
|
|
|
+ class function GetPackageName: string; static;
|
|
|
+ end;
|
|
|
+
|
|
|
+implementation
|
|
|
+
|
|
|
+uses
|
|
|
+ Androidapi.Helpers,
|
|
|
+ Androidapi.JNI.Os, Androidapi.JNI.Support,
|
|
|
+ Androidapi.JNI.Media, Androidapi.JNI.Provider;
|
|
|
+
|
|
|
+{ TAndroidHelperEx }
|
|
|
+
|
|
|
+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, TAndroidHelper.Context.getClassLoader);
|
|
|
+end;
|
|
|
+
|
|
|
+class function TAndroidHelperEx.GetDefaultIconID: Integer;
|
|
|
+begin
|
|
|
+ Result := TAndroidHelper.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.GetJContext: JContext;
|
|
|
+begin
|
|
|
+ Result :=
|
|
|
+{$IF CompilerVersion > 27}
|
|
|
+ TAndroidHelper.Context;
|
|
|
+{$ELSE}
|
|
|
+ SharedActivityContext;
|
|
|
+{$ENDIF}
|
|
|
+end;
|
|
|
+
|
|
|
+class function TAndroidHelperEx.GetPackageName: string;
|
|
|
+begin
|
|
|
+ Result := JStringToString(Context.getPackageName);
|
|
|
+end;
|
|
|
+
|
|
|
+class function TAndroidHelperEx.GetTargetSdkVersion: Integer;
|
|
|
+var
|
|
|
+ LApplicationInfo: JApplicationInfo;
|
|
|
+begin
|
|
|
+ LApplicationInfo := TAndroidHelper.Context.getPackageManager.getApplicationInfo(TAndroidHelper.Context.getPackageName, 0);
|
|
|
+ Result := LApplicationInfo.targetSdkVersion;
|
|
|
+end;
|
|
|
+
|
|
|
+class function TAndroidHelperEx.IsActivityForeground: Boolean;
|
|
|
+var
|
|
|
+ LService: JObject;
|
|
|
+ LRunningApps: JList;
|
|
|
+ LAppInfo: JActivityManager_RunningAppProcessInfo;
|
|
|
+ I: Integer;
|
|
|
+begin
|
|
|
+ Result := False;
|
|
|
+ LService := TAndroidHelper.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(TAndroidHelper.Context.getPackageName) then
|
|
|
+ Exit(True);
|
|
|
+ end
|
|
|
+ else if LRunningApps.size = 1 then
|
|
|
+ Exit(True);
|
|
|
+ end;
|
|
|
+ end;
|
|
|
+end;
|
|
|
+
|
|
|
+class function TAndroidHelperEx.UriFromFile(const AFile: JFile): Jnet_Uri;
|
|
|
+var
|
|
|
+ LAuthority: JString;
|
|
|
+begin
|
|
|
+ if CheckBuildAndTarget(NOUGAT) then
|
|
|
+ begin
|
|
|
+ LAuthority := StringToJString(JStringToString(TAndroidHelper.Context.getApplicationContext.getPackageName) + '.fileprovider');
|
|
|
+ Result := TJFileProvider.JavaClass.getUriForFile(TAndroidHelper.Context, LAuthority, AFile);
|
|
|
+ end
|
|
|
+ else
|
|
|
+ Result := TJnet_uri.JavaClass.fromFile(AFile);
|
|
|
+end;
|
|
|
+
|
|
|
+class function TAndroidHelperEx.UriFromFileName(const AFileName: string): Jnet_Uri;
|
|
|
+begin
|
|
|
+ Result := UriFromFile(TJFile.JavaClass.init(StringToJString(AFileName)));
|
|
|
+end;
|
|
|
+
|
|
|
+end.
|