2 * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
4 * Licensed under the Apache License, Version 2.0 (the License);
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an AS IS BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
18 using System.Collections.Generic;
19 using System.ComponentModel;
20 using System.Runtime.InteropServices;
21 using System.Threading.Tasks;
22 using static Interop.ApplicationManager;
24 namespace Tizen.Applications
27 /// This class has the methods and events of the ApplicationManager.
29 /// <since_tizen> 3 </since_tizen>
30 public static class ApplicationManager
32 private const string LogTag = "Tizen.Applications";
33 private static EventHandler<ApplicationLaunchedEventArgs> s_launchedHandler;
34 private static EventHandler<ApplicationTerminatedEventArgs> s_terminatedHandler;
35 private static Interop.ApplicationManager.AppManagerAppContextEventCallback s_applicationChangedEventCallback;
36 private static EventHandler<ApplicationEnabledEventArgs> s_enabledHandler;
37 private static EventHandler<ApplicationDisabledEventArgs> s_disabledHandler;
38 private static Interop.ApplicationManager.AppManagerEventCallback s_eventCallback;
39 private static IntPtr _eventHandle = IntPtr.Zero;
40 private static readonly object s_eventLock = new object();
41 private static readonly object s_applicationChangedEventLock = new object();
44 /// Occurs whenever the installed application is enabled.
46 /// <since_tizen> 3 </since_tizen>
47 public static event EventHandler<ApplicationEnabledEventArgs> ApplicationEnabled
53 if (s_eventCallback == null)
55 RegisterApplicationEvent();
57 s_enabledHandler += value;
64 s_enabledHandler -= value;
65 if (s_enabledHandler == null && s_disabledHandler == null && s_eventCallback != null)
67 UnRegisterApplicationEvent();
68 s_eventCallback = null;
75 /// Occurs whenever the installed application is disabled.
77 /// <since_tizen> 3 </since_tizen>
78 public static event EventHandler<ApplicationDisabledEventArgs> ApplicationDisabled
84 if (s_eventCallback == null)
86 RegisterApplicationEvent();
88 s_disabledHandler += value;
95 s_disabledHandler -= value;
96 if (s_enabledHandler == null && s_disabledHandler == null && s_eventCallback != null)
98 UnRegisterApplicationEvent();
99 s_eventCallback = null;
106 /// Occurs whenever the installed applications get launched.
108 /// <since_tizen> 3 </since_tizen>
109 public static event EventHandler<ApplicationLaunchedEventArgs> ApplicationLaunched
113 lock (s_applicationChangedEventLock)
115 if (s_applicationChangedEventCallback == null)
117 RegisterApplicationChangedEvent();
119 s_launchedHandler += value;
124 lock (s_applicationChangedEventLock)
126 s_launchedHandler -= value;
127 if (s_launchedHandler == null && s_terminatedHandler == null && s_applicationChangedEventCallback != null)
129 UnRegisterApplicationChangedEvent();
130 s_applicationChangedEventCallback = null;
137 /// Occurs whenever the installed applications get terminated.
139 /// <since_tizen> 3 </since_tizen>
140 public static event EventHandler<ApplicationTerminatedEventArgs> ApplicationTerminated
144 lock (s_applicationChangedEventLock)
146 if (s_applicationChangedEventCallback == null)
148 RegisterApplicationChangedEvent();
150 s_terminatedHandler += value;
155 lock (s_applicationChangedEventLock)
157 s_terminatedHandler -= value;
158 if (s_launchedHandler == null && s_terminatedHandler == null && s_applicationChangedEventCallback != null)
160 UnRegisterApplicationChangedEvent();
161 s_applicationChangedEventCallback = null;
168 /// Gets the information of the installed applications asynchronously.
170 /// <returns>The installed application info list.</returns>
171 /// <since_tizen> 3 </since_tizen>
172 public static async Task<IEnumerable<ApplicationInfo>> GetInstalledApplicationsAsync()
174 return await Task.Run(() =>
176 Interop.ApplicationManager.ErrorCode err = Interop.ApplicationManager.ErrorCode.None;
177 List<ApplicationInfo> result = new List<ApplicationInfo>();
179 Interop.ApplicationManager.AppManagerAppInfoCallback cb = (IntPtr infoHandle, IntPtr userData) =>
181 if (infoHandle != IntPtr.Zero)
183 IntPtr clonedHandle = IntPtr.Zero;
184 err = Interop.ApplicationManager.AppInfoClone(out clonedHandle, infoHandle);
185 if (err != Interop.ApplicationManager.ErrorCode.None)
187 Log.Warn(LogTag, "Failed to clone the appinfo. err = " + err);
190 ApplicationInfo app = new ApplicationInfo(clonedHandle);
196 err = Interop.ApplicationManager.AppManagerForeachAppInfo(cb, IntPtr.Zero);
197 if (err != Interop.ApplicationManager.ErrorCode.None)
199 throw ApplicationManagerErrorFactory.GetException(err, "Failed to foreach the appinfo.");
206 /// Terminates the application if it is running on background.
208 /// <param name="app">ApplicationRunningContext object</param>
209 /// <exception cref="ArgumentException">Thrown when failed of invalid argument.</exception>
210 /// <exception cref="UnauthorizedAccessException">Thrown when failed because of permission denied.</exception>
211 /// <exception cref="InvalidOperationException">Thrown when failed because of system error.</exception>
212 /// <privilege>http://tizen.org/privilege/appmanager.kill.bgapp</privilege>
214 /// This function returns after it just sends a request for terminating a background application.
215 /// Platform will decide if the target application could be terminated or not according to the state of the target application.
217 /// <since_tizen> 6 </since_tizen>
218 public static void TerminateBackgroundApplication(ApplicationRunningContext app)
220 ErrorCode err = Interop.ApplicationManager.AppManagerRequestTerminateBgApp(app._contextHandle);
221 if (err != Interop.ApplicationManager.ErrorCode.None)
225 case Interop.ApplicationManager.ErrorCode.InvalidParameter:
226 throw new ArgumentException("Invalid argument.");
227 case Interop.ApplicationManager.ErrorCode.PermissionDenied:
228 throw new UnauthorizedAccessException("Permission denied.");
230 throw new InvalidOperationException("Invalid Operation.");
236 /// Gets the information of the installed applications with the ApplicationInfoFilter asynchronously.
238 /// <param name="filter">Key-value pairs for filtering.</param>
239 /// <returns>The installed application info list.</returns>
240 /// <since_tizen> 3 </since_tizen>
241 public static async Task<IEnumerable<ApplicationInfo>> GetInstalledApplicationsAsync(ApplicationInfoFilter filter)
243 return await Task.Run(() =>
245 List<ApplicationInfo> result = new List<ApplicationInfo>();
247 Interop.ApplicationManager.AppInfoFilterCallback cb = (IntPtr infoHandle, IntPtr userData) =>
249 if (infoHandle != IntPtr.Zero)
251 IntPtr clonedHandle = IntPtr.Zero;
252 Interop.ApplicationManager.ErrorCode err = Interop.ApplicationManager.AppInfoClone(out clonedHandle, infoHandle);
253 if (err != Interop.ApplicationManager.ErrorCode.None)
255 Log.Warn(LogTag, "Failed to clone the appinfo. err = " + err);
258 ApplicationInfo app = new ApplicationInfo(clonedHandle);
270 /// Gets the information of the installed applications with the ApplicationInfoMetadataFilter asynchronously.
272 /// <param name="filter">Key-value pairs for filtering.</param>
273 /// <returns>The installed application info list.</returns>
274 /// <since_tizen> 3 </since_tizen>
275 public static async Task<IEnumerable<ApplicationInfo>> GetInstalledApplicationsAsync(ApplicationInfoMetadataFilter filter)
277 return await Task.Run(() =>
279 List<ApplicationInfo> result = new List<ApplicationInfo>();
281 Interop.ApplicationManager.AppInfoFilterCallback cb = (IntPtr infoHandle, IntPtr userData) =>
283 if (infoHandle != IntPtr.Zero)
285 IntPtr clonedHandle = IntPtr.Zero;
286 Interop.ApplicationManager.ErrorCode err = Interop.ApplicationManager.AppInfoClone(out clonedHandle, infoHandle);
287 if (err != Interop.ApplicationManager.ErrorCode.None)
289 Log.Warn(LogTag, "Failed to clone the appinfo. err = " + err);
292 ApplicationInfo app = new ApplicationInfo(clonedHandle);
304 /// Gets the information of the running applications asynchronously.
306 /// <returns>The application running context list.</returns>
307 /// <since_tizen> 3 </since_tizen>
308 public static async Task<IEnumerable<ApplicationRunningContext>> GetRunningApplicationsAsync()
310 return await Task.Run(() =>
312 Interop.ApplicationManager.ErrorCode err = Interop.ApplicationManager.ErrorCode.None;
313 List<ApplicationRunningContext> result = new List<ApplicationRunningContext>();
315 Interop.ApplicationManager.AppManagerAppContextCallback cb = (IntPtr contextHandle, IntPtr userData) =>
317 if (contextHandle != IntPtr.Zero)
319 IntPtr clonedHandle = IntPtr.Zero;
320 err = Interop.ApplicationManager.AppContextClone(out clonedHandle, contextHandle);
321 if (err != Interop.ApplicationManager.ErrorCode.None)
323 Log.Warn(LogTag, "Failed to clone the app context. err = " + err);
326 ApplicationRunningContext context = new ApplicationRunningContext(clonedHandle);
333 err = Interop.ApplicationManager.AppManagerForeachAppContext(cb, IntPtr.Zero);
334 if (err != Interop.ApplicationManager.ErrorCode.None)
336 throw ApplicationManagerErrorFactory.GetException(err, "Failed to foreach appcontext.");
343 /// Gets the information of the running applications including subapp asynchronously.
345 /// <returns>The application running context list.</returns>
346 /// <since_tizen> 3 </since_tizen>
347 public static async Task<IEnumerable<ApplicationRunningContext>> GetAllRunningApplicationsAsync()
349 return await Task.Run(() =>
351 Interop.ApplicationManager.ErrorCode err = Interop.ApplicationManager.ErrorCode.None;
352 List<ApplicationRunningContext> result = new List<ApplicationRunningContext>();
354 Interop.ApplicationManager.AppManagerAppContextCallback cb = (IntPtr contextHandle, IntPtr userData) =>
356 if (contextHandle != IntPtr.Zero)
358 IntPtr clonedHandle = IntPtr.Zero;
359 err = Interop.ApplicationManager.AppContextClone(out clonedHandle, contextHandle);
360 if (err != Interop.ApplicationManager.ErrorCode.None)
362 Log.Warn(LogTag, "Failed to clone the app context. err = " + err);
365 ApplicationRunningContext context = new ApplicationRunningContext(clonedHandle);
372 err = Interop.ApplicationManager.AppManagerForeachRunningAppContext(cb, IntPtr.Zero);
373 if (err != Interop.ApplicationManager.ErrorCode.None)
375 throw ApplicationManagerErrorFactory.GetException(err, "Failed to foreach appcontext.");
382 /// Gets the information of the specified application with the application ID.
384 /// <param name="applicationId">Application ID.</param>
385 /// <returns>The application info.</returns>
386 /// <since_tizen> 3 </since_tizen>
387 public static ApplicationInfo GetInstalledApplication(string applicationId)
389 IntPtr infoHandle = IntPtr.Zero;
390 Interop.ApplicationManager.ErrorCode err = Interop.ApplicationManager.AppManagerGetAppInfo(applicationId, out infoHandle);
391 if (err != Interop.ApplicationManager.ErrorCode.None)
393 throw ApplicationManagerErrorFactory.GetException(err, "Failed to get the installed application information of " + applicationId + ".");
395 ApplicationInfo app = new ApplicationInfo(infoHandle);
400 /// Returns if the specified application is running or not.
402 /// <param name="applicationId">The application ID.</param>
403 /// <returns>Returns true if the given application is running, otherwise false.</returns>
404 /// <exception cref="ArgumentException">Thrown when the given parameter is invalid.</exception>
405 /// <since_tizen> 3 </since_tizen>
406 public static bool IsRunning(string applicationId)
408 bool isRunning = false;
409 Interop.ApplicationManager.ErrorCode err = Interop.ApplicationManager.AppManagerIsRunning(applicationId, out isRunning);
410 if (err != Interop.ApplicationManager.ErrorCode.None)
412 throw ApplicationManagerErrorFactory.GetException(Interop.ApplicationManager.ErrorCode.InvalidParameter, "Invalid parameter");
418 /// Returns the application id.
420 /// <param name="processId">The application pid.</param>
421 /// <returns>Returns the application id.</returns>
422 /// <exception cref="ArgumentException">Thrown when the given parameter is invalid.</exception>
423 /// <since_tizen> 6 </since_tizen>
424 public static string GetAppId(int processId)
427 Interop.ApplicationManager.ErrorCode err = Interop.ApplicationManager.AppManagerGetAppId(processId, out appid);
428 if (err != Interop.ApplicationManager.ErrorCode.None)
430 throw ApplicationManagerErrorFactory.GetException(err, "fail to get appid(" + processId + ")");
435 private static void RegisterApplicationChangedEvent()
437 Interop.ApplicationManager.ErrorCode err = Interop.ApplicationManager.ErrorCode.None;
438 s_applicationChangedEventCallback = (IntPtr contextHandle, Interop.ApplicationManager.AppContextEvent state, IntPtr userData) =>
440 if (contextHandle == IntPtr.Zero) return;
442 IntPtr clonedHandle = IntPtr.Zero;
443 err = Interop.ApplicationManager.AppContextClone(out clonedHandle, contextHandle);
444 if (err != Interop.ApplicationManager.ErrorCode.None)
446 throw ApplicationManagerErrorFactory.GetException(err, "Failed to register the application context event.");
448 using (ApplicationRunningContext context = new ApplicationRunningContext(clonedHandle))
450 if (state == Interop.ApplicationManager.AppContextEvent.Launched)
452 s_launchedHandler?.Invoke(null, new ApplicationLaunchedEventArgs { ApplicationRunningContext = context });
454 else if (state == Interop.ApplicationManager.AppContextEvent.Terminated)
456 s_terminatedHandler?.Invoke(null, new ApplicationTerminatedEventArgs { ApplicationRunningContext = context });
460 err = Interop.ApplicationManager.AppManagerSetAppContextEvent(s_applicationChangedEventCallback, IntPtr.Zero);
461 if (err != Interop.ApplicationManager.ErrorCode.None)
463 throw ApplicationManagerErrorFactory.GetException(err, "Failed to register the application context event.");
467 private static void UnRegisterApplicationChangedEvent()
469 Interop.ApplicationManager.AppManagerUnSetAppContextEvent();
472 private static void RegisterApplicationEvent()
474 Interop.ApplicationManager.ErrorCode err = Interop.ApplicationManager.ErrorCode.None;
475 err = Interop.ApplicationManager.AppManagerEventCreate(out _eventHandle);
476 if (err != Interop.ApplicationManager.ErrorCode.None)
478 throw ApplicationManagerErrorFactory.GetException(err, "Failed to create the application event handle");
481 err = Interop.ApplicationManager.AppManagerEventSetStatus(_eventHandle, Interop.ApplicationManager.AppManagerEventStatusType.All);
482 if (err != Interop.ApplicationManager.ErrorCode.None)
484 Interop.ApplicationManager.AppManagerEventDestroy(_eventHandle);
485 _eventHandle = IntPtr.Zero;
486 throw ApplicationManagerErrorFactory.GetException(err, "Failed to set the application event");
489 s_eventCallback = (string appType, string appId, Interop.ApplicationManager.AppManagerEventType eventType, Interop.ApplicationManager.AppManagerEventState eventState, IntPtr eventHandle, IntPtr UserData) =>
491 if (eventType == Interop.ApplicationManager.AppManagerEventType.Enable)
493 s_enabledHandler?.Invoke(null, new ApplicationEnabledEventArgs(appId, (ApplicationEventState)eventState));
495 else if (eventType == Interop.ApplicationManager.AppManagerEventType.Disable)
497 s_disabledHandler?.Invoke(null, new ApplicationDisabledEventArgs(appId, (ApplicationEventState)eventState));
500 err = Interop.ApplicationManager.AppManagerSetEventCallback(_eventHandle, s_eventCallback, IntPtr.Zero);
501 if (err != Interop.ApplicationManager.ErrorCode.None)
503 Interop.ApplicationManager.AppManagerEventDestroy(_eventHandle);
504 _eventHandle = IntPtr.Zero;
505 throw ApplicationManagerErrorFactory.GetException(err, "Failed to set the application event callback");
509 private static void UnRegisterApplicationEvent()
511 if (_eventHandle != IntPtr.Zero)
513 Interop.ApplicationManager.AppManagerUnSetEventCallback(_eventHandle);
514 Interop.ApplicationManager.AppManagerEventDestroy(_eventHandle);
515 _eventHandle = IntPtr.Zero;
520 /// Gets the information of the recent applications.
522 /// <returns>Returns a dictionary containing all the recent application info.</returns>
523 /// <exception cref="InvalidOperationException">Thrown when failed because of an invalid operation.</exception>
524 /// <since_tizen> 3 </since_tizen>
525 [EditorBrowsable(EditorBrowsableState.Never)]
526 public static IEnumerable<RecentApplicationInfo> GetRecentApplications()
528 Interop.ApplicationManager.ErrorCode err = Interop.ApplicationManager.ErrorCode.None;
530 List<RecentApplicationInfo> result = new List<RecentApplicationInfo>();
534 err = Interop.ApplicationManager.RuaHistoryLoadDb(out table, out nrows, out ncols);
535 if (err != Interop.ApplicationManager.ErrorCode.None)
537 throw ApplicationManagerErrorFactory.GetException(err, "Failed to load a table for the recent application list.");
540 for (int row = 0; row < nrows; ++row)
542 Interop.ApplicationManager.RuaRec record;
544 err = Interop.ApplicationManager.RuaHistoryGetRecord(out record, table, nrows, ncols, row);
545 if (err != Interop.ApplicationManager.ErrorCode.None)
547 throw ApplicationManagerErrorFactory.GetException(err, "Failed to get record.");
550 RecentApplicationInfo info = new RecentApplicationInfo(record);
554 err = Interop.ApplicationManager.RuaHistoryUnLoadDb(ref table);
555 if (err != Interop.ApplicationManager.ErrorCode.None)
557 throw ApplicationManagerErrorFactory.GetException(err, "Failed to unload a table for the recent application list.");
564 internal static class FilterExtension
566 private const string LogTag = "Tizen.Applications";
567 internal static void Fetch(this ApplicationInfoFilter filter, Interop.ApplicationManager.AppInfoFilterCallback callback)
569 if (filter is ApplicationInfoMetadataFilter)
571 ApplicationInfoMetadataFilter metaFilter = (ApplicationInfoMetadataFilter)filter;
572 metaFilter.Fetch(callback);
576 IntPtr nativeHandle = MakeNativeAppInfoFilter(filter.Filter);
577 if (nativeHandle == IntPtr.Zero)
579 throw ApplicationManagerErrorFactory.NativeFilterHandleIsInvalid();
583 Interop.ApplicationManager.ErrorCode err = Interop.ApplicationManager.AppInfoFilterForeachAppinfo(nativeHandle, callback, IntPtr.Zero);
584 if (err != Interop.ApplicationManager.ErrorCode.None)
586 throw ApplicationManagerErrorFactory.GetException(err, "Failed to get application information list with filter.");
591 Interop.ApplicationManager.AppInfoFilterDestroy(nativeHandle);
595 internal static void Fetch(this ApplicationInfoMetadataFilter filter, Interop.ApplicationManager.AppInfoFilterCallback callback)
597 IntPtr nativeHandle = MakeNativeAppMetadataFilter(filter.Filter);
598 if (nativeHandle == IntPtr.Zero)
600 throw ApplicationManagerErrorFactory.NativeFilterHandleIsInvalid();
604 Interop.ApplicationManager.ErrorCode err = Interop.ApplicationManager.AppInfoMetadataFilterForeach(nativeHandle, callback, IntPtr.Zero);
605 if (err != Interop.ApplicationManager.ErrorCode.None)
607 throw ApplicationManagerErrorFactory.GetException(err, "Failed to get metadata list with filter.");
612 Interop.ApplicationManager.AppInfoMetadataFilterDestroy(nativeHandle);
616 private static IntPtr MakeNativeAppInfoFilter(IDictionary<string, string> filter)
618 if (filter == null || filter.Count == 0)
620 throw ApplicationManagerErrorFactory.FilterIsInvalid();
623 IntPtr infoHandle = IntPtr.Zero;
624 Interop.ApplicationManager.ErrorCode err = Interop.ApplicationManager.AppInfoFilterCreate(out infoHandle);
625 if (err != Interop.ApplicationManager.ErrorCode.None)
627 throw ApplicationManagerErrorFactory.GetException(err, "Failed to create the filter handle.");
630 foreach (var item in filter)
632 if ((item.Key == ApplicationInfoFilter.Keys.Id) ||
633 (item.Key == ApplicationInfoFilter.Keys.Type) ||
634 (item.Key == ApplicationInfoFilter.Keys.Category) ||
635 (item.Key == ApplicationInfoFilter.Keys.InstalledStorage))
637 err = Interop.ApplicationManager.AppInfoFilterAddString(infoHandle, item.Key, item.Value);
639 else if ((item.Key == ApplicationInfoFilter.Keys.NoDisplay) ||
640 (item.Key == ApplicationInfoFilter.Keys.TaskManage))
642 err = Interop.ApplicationManager.AppInfoFilterAddBool(infoHandle, item.Key, Convert.ToBoolean(item.Value));
646 Log.Warn(LogTag, string.Format("'{0}' is not supported key for the filter.", item.Key));
648 if (err != Interop.ApplicationManager.ErrorCode.None)
650 Interop.ApplicationManager.AppInfoFilterDestroy(infoHandle);
651 throw ApplicationManagerErrorFactory.GetException(err, "Failed to add item to the filter.");
657 private static IntPtr MakeNativeAppMetadataFilter(IDictionary<string, string> filter)
659 if (filter == null || filter.Count == 0)
661 throw ApplicationManagerErrorFactory.FilterIsInvalid();
664 IntPtr infoHandle = IntPtr.Zero;
665 Interop.ApplicationManager.ErrorCode err = Interop.ApplicationManager.AppInfoMetadataFilterCreate(out infoHandle);
666 if (err != Interop.ApplicationManager.ErrorCode.None)
668 throw ApplicationManagerErrorFactory.GetException(err, "Failed to create the filter for searching with metadata.");
670 foreach (var item in filter)
672 err = Interop.ApplicationManager.AppInfoMetadataFilterAdd(infoHandle, item.Key, item.Value);
673 if (err != Interop.ApplicationManager.ErrorCode.None)
675 Interop.ApplicationManager.AppInfoMetadataFilterDestroy(infoHandle);
676 throw ApplicationManagerErrorFactory.GetException(err, "Failed to add the item to the filter.");
683 internal static class ApplicationManagerErrorFactory
685 internal static Exception NativeFilterHandleIsInvalid()
687 return new InvalidOperationException("The native handle for filtering is invalid.");
690 internal static Exception FilterIsInvalid()
692 return new ArgumentException("The filter is invalid.");
695 internal static Exception GetException(Interop.ApplicationManager.ErrorCode err, string message)
697 string errMessage = String.Format("{0} err = {1}", message, err);
700 case Interop.ApplicationManager.ErrorCode.InvalidParameter:
701 return new ArgumentException(errMessage);
703 return new InvalidOperationException(errMessage);