ksAndroid.Helpers.pas 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310
  1. {*******************************************************}
  2. { }
  3. { Helpers for Android }
  4. { }
  5. { Copyright (C) 2020 KngStr }
  6. { }
  7. { Some Code from }
  8. { Kastri Free of DelphiWorlds }
  9. { QDAC of swish }
  10. { Thanks }
  11. { }
  12. {*******************************************************}
  13. unit ksAndroid.Helpers;
  14. interface
  15. uses
  16. Androidapi.JNI.GraphicsContentViewText, Androidapi.JNI.App,
  17. Androidapi.JNI.JavaTypes, Androidapi.JNI.Net;
  18. type
  19. TAndroidHelperEx = record
  20. private
  21. class function GetJActivity: JActivity; static;
  22. class function GetJContext: JContext; static;
  23. class function GetJActivityManager: JActivityManager; static;
  24. public
  25. const
  26. ICE_CREAM_SANDWICH = 14;
  27. ICE_CREAM_SANDWICH_MR1 = 15;
  28. JELLY_BEAN = 16;
  29. JELLY_BEAN_MR1 = 17;
  30. JELLY_BEAN_MR2 = 18;
  31. KITKAT = 19;
  32. KITKAT_MR1 = 20;
  33. LOLLIPOP = 21;
  34. LOLLIPOP_MR1 = 22;
  35. MARSHMALLOW = 23;
  36. NOUGAT = 24;
  37. NOUGAT_MR1 = 25;
  38. OREO = 26;
  39. OREO_MR1 = 27;
  40. PIE = 28;
  41. Q = 29;
  42. /// <summary>
  43. /// Checks if both build and target are greater or equal to the tested value
  44. /// </summary>
  45. class function CheckBuildAndTarget(const AValue: Integer): Boolean; static;
  46. /// <summary>
  47. /// Returns the equivalent of "AndroidClass.class"
  48. /// </summary>
  49. class function GetClass(const APackageClassName: string): Jlang_Class; static;
  50. /// <summary>
  51. /// Returns the application default icon ID
  52. /// </summary>
  53. class function GetDefaultIconID: Integer; static;
  54. /// <summary>
  55. /// Returns a URI to the notification sound
  56. /// </summary>
  57. class function GetDefaultNotificationSound: Jnet_Uri; static;
  58. /// <summary>
  59. /// Returns target Sdk version
  60. /// </summary>
  61. class function GetTargetSdkVersion: Integer; static;
  62. /// <summary>
  63. /// Returns installed Sdk version
  64. /// </summary>
  65. class function GetBuildSdkVersion: Integer; static;
  66. /// <summary>
  67. /// Returns whether the activity is running foreground
  68. /// </summary>
  69. /// <remarks>
  70. /// Useful from within a service to determine whether or not the service needs to run in foreground mode
  71. /// </remarks>
  72. class function IsActivityForeground: Boolean; static;
  73. /// <summary>
  74. /// Converts file to uri, using FileProvider if target API >= 24
  75. /// </summary>
  76. /// <remarks>
  77. /// Use this only when accessing files with an "external" URI
  78. /// </remarks>
  79. class function UriFromFile(const AFile: JFile): Jnet_Uri; static;
  80. /// <summary>
  81. /// Converts filename to uri, using FileProvider if target API >= 24
  82. /// </summary>
  83. /// <remarks>
  84. /// Use this only when accessing files with an "external" URI
  85. /// </remarks>
  86. class function UriFromFileName(const AFileName: string): Jnet_Uri; static;
  87. /// <summary>Returns Java Application Context</summary>
  88. class property Context: JContext read GetJContext;
  89. /// <summary>Returns Java Application Activity</summary>
  90. /// <remarks>An exception will be launched if there is no activity, for example a Service</remarks>
  91. class property Activity: JActivity read GetJActivity;
  92. /// <summary>Returns Java Application Activity Manager</summary>
  93. class property ActivityManager: JActivityManager read GetJActivityManager;
  94. /// <remarks>Need reorder tasks permission</remarks>
  95. class procedure BringAppToFront; static;
  96. /// <remarks>Need reorder tasks permission</remarks>
  97. class procedure SendAppToBack; static;
  98. /// <summary>Call a Java Activity</summary>
  99. class function StartActivity(Intent: JIntent; const Code: Integer = -1): Boolean; static;
  100. /// <summary>Returns Application package name</summary>
  101. class function GetPackageName: string; static;
  102. /// <summary>Checks if there is at least one application capable of receiving the intent.</summary>
  103. class function HasAssocApp(const URI: string): Boolean; overload; static;
  104. /// <summary>Checks if there is at least one application capable of receiving the intent.</summary>
  105. class function HasAssocApp(const Intent: JIntent): Boolean; overload; static;
  106. /// <summary>Check if an application is installed</summary>
  107. class function IsAppInstalled(const APackage: string): Boolean; static;
  108. /// <summary>Add/Cear FLAG_KEEP_SCREEN_ON</summary>
  109. class function KeepScreen(AOn: Boolean): Boolean; static;
  110. end;
  111. implementation
  112. uses
  113. Androidapi.Helpers, Androidapi.JNIBridge,
  114. Androidapi.JNI.Os, Androidapi.JNI.Support,
  115. Androidapi.JNI.Media, Androidapi.JNI.Provider,
  116. FMX.Helpers.Android;
  117. { TAndroidHelperEx }
  118. class procedure TAndroidHelperEx.BringAppToFront;
  119. begin
  120. ActivityManager.moveTaskToFront(Activity.getTaskId, TJIntent.JavaClass.FLAG_ACTIVITY_NEW_TASK);
  121. end;
  122. class function TAndroidHelperEx.CheckBuildAndTarget(const AValue: Integer): Boolean;
  123. begin
  124. Result := (GetBuildSdkVersion >= AValue) and (GetTargetSdkVersion >= AValue);
  125. end;
  126. class function TAndroidHelperEx.GetBuildSdkVersion: Integer;
  127. begin
  128. Result := TJBuild_VERSION.JavaClass.SDK_INT;
  129. end;
  130. class function TAndroidHelperEx.GetClass(const APackageClassName: string): Jlang_Class;
  131. begin
  132. Result := TJLang_Class.JavaClass.forName(StringToJString(APackageClassName), True, Context.getClassLoader);
  133. end;
  134. class function TAndroidHelperEx.GetDefaultIconID: Integer;
  135. begin
  136. Result := Context.getApplicationInfo.icon;
  137. end;
  138. class function TAndroidHelperEx.GetDefaultNotificationSound: Jnet_Uri;
  139. begin
  140. Result := TJRingtoneManager.JavaClass.getDefaultUri(TJRingtoneManager.JavaClass.TYPE_NOTIFICATION);
  141. end;
  142. class function TAndroidHelperEx.GetJActivity: JActivity;
  143. begin
  144. Result :=
  145. {$IF CompilerVersion > 27}
  146. TAndroidHelper.Activity
  147. {$ELSE}
  148. SharedActivity
  149. {$ENDIF}
  150. end;
  151. class function TAndroidHelperEx.GetJActivityManager: JActivityManager;
  152. var
  153. AService: JObject;
  154. begin
  155. AService := Context.getSystemService(TJContext.JavaClass.ACTIVITY_SERVICE);
  156. Result := TJActivityManager.Wrap((AService as ILocalObject).GetObjectID);
  157. end;
  158. class function TAndroidHelperEx.GetJContext: JContext;
  159. begin
  160. Result :=
  161. {$IF CompilerVersion > 27}
  162. TAndroidHelper.Context;
  163. {$ELSE}
  164. SharedActivityContext;
  165. {$ENDIF}
  166. end;
  167. class function TAndroidHelperEx.GetPackageName: string;
  168. begin
  169. Result := JStringToString(Context.getPackageName);
  170. end;
  171. class function TAndroidHelperEx.GetTargetSdkVersion: Integer;
  172. var
  173. LApplicationInfo: JApplicationInfo;
  174. begin
  175. LApplicationInfo := Context.getPackageManager.getApplicationInfo(Context.getPackageName, 0);
  176. Result := LApplicationInfo.targetSdkVersion;
  177. end;
  178. class function TAndroidHelperEx.HasAssocApp(const Intent: JIntent): Boolean;
  179. begin
  180. Result := TAndroidHelper.Activity.getPackageManager.queryIntentActivities(
  181. Intent, TJPackageManager.JavaClass.MATCH_DEFAULT_ONLY).size > 0;
  182. end;
  183. class function TAndroidHelperEx.HasAssocApp(const URI: string): Boolean;
  184. var
  185. Intent: JIntent;
  186. begin
  187. Result := False;
  188. Intent := TJIntent.Create;
  189. Intent.setData(TJnet_Uri.JavaClass.parse(StringToJString(URI)));
  190. Intent.setAction(StringToJString('android.intent.action.VIEW'));
  191. Result := HasAssocApp(Intent);
  192. end;
  193. class function TAndroidHelperEx.IsActivityForeground: Boolean;
  194. var
  195. LService: JObject;
  196. LRunningApps: JList;
  197. LAppInfo: JActivityManager_RunningAppProcessInfo;
  198. I: Integer;
  199. begin
  200. Result := False;
  201. LService := Context.getSystemService(TJContext.JavaClass.ACTIVITY_SERVICE);
  202. LRunningApps := TJActivityManager.Wrap(TAndroidHelper.JObjectToID(LService)).getRunningAppProcesses;
  203. for I := 0 to LRunningApps.size - 1 do
  204. begin
  205. LAppInfo := TJActivityManager_RunningAppProcessInfo.Wrap(TAndroidHelper.JObjectToID(LRunningApps.get(I)));
  206. if LAppInfo.importance = 100 then
  207. begin
  208. if LAppInfo.importanceReasonComponent <> nil then
  209. begin
  210. if LAppInfo.importanceReasonComponent.getPackageName.equals(Context.getPackageName) then
  211. Exit(True);
  212. end
  213. else if LRunningApps.size = 1 then
  214. Exit(True);
  215. end;
  216. end;
  217. end;
  218. class function TAndroidHelperEx.IsAppInstalled(const APackage: string): Boolean;
  219. begin
  220. Result := False;
  221. try
  222. //只有异常是可靠的,返回值判定不对
  223. Result := Context.getPackageManager.getPackageInfo(StringToJString(S),
  224. TJPackageManager.JavaClass.GET_ACTIVITIES) = nil;
  225. Result := True;
  226. except
  227. end;
  228. end;
  229. class function TAndroidHelperEx.KeepScreen(AOn: Boolean): Boolean;
  230. begin
  231. CallInUIThreadAndWaitFinishing(
  232. procedure
  233. begin
  234. if AOn then
  235. SharedActivity.getWindow.addFlags(
  236. TJWindowManager_LayoutParams.JavaClass.FLAG_KEEP_SCREEN_ON)
  237. else
  238. SharedActivity.getWindow.clearFlags(
  239. TJWindowManager_LayoutParams.JavaClass.FLAG_KEEP_SCREEN_ON);
  240. end);
  241. end;
  242. class procedure TAndroidHelperEx.SendAppToBack;
  243. begin
  244. //SharedActivityManager.moveTaskToBack(Activity.getTaskId, TJIntent.JavaClass.FLAG_ACTIVITY_NEW_TASK);
  245. Activity.moveTaskToBack(True);
  246. end;
  247. class function TAndroidHelperEx.StartActivity(Intent: JIntent; const Code: Integer): Boolean;
  248. begin
  249. Result := False;
  250. //Checks if there is at least one application capable of receiving the intent.
  251. if Activity.getPackageManager.queryIntentActivities(Intent,
  252. TJPackageManager.JavaClass.MATCH_DEFAULT_ONLY).size > 0 then begin
  253. if Code = -1 then
  254. Activity.startActivity(Intent)
  255. else
  256. Activity.startActivityForResult(Intent, Code);
  257. Result := True;
  258. end;
  259. end;
  260. class function TAndroidHelperEx.UriFromFile(const AFile: JFile): Jnet_Uri;
  261. var
  262. LAuthority: JString;
  263. begin
  264. if CheckBuildAndTarget(NOUGAT) then
  265. begin
  266. LAuthority := StringToJString(JStringToString(Context.getApplicationContext.getPackageName) + '.fileprovider');
  267. Result := TJFileProvider.JavaClass.getUriForFile(Context, LAuthority, AFile);
  268. end
  269. else
  270. Result := TJnet_uri.JavaClass.fromFile(AFile);
  271. end;
  272. class function TAndroidHelperEx.UriFromFileName(const AFileName: string): Jnet_Uri;
  273. begin
  274. Result := UriFromFile(TJFile.JavaClass.init(StringToJString(AFileName)));
  275. end;
  276. end.