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;
21 using System.Runtime.InteropServices;
22 using System.Threading.Tasks;
24 namespace Tizen.Applications
27 /// Represents the control message to exchange between applications.
31 /// public class AppControlExample : UIApplication
34 /// protected override void OnAppControlReceived(AppControlReceivedEventArgs e)
36 /// AppControl appControl = new AppControl();
37 /// appControl.ApplicationId = "org.tizen.calculator";
38 /// AppControl.SendLaunchRequest(appControl, (launchRequest, replyRequest, result) => {
45 /// <since_tizen> 3 </since_tizen>
46 public class AppControl
48 private const string LogTag = "Tizen.Applications";
50 private static Dictionary<int, Interop.AppControl.ResultCallback> s_resultNativeCallbackMaps = new Dictionary<int, Interop.AppControl.ResultCallback>();
51 private static Dictionary<int, AppControlReplyCallback> s_replyCallbackMaps = new Dictionary<int, AppControlReplyCallback>();
52 private static int s_reaustId = 0;
54 private readonly SafeAppControlHandle _handle;
56 private string _operation = null;
57 private string _mime = null;
58 private string _uri = null;
59 private string _category = null;
60 private string _applicationId = null;
61 private ExtraDataCollection _extraData = null;
62 private string _componentId = null;
65 /// Initializes the instance of the AppControl class.
67 /// <exception cref="InvalidOperationException">Thrown when failed to create the AppControl handle.</exception>
68 /// <since_tizen> 3 </since_tizen>
71 Interop.AppControl.ErrorCode err = Interop.AppControl.Create(out _handle);
72 if (err != Interop.AppControl.ErrorCode.None)
74 throw new InvalidOperationException("Failed to create the appcontrol handle. Err = " + err);
79 /// Initializes the instance of the AppControl class with a parameter.
81 /// <param name="enableAppStartedResultEvent">The flag value to receive an additional launch result event on the launch request.</param>
82 /// <exception cref="InvalidOperationException">Thrown when failed to create the AppControl handle.</exception>
83 /// <since_tizen> 3 </since_tizen>
84 public AppControl(bool enableAppStartedResultEvent)
86 Interop.AppControl.ErrorCode err = Interop.AppControl.Create(out _handle);
87 if (err != Interop.AppControl.ErrorCode.None)
89 throw new InvalidOperationException("Failed to create the appcontrol handle. Err = " + err);
92 if (enableAppStartedResultEvent)
94 err = Interop.AppControl.EnableAppStartedResultEvent(_handle);
95 if (err != Interop.AppControl.ErrorCode.None)
97 throw new InvalidOperationException("Failed to set EnableAppStartedResultEvent");
103 /// Initializes the instance of the AppControl class with the SafeAppControlHandle.
105 /// <param name="handle"></param>
106 /// <since_tizen> 3 </since_tizen>
107 public AppControl(SafeAppControlHandle handle)
111 throw new ArgumentNullException(nameof(handle));
114 if (handle.IsInvalid)
116 throw new ArgumentNullException(nameof(handle), "handle is invalid");
119 bool mustRelease = false;
122 handle.DangerousAddRef(ref mustRelease);
123 Interop.AppControl.ErrorCode err = Interop.AppControl.DangerousClone(out _handle, handle.DangerousGetHandle());
124 if (err != Interop.AppControl.ErrorCode.None)
126 throw new InvalidOperationException("Failed to clone the appcontrol handle. Err = " + err);
129 catch (ObjectDisposedException e)
131 throw new ArgumentNullException(nameof(handle), e.Message);
137 handle.DangerousRelease();
142 private AppControl(IntPtr handle)
144 Interop.AppControl.ErrorCode err = Interop.AppControl.DangerousClone(out _handle, handle);
145 if (err != Interop.AppControl.ErrorCode.None)
147 throw new InvalidOperationException("Failed to clone the appcontrol handle. Err = " + err);
151 private static Interop.AppControl.ReplyCallback s_replyNativeCallback = (launchHandle, replyHandle, result, userData) =>
153 int requestId = (int)userData;
154 lock (s_replyCallbackMaps)
156 if (s_replyCallbackMaps.ContainsKey(requestId))
158 s_replyCallbackMaps[requestId](new AppControl(launchHandle), new AppControl(replyHandle), (AppControlReplyResult)result);
159 if (result != Interop.AppControl.AppStartedStatus)
161 s_replyCallbackMaps.Remove(requestId);
167 #region Public Properties
170 /// Gets the SafeAppControlHandle instance.
172 /// <since_tizen> 3 </since_tizen>
173 public SafeAppControlHandle SafeAppControlHandle
182 /// Gets and sets the operation to be performed.
185 /// The operation is the mandatory information for the launch request. If the operation is not specified,
186 /// AppControlOperations.Default is used for the launch request. If the operation is AppControlOperations.Default,
187 /// the package information is mandatory to explicitly launch the application.
188 /// (if the operation is null for setter, it clears the previous value.)
192 /// AppControl appControl = new AppControl();
193 /// appControl.Operation = AppControlOperations.Default;
194 /// Log.Debug(LogTag, "Operation: " + appControl.Operation);
197 /// <since_tizen> 3 </since_tizen>
198 public string Operation
202 if (String.IsNullOrEmpty(_operation))
204 Interop.AppControl.ErrorCode err = Interop.AppControl.GetOperation(_handle, out _operation);
205 if (err != Interop.AppControl.ErrorCode.None)
207 Log.Warn(LogTag, "Failed to get the operation from the appcontrol. Err = " + err);
214 Interop.AppControl.ErrorCode err = Interop.AppControl.SetOperation(_handle, value);
215 if (err == Interop.AppControl.ErrorCode.None)
221 Log.Warn(LogTag, "Failed to set the operation to the appcontrol. Err = " + err);
227 /// Gets and sets the explicit MIME type of the data.
230 /// (if the mime is null for setter, it clears the previous value.)
234 /// AppControl appControl = new AppControl();
235 /// appControl.Mime = "image/jpg";
236 /// Log.Debug(LogTag, "Mime: " + appControl.Mime);
239 /// <since_tizen> 3 </since_tizen>
244 if (String.IsNullOrEmpty(_mime))
246 Interop.AppControl.ErrorCode err = Interop.AppControl.GetMime(_handle, out _mime);
247 if (err != Interop.AppControl.ErrorCode.None)
249 Log.Warn(LogTag, "Failed to get the mime from the appcontrol. Err = " + err);
256 Interop.AppControl.ErrorCode err = Interop.AppControl.SetMime(_handle, value);
257 if (err == Interop.AppControl.ErrorCode.None)
263 Log.Warn(LogTag, "Failed to set the mime to the appcontrol. Err = " + err);
269 /// Gets and sets the URI of the data.
272 /// Since Tizen 2.4, if the parameter 'uri' is started with 'file://' and
273 /// it is a regular file in this application's data path, which can be obtained
274 /// by property DataPath in ApplicationInfo class,
275 /// it will be shared to the callee application.
276 /// Framework will grant a temporary permission to the callee application for this file and
277 /// revoke it when the callee application is terminated.
278 /// The callee application can just read it.
279 /// (if the uri is null for setter, it clears the previous value.)
283 /// public class AppControlExample : UIApplication
286 /// protected override void OnAppControlReceived(AppControlReceivedEventArgs e)
289 /// AppControl appControl = new AppControl();
290 /// appContrl.Uri = this.ApplicationInfo.DataPath + "image.jpg";
291 /// Log.Debug(LogTag, "Set Uri: " + appControl.Uri);
296 /// <since_tizen> 3 </since_tizen>
297 #pragma warning disable CA1056
299 #pragma warning restore CA1056
303 if (String.IsNullOrEmpty(_uri))
305 Interop.AppControl.ErrorCode err = Interop.AppControl.GetUri(_handle, out _uri);
306 if (err != Interop.AppControl.ErrorCode.None)
308 Log.Warn(LogTag, "Failed to get the uri from the appcontrol. Err = " + err);
315 Interop.AppControl.ErrorCode err = Interop.AppControl.SetUri(_handle, value);
316 if (err == Interop.AppControl.ErrorCode.None)
322 Log.Warn(LogTag, "Failed to set the uri to the appcontrol. Err = " + err);
328 /// Gets and sets the explicit category.
331 /// (if the category is null for setter, it clears the previous value.)
333 /// <since_tizen> 3 </since_tizen>
334 public string Category
338 if (String.IsNullOrEmpty(_category))
340 Interop.AppControl.ErrorCode err = Interop.AppControl.GetCategory(_handle, out _category);
341 if (err != Interop.AppControl.ErrorCode.None)
343 Log.Warn(LogTag, "Failed to get the category from the appcontrol. Err = " + err);
350 Interop.AppControl.ErrorCode err = Interop.AppControl.SetCategory(_handle, value);
351 if (err == Interop.AppControl.ErrorCode.None)
357 Log.Warn(LogTag, "Failed to set the category to the appcontrol. Err = " + err);
363 /// Gets and sets the application ID to explicitly launch.
366 /// (if the application ID is null for setter, it clears the previous value.)
370 /// AppControl appControl = new AppControl();
371 /// appControl.ApplicationId = "org.tizen.calculator";
372 /// Log.Debug(LogTag, "ApplicationId: " + appControl.ApplicationId);
375 /// <since_tizen> 3 </since_tizen>
376 public string ApplicationId
380 if (String.IsNullOrEmpty(_applicationId))
382 Interop.AppControl.ErrorCode err = Interop.AppControl.GetAppId(_handle, out _applicationId);
383 if (err != Interop.AppControl.ErrorCode.None)
385 Log.Warn(LogTag, "Failed to get the application id from the AppControl. Err = " + err);
388 return _applicationId;
392 Interop.AppControl.ErrorCode err = Interop.AppControl.SetAppId(_handle, value);
393 if (err == Interop.AppControl.ErrorCode.None)
395 _applicationId = value;
399 Log.Warn(LogTag, "Failed to set the application id to the AppControl. Err = " + err);
405 /// Gets and sets the launch mode of the application.
408 /// Although, LaunchMode were set as AppControlLaunchMode.Group, the
409 /// callee application would be launched as a single mode
410 /// if the manifest file of callee application defined the launch mode as "single".
411 /// This property can just set the preference of the caller application to launch an application.
412 /// Sub-applications, which were launched as a group mode always have own process.
413 /// Since Tizen 3.0, if launch mode is not set in the caller application control,
414 /// this property returns the AppControlLaunchMode.Single launch mode.
418 /// AppControl appControl = new AppControl();
419 /// appControl.LaunchMode = AppControlLaunchMode.Group;
422 /// <since_tizen> 3 </since_tizen>
423 public AppControlLaunchMode LaunchMode
428 Interop.AppControl.ErrorCode err = Interop.AppControl.GetLaunchMode(_handle, out value);
429 if (err != Interop.AppControl.ErrorCode.None)
431 Log.Warn(LogTag, "Failed to get the LaunchMode from the AppControl. Err = " + err);
433 return (AppControlLaunchMode)value;
437 Interop.AppControl.ErrorCode err = Interop.AppControl.SetLaunchMode(_handle, (int)value);
438 if (err != Interop.AppControl.ErrorCode.None)
440 Log.Warn(LogTag, "Failed to set the LaunchMode to the AppControl. Err = " + err);
446 /// Gets the collection of the extra data.
449 /// Extra data for communication between AppControls.
453 /// AppControl appControl = new AppControl();
454 /// appControl.ExtraData.Add("key", "value");
458 /// <since_tizen> 3 </since_tizen>
459 public ExtraDataCollection ExtraData
463 if (_extraData == null)
464 _extraData = new ExtraDataCollection(_handle);
470 /// Gets and sets the component ID to explicitly launch a component.
473 /// (if the component ID is null for setter, it clears the previous value.)
474 /// From Tizen 5.5, a new application model is supported that is component-based application.
475 /// This property is for launching component-based application. If it's not set, the main component of component-based application will be launched.
476 /// If the target app is not component-based application, setting property is meaningless.
480 /// AppControl appControl = new AppControl();
481 /// appControl.ApplicationId = "org.tizen.component-based-app"; // component-based application
482 /// appControl.ComponentId = "org.tizen.frame-component";
483 /// AppControl.SendLaunchRequest(appControl);
486 /// <since_tizen> 6 </since_tizen>
487 public string ComponentId
491 if (String.IsNullOrEmpty(_componentId))
493 Interop.AppControl.ErrorCode err = Interop.AppControl.GetComponentId(_handle, out _componentId);
494 if (err != Interop.AppControl.ErrorCode.None)
496 Log.Warn(LogTag, "Failed to get the component id from the AppControl. Err = " + err);
503 Interop.AppControl.ErrorCode err = Interop.AppControl.SetComponentId(_handle, value);
504 if (err == Interop.AppControl.ErrorCode.None)
506 _componentId = value;
510 Log.Warn(LogTag, "Failed to set the component id to the AppControl. Err = " + err);
515 #endregion // Public Properties
518 /// Retrieves all applications that can be launched to handle the given app_control request.
520 /// <param name="control">The AppControl.</param>
521 /// <returns>ApplicationIds.</returns>
522 /// <exception cref="InvalidOperationException">Thrown when failed because of an invalid parameter.</exception>
525 /// IEnumerable<string> applicationIds = AppControl.GetMatchedApplicationIds(control);
526 /// if (applicationIds != null)
528 /// foreach (string id in applicationIds)
535 /// <since_tizen> 3 </since_tizen>
536 public static IEnumerable<string> GetMatchedApplicationIds(AppControl control)
540 throw new ArgumentNullException(nameof(control));
543 List<string> ids = new List<string>();
544 Interop.AppControl.AppMatchedCallback callback = (handle, applicationId, userData) =>
546 if (applicationId == null)
551 ids.Add(applicationId);
555 Interop.AppControl.ErrorCode err = Interop.AppControl.ForeachAppMatched(control._handle, callback, IntPtr.Zero);
556 if (err != Interop.AppControl.ErrorCode.None)
558 throw new InvalidOperationException("Failed to get matched application ids. err = " + err);
565 /// Sends the launch request.
568 /// The operation is mandatory information for the launch request.
569 /// If the operation is not specified, AppControlOperations.Default is used by default.
570 /// If the operation is AppControlOperations.Default, the application ID is mandatory to explicitly launch the application.<br/>
571 /// Since Tizen 2.4, the launch request of the service application over out of packages is restricted by the platform.
572 /// Also, implicit launch requests are NOT delivered to service applications since 2.4.
573 /// To launch a service application, an explicit launch request with the application ID given by property ApplicationId MUST be sent.
575 /// <param name="launchRequest">The AppControl.</param>
576 /// <exception cref="ArgumentNullException">Thrown when failed because of a null argument.</exception>
577 /// <exception cref="InvalidOperationException">Thrown when failed because of an invalid operation.</exception>
578 /// <exception cref="TimeoutException">Thrown when failed because of timeout.</exception>
579 /// <privilege>http://tizen.org/privilege/appmanager.launch</privilege>
582 /// AppControl appControl = new AppControl();
583 /// appControl.ApplicationId = "org.tizen.calculator";
584 /// AppControl.SendLaunchRequest(appControl);
587 /// <since_tizen> 3 </since_tizen>
588 public static void SendLaunchRequest(AppControl launchRequest)
590 SendLaunchRequest(launchRequest, null);
594 /// Sends the launch request with setting timeout.
597 /// The operation is mandatory information for the launch request.
598 /// If the operation is not specified, AppControlOperations.Default is used by default.
599 /// If the operation is AppControlOperations.Default, the application ID is mandatory to explicitly launch the application.<br/>
600 /// To launch a service application, an explicit launch request with the application ID given by property ApplicationId MUST be sent.<br/>
601 /// It can set receiving timeout interval using timeout parameter.
602 /// If there is an error that is not related to timeout, the error is returned immediately regardless of the timeout value.
604 /// <param name="launchRequest">The AppControl.</param>
605 /// <param name="timeout">The timeout in milliseconds, the timeout range is 5000 to 30000.</param>
606 /// <exception cref="ArgumentNullException">Thrown when failed because of a null argument.</exception>
607 /// <exception cref="InvalidOperationException">Thrown when failed because of an invalid operation.</exception>
608 /// <exception cref="TimeoutException">Thrown when failed because of timeout.</exception>
609 /// <privilege>http://tizen.org/privilege/appmanager.launch</privilege>
612 /// AppControl appControl = new AppControl();
613 /// appControl.ApplicationId = "org.tizen.calculator";
614 /// AppControl.SendLaunchRequest(appControl, 10000);
617 /// <since_tizen> 7.5 </since_tizen>
618 [EditorBrowsable(EditorBrowsableState.Never)]
619 public static void SendLaunchRequest(AppControl launchRequest, uint timeout)
621 SendLaunchRequest(launchRequest, timeout, null);
625 /// Sends the launch request.
628 /// The operation is mandatory information for the launch request.
629 /// If the operation is not specified, AppControlOperations.Default is used by default.
630 /// If the operation is AppControlOperations.Default, the application ID is mandatory to explicitly launch the application.<br/>
631 /// Since Tizen 2.4, the launch request of the service application over out of packages is restricted by the platform.
632 /// Also, implicit launch requests are NOT delivered to service applications since 2.4.
633 /// To launch a service application, an explicit launch request with the application ID given by property ApplicationId MUST be sent.
635 /// <param name="launchRequest">The AppControl.</param>
636 /// <param name="replyAfterLaunching">The callback function to be called when the reply is delivered.</param>
637 /// <exception cref="ArgumentException">Thrown when failed because of the argument is invalid.</exception>
638 /// <exception cref="Exceptions.AppNotFoundException">Thrown when the application to run is not found.</exception>
639 /// <exception cref="Exceptions.LaunchFailedException">Thrown when the request failed to launch the application.</exception>
640 /// <exception cref="Exceptions.LaunchRejectedException">Thrown when the launch request is rejected.</exception>
641 /// <exception cref="Exceptions.OutOfMemoryException">Thrown when the memory is insufficient.</exception>
642 /// <exception cref="Exceptions.PermissionDeniedException">Thrown when the permission is denied.</exception>
643 /// <exception cref="TimeoutException">Thrown when failed because of timeout.</exception>
644 /// <privilege>http://tizen.org/privilege/appmanager.launch</privilege>
647 /// AppControl appControl = new AppControl();
648 /// appControl.ApplicationId = "org.tizen.calculator";
649 /// AppControl.SendLaunchRequest(appControl, (launchRequest, replyRequest, result) => {
654 /// <since_tizen> 3 </since_tizen>
655 public static void SendLaunchRequest(AppControl launchRequest, AppControlReplyCallback replyAfterLaunching)
657 if (launchRequest == null)
659 throw new ArgumentNullException(nameof(launchRequest));
662 Interop.AppControl.ErrorCode err;
664 if (replyAfterLaunching != null)
667 lock (s_replyCallbackMaps)
670 s_replyCallbackMaps[id] = replyAfterLaunching;
672 err = Interop.AppControl.SendLaunchRequest(launchRequest._handle, s_replyNativeCallback, (IntPtr)id);
676 err = Interop.AppControl.SendLaunchRequest(launchRequest._handle, null, IntPtr.Zero);
679 if (err != Interop.AppControl.ErrorCode.None)
683 case Interop.AppControl.ErrorCode.InvalidParameter:
684 throw new ArgumentException("Invalid Arguments");
685 case Interop.AppControl.ErrorCode.TimedOut:
686 throw new TimeoutException("Timed out");
687 case Interop.AppControl.ErrorCode.OutOfMemory:
688 throw new Exceptions.OutOfMemoryException("Out-of-memory");
689 case Interop.AppControl.ErrorCode.AppNotFound:
690 throw new Exceptions.AppNotFoundException("App(" + launchRequest.ApplicationId + ") not found. Operation(" + launchRequest.Operation + ")");
691 case Interop.AppControl.ErrorCode.LaunchRejected:
692 throw new Exceptions.LaunchRejectedException("Launch rejected");
693 case Interop.AppControl.ErrorCode.LaunchFailed:
694 throw new Exceptions.LaunchFailedException("Launch failed");
695 case Interop.AppControl.ErrorCode.PermissionDenied:
696 throw new Exceptions.PermissionDeniedException("Permission denied");
699 throw new Exceptions.LaunchRejectedException("Launch rejected");
705 /// Sends the launch request with setting timeout
708 /// The operation is mandatory information for the launch request.
709 /// If the operation is not specified, AppControlOperations.Default is used by default.
710 /// If the operation is AppControlOperations.Default, the application ID is mandatory to explicitly launch the application.<br/>
711 /// To launch a service application, an explicit launch request with the application ID given by property ApplicationId MUST be sent.<br/>
712 /// It can set receiving timeout interval using timeout parameter.
713 /// If there is an error that is not related to timeout, the error is returned immediately regardless of the timeout value.
715 /// <param name="launchRequest">The AppControl.</param>
716 /// <param name="timeout">The timeout in milliseconds, the timeout range is 5000 to 30000.</param>
717 /// <param name="replyAfterLaunching">The callback function to be called when the reply is delivered.</param>
718 /// <exception cref="ArgumentException">Thrown when failed because of the argument is invalid.</exception>
719 /// <exception cref="Exceptions.AppNotFoundException">Thrown when the application to run is not found.</exception>
720 /// <exception cref="Exceptions.LaunchFailedException">Thrown when the request failed to launch the application.</exception>
721 /// <exception cref="Exceptions.LaunchRejectedException">Thrown when the launch request is rejected.</exception>
722 /// <exception cref="Exceptions.OutOfMemoryException">Thrown when the memory is insufficient.</exception>
723 /// <exception cref="Exceptions.PermissionDeniedException">Thrown when the permission is denied.</exception>
724 /// <exception cref="TimeoutException">Thrown when failed because of timeout. The timeout interval is set by timeout parameter.</exception>
725 /// <privilege>http://tizen.org/privilege/appmanager.launch</privilege>
728 /// AppControl appControl = new AppControl();
729 /// appControl.ApplicationId = "org.tizen.calculator";
730 /// AppControl.SendLaunchRequest(appControl, 10000, (launchRequest, replyRequest, result) => {
735 /// <since_tizen> 7.5 </since_tizen>
736 [EditorBrowsable(EditorBrowsableState.Never)]
737 public static void SendLaunchRequest(AppControl launchRequest, uint timeout, AppControlReplyCallback replyAfterLaunching)
739 if (launchRequest == null)
741 throw new ArgumentNullException(nameof(launchRequest));
744 Interop.AppControl.ErrorCode err;
746 if (replyAfterLaunching != null)
749 lock (s_replyCallbackMaps)
752 s_replyCallbackMaps[id] = replyAfterLaunching;
754 err = Interop.AppControl.SendLaunchRequestWithTimeout(launchRequest._handle, timeout, s_replyNativeCallback, (IntPtr)id);
758 err = Interop.AppControl.SendLaunchRequestWithTimeout(launchRequest._handle, timeout, null, IntPtr.Zero);
761 if (err != Interop.AppControl.ErrorCode.None)
765 case Interop.AppControl.ErrorCode.InvalidParameter:
766 throw new ArgumentException("Invalid Arguments");
767 case Interop.AppControl.ErrorCode.TimedOut:
768 throw new TimeoutException("Timed out");
769 case Interop.AppControl.ErrorCode.OutOfMemory:
770 throw new Exceptions.OutOfMemoryException("Out-of-memory");
771 case Interop.AppControl.ErrorCode.AppNotFound:
772 throw new Exceptions.AppNotFoundException("App(" + launchRequest.ApplicationId + ") not found. Operation(" + launchRequest.Operation + ")");
773 case Interop.AppControl.ErrorCode.LaunchRejected:
774 throw new Exceptions.LaunchRejectedException("Launch rejected");
775 case Interop.AppControl.ErrorCode.LaunchFailed:
776 throw new Exceptions.LaunchFailedException("Launch failed");
777 case Interop.AppControl.ErrorCode.PermissionDenied:
778 throw new Exceptions.PermissionDeniedException("Permission denied");
781 throw new Exceptions.LaunchRejectedException("Launch rejected");
787 /// Sends the terminate request to the application that is launched by AppControl.
790 /// You are not allowed to terminate other general applications using this API.
791 /// This API can be used to terminate sub-applications, which were launched as a group mode by the caller application.
792 /// Once the callee application is being terminated by this API,
793 /// other applications, which were launched by the callee application as a group mode will be terminated as well.
795 /// <param name="terminateRequest">The AppControl.</param>
796 /// <exception cref="ArgumentException">Thrown when failed because of the argument is invalid.</exception>
797 /// <exception cref="InvalidOperationException">Thrown when failed because of an invalid operation.</exception>
798 /// <exception cref="TimeoutException">Thrown when failed because of timeout.</exception>
801 /// AppControl terminateRequest = new AppControl();
802 /// terminateRequest.ApplicationId = "org.tizen.calculator";
803 /// AppControl.SendTerminateRequest(terminateRequest);
806 /// <since_tizen> 3 </since_tizen>
807 public static void SendTerminateRequest(AppControl terminateRequest)
809 if (terminateRequest == null)
811 throw new ArgumentNullException(nameof(terminateRequest));
813 Interop.AppControl.ErrorCode err;
815 err = Interop.AppControl.SendTerminateRequest(terminateRequest._handle);
817 if (err != Interop.AppControl.ErrorCode.None)
821 case Interop.AppControl.ErrorCode.InvalidParameter:
822 throw new ArgumentException("Invalid Arguments");
823 case Interop.AppControl.ErrorCode.TimedOut:
824 throw new TimeoutException("Timed out");
826 throw new InvalidOperationException("Error = " + err);
832 /// Sends the launch request asynchronously.
835 /// The operation is mandatory information for the launch request.
836 /// If the operation is not specified, AppControlOperations.Default is used by default.
837 /// If the operation is AppControlOperations.Default, the application ID is mandatory to explicitly launch the application.<br/>
838 /// Since Tizen 2.4, the launch request of the service application over out of packages is restricted by the platform.
839 /// Also, implicit launch requests are NOT delivered to service applications since 2.4.
840 /// To launch a service application, an explicit launch request with the application ID given by property ApplicationId MUST be sent.
842 /// <param name="launchRequest">The AppControl.</param>
843 /// <param name="replyAfterLaunching">The callback function to be called when the reply is delivered.</param>
844 /// <returns>A task with the result of the launch request.</returns>
845 /// <exception cref="ArgumentException">Thrown when failed because of the argument is invalid.</exception>
846 /// <exception cref="Exceptions.AppNotFoundException">Thrown when the application to run is not found.</exception>
847 /// <exception cref="Exceptions.LaunchRejectedException">Thrown when the launch request is rejected.</exception>
848 /// <privilege>http://tizen.org/privilege/appmanager.launch</privilege>
849 /// <since_tizen> 6 </since_tizen>
850 public static Task<AppControlResult> SendLaunchRequestAsync(AppControl launchRequest, AppControlReplyCallback replyAfterLaunching)
852 if (launchRequest == null)
854 throw new ArgumentNullException(nameof(launchRequest));
857 var task = new TaskCompletionSource<AppControlResult>();
858 Interop.AppControl.ErrorCode err;
861 lock (s_resultNativeCallbackMaps)
863 requestId = s_reaustId++;
864 s_resultNativeCallbackMaps[requestId] = (handle, result, userData) =>
866 task.SetResult((AppControlResult)result);
867 lock (s_resultNativeCallbackMaps)
869 s_resultNativeCallbackMaps.Remove((int)userData);
874 if (replyAfterLaunching != null)
876 lock (s_replyCallbackMaps)
878 s_replyCallbackMaps[requestId] = replyAfterLaunching;
880 err = Interop.AppControl.SendLaunchRequestAsync(launchRequest.SafeAppControlHandle, s_resultNativeCallbackMaps[requestId], s_replyNativeCallback, (IntPtr)requestId);
884 err = Interop.AppControl.SendLaunchRequestAsync(launchRequest.SafeAppControlHandle, s_resultNativeCallbackMaps[requestId], null, (IntPtr)requestId);
887 if (err != Interop.AppControl.ErrorCode.None)
891 case Interop.AppControl.ErrorCode.InvalidParameter:
892 throw new ArgumentException("Invalid Arguments");
893 case Interop.AppControl.ErrorCode.AppNotFound:
894 throw new Exceptions.AppNotFoundException("App(" + launchRequest.ApplicationId + ") not found. Operation(" + launchRequest.Operation + ")");
895 case Interop.AppControl.ErrorCode.LaunchRejected:
896 throw new Exceptions.LaunchRejectedException("Launch rejected");
897 case Interop.AppControl.ErrorCode.PermissionDenied:
898 throw new Exceptions.PermissionDeniedException("Permission denied");
901 throw new Exceptions.LaunchRejectedException("Launch rejected");
909 /// Sets the auto restart.
912 /// The functionality of this method only applies to the caller application.
913 /// The auto restart cannot be applied to other applications. The application ID set in the AppControl is ignored.
914 /// This method is only available for platform level signed applications.
916 /// <param name="appControl">The AppControl.</param>
917 /// <exception cref="ArgumentNullException">Thrown when the argument is null.</exception>
918 /// <exception cref="ArgumentException">Thrown when the argument is invalid.</exception>
919 /// <exception cref="Exceptions.PermissionDeniedException">Thrown when the permission is denied.</exception>
920 /// <exception cref="Exceptions.OutOfMemoryException">Thrown when the memory is insufficient.</exception>
921 /// <exception cref="InvalidOperationException">Thrown when the memory is insufficient.</exception>
922 [EditorBrowsable(EditorBrowsableState.Never)]
923 public static void SetAutoRestart(AppControl appControl)
925 if (appControl == null)
927 throw new ArgumentNullException(nameof(appControl));
930 Interop.AppControl.ErrorCode err = Interop.AppControl.SetAutoRestart(appControl.SafeAppControlHandle);
931 if (err != Interop.AppControl.ErrorCode.None)
935 case Interop.AppControl.ErrorCode.InvalidParameter:
936 throw new ArgumentException("Invalid arguments");
937 case Interop.AppControl.ErrorCode.PermissionDenied:
938 throw new Exceptions.PermissionDeniedException("Permission denied");
939 case Interop.AppControl.ErrorCode.OutOfMemory:
940 throw new Exceptions.OutOfMemoryException("Out of memory");
942 throw new InvalidOperationException("err = " + err);
948 /// Unsets the auto restart.
951 /// The functionality of this method only applies to the caller application.
952 /// This method is only available for platform level signed applications.
954 /// <exception cref="Exceptions.PermissionDeniedException">Thrown when the permission is denied.</exception>
955 /// <exception cref="Exceptions.OutOfMemoryException">Thrown when the memory is insufficient.</exception>
956 /// <exception cref="InvalidOperationException">Thrown when the memory is insufficient.</exception>
957 [EditorBrowsable(EditorBrowsableState.Never)]
958 public static void UnsetAutoRestart()
960 Interop.AppControl.ErrorCode err = Interop.AppControl.UnsetAutoRestart();
961 if (err != Interop.AppControl.ErrorCode.None)
965 case Interop.AppControl.ErrorCode.PermissionDenied:
966 throw new Exceptions.PermissionDeniedException("Permission denied");
967 case Interop.AppControl.ErrorCode.OutOfMemory:
968 throw new Exceptions.OutOfMemoryException("Out of memory");
970 throw new InvalidOperationException("err = " + err);
976 /// Gets all default applications.
978 /// <returns>ApplicationIds.</returns>
979 /// <exception cref="InvalidOperationException">Thrown when failed because of an invalid operation.</exception>
982 /// IEnumerable<string> applicationIds = AppControl.GetDefaultApplicationIds();
983 /// if (applicationIds != null)
985 /// foreach (string id in applicationIds)
992 /// <since_tizen> 11 </since_tizen>
993 [EditorBrowsable(EditorBrowsableState.Never)]
994 public static IEnumerable<string> GetDefaultApplicationIds()
996 List<string> ids = new List<string>();
997 Interop.AppControl.DefaultApplicationCallback callback = (applicationId, userData) =>
999 if (applicationId == null)
1004 ids.Add(applicationId);
1008 Interop.AppControl.ErrorCode err = Interop.AppControl.ForeachDefaultApplication(callback, IntPtr.Zero);
1009 if (err != Interop.AppControl.ErrorCode.None)
1011 throw new InvalidOperationException("Failed to get default application Ids. err = " + err);
1018 /// Sets the window position.
1020 /// <param name="windowPosition">The window position object.</param>
1021 /// <exception cref="ArgumentNullException">Thrown when the argument is null.</exception>
1022 /// <exception cref="ArgumentException">Thrown when the argument is invalid.</exception>
1023 /// <exception cref="InvalidOperationException">Thrown when the invalid operation error occurs.</exception>
1024 /// <since_tizen> 11 </since_tizen>
1025 public void SetWindowPosition(WindowPosition windowPosition)
1027 if (windowPosition == null)
1029 throw new ArgumentNullException(nameof(windowPosition));
1032 Interop.AppControl.ErrorCode err = Interop.AppControl.SetWindowPosition(this.SafeAppControlHandle, windowPosition.PositionX, windowPosition.PositionY, windowPosition.Width, windowPosition.Height);
1033 if (err != Interop.AppControl.ErrorCode.None)
1035 if (err == Interop.AppControl.ErrorCode.InvalidParameter)
1037 throw new ArgumentException("Invalid arguments");
1041 throw new InvalidOperationException("err = " + err);
1047 /// Gets the window position.
1049 /// <returns>The window position.</returns>
1050 /// <exception cref="InvalidOperationException">Thrown when the invalid operation error occurs.</exception>
1051 /// <since_tizen> 11 </since_tizen>
1052 public WindowPosition GetWindowPosition()
1054 Interop.AppControl.ErrorCode err = Interop.AppControl.GetWindowPosition(this.SafeAppControlHandle, out int x, out int y, out int w, out int h);
1055 if (err != Interop.AppControl.ErrorCode.None)
1057 throw new InvalidOperationException("err = " + err);
1060 return new WindowPosition(x, y, w, h);
1064 /// Class for extra data.
1066 /// <since_tizen> 3 </since_tizen>
1067 #pragma warning disable CA1034
1068 public class ExtraDataCollection
1069 #pragma warning restore CA1034
1071 private readonly SafeAppControlHandle _handle;
1073 internal ExtraDataCollection(SafeAppControlHandle handle)
1079 /// Adds extra data.
1082 /// The function replaces any existing value for the given key.
1084 /// <param name="key">The name of the extra data.</param>
1085 /// <param name="value">The value associated with the given key.</param>
1086 /// <exception cref="ArgumentNullException">Thrown when a key or a value is a zero-length string.</exception>
1087 /// <exception cref="ArgumentException">Thrown when the application tries to use the same key with the system-defined key.</exception>
1090 /// AppControl appControl = new AppControl();
1091 /// appControl.ExtraData.Add("myKey", "myValue");
1094 /// <since_tizen> 3 </since_tizen>
1095 public void Add(string key, string value)
1097 if (string.IsNullOrEmpty(key))
1099 throw new ArgumentNullException(nameof(key));
1101 if (string.IsNullOrEmpty(value))
1103 throw new ArgumentNullException(nameof(value));
1105 Interop.AppControl.ErrorCode err = Interop.AppControl.AddExtraData(_handle, key, value);
1106 if (err != Interop.AppControl.ErrorCode.None)
1110 case Interop.AppControl.ErrorCode.InvalidParameter:
1111 throw new ArgumentException("Invalid parameter: key or value is a zero-length string");
1112 case Interop.AppControl.ErrorCode.KeyRejected:
1113 throw new ArgumentException("Key is rejected: the key is system-defined key.");
1115 throw new InvalidOperationException("Error = " + err);
1121 /// Adds extra data.
1124 /// The function replaces any existing value for the given key.
1126 /// <param name="key">The name of the extra data.</param>
1127 /// <param name="value">The value associated with the given key.</param>
1128 /// <exception cref="ArgumentNullException">Thrown when key or value is a zero-length string.</exception>
1129 /// <exception cref="ArgumentException">Thrown when the application tries to use the same key with the system-defined key.</exception>
1132 /// AppControl appControl = new AppControl();
1133 /// string[] myValues = new string[] { "first", "second", "third" };
1134 /// appControl.ExtraData.Add("myKey", myValues);
1137 /// <since_tizen> 3 </since_tizen>
1138 public void Add(string key, IEnumerable<string> value)
1140 if (string.IsNullOrEmpty(key))
1142 throw new ArgumentNullException(nameof(key));
1146 throw new ArgumentNullException(nameof(value));
1148 string[] valueArray = value.ToArray();
1149 Interop.AppControl.ErrorCode err = Interop.AppControl.AddExtraDataArray(_handle, key, valueArray, valueArray.Length);
1150 if (err != Interop.AppControl.ErrorCode.None)
1154 case Interop.AppControl.ErrorCode.InvalidParameter:
1155 throw new ArgumentException("Invalid parameter: key or value is a zero-length string");
1156 case Interop.AppControl.ErrorCode.KeyRejected:
1157 throw new ArgumentException("Key is rejected: the key is system-defined key.");
1159 throw new InvalidOperationException("Error = " + err);
1165 /// Gets the extra data.
1167 /// <typeparam name="T">Only string and IEnumerable<string></typeparam>
1168 /// <param name="key">The name of extra data.</param>
1169 /// <returns>The value associated with the given key.</returns>
1170 /// <exception cref="ArgumentNullException">Thrown when the key is an invalid parameter.</exception>
1171 /// <exception cref="KeyNotFoundException">Thrown when the key is not found.</exception>
1172 /// <exception cref="ArgumentException">Thrown when the key is rejected.</exception>
1175 /// AppControl appControl = new AppControl();
1176 /// string myValue = appControl.ExtraData.Get<string>("myKey");
1179 /// <since_tizen> 3 </since_tizen>
1180 public T Get<T>(string key)
1182 object ret = Get(key);
1187 /// Gets the extra data.
1189 /// <param name="key">The name of extra data.</param>
1190 /// <returns>The value associated with the given key.</returns>
1191 /// <exception cref="ArgumentNullException">Thrown when the key is an invalid parameter.</exception>
1192 /// <exception cref="KeyNotFoundException">Thrown when the key is not found.</exception>
1193 /// <exception cref="ArgumentException">Thrown when the key is rejected.</exception>
1196 /// AppControl appControl = new AppControl();
1197 /// string myValue = appControl.ExtraData.Get("myKey") as string;
1198 /// if (myValue != null)
1204 /// <since_tizen> 3 </since_tizen>
1205 public object Get(string key)
1207 if (IsCollection(key))
1209 return GetDataCollection(key);
1213 return GetData(key);
1218 /// Gets all keys in extra data.
1220 /// <returns>The keys in the AppControl.</returns>
1221 /// <exception cref="InvalidOperationException">Thrown when the key is an invalid parameter.</exception>
1224 /// AppControl appControl = new AppControl();
1225 /// IEnumerable<string> keys = appControl.GetKeys();
1226 /// if (keys != null)
1228 /// foreach (string key in keys)
1235 /// <since_tizen> 3 </since_tizen>
1236 public IEnumerable<string> GetKeys()
1238 List<string> keys = new List<string>();
1239 Interop.AppControl.ExtraDataCallback callback = (handle, key, userData) =>
1250 Interop.AppControl.ErrorCode err = Interop.AppControl.ForeachExtraData(_handle, callback, IntPtr.Zero);
1251 if (err != Interop.AppControl.ErrorCode.None)
1253 throw new InvalidOperationException("Failed to get keys. err = " + err);
1260 /// Tries getting the extra data.
1262 /// <param name="key">The name of extra data.</param>
1263 /// <param name="value">The value associated with the given key.</param>
1264 /// <returns>The result whether getting the value is done.</returns>
1265 /// <exception cref="ArgumentNullException">Thrown when the key is an invalid parameter.</exception>
1266 /// <exception cref="KeyNotFoundException">Thrown when the key is not found.</exception>
1267 /// <exception cref="ArgumentException">Thrown when the key is rejected.</exception>
1270 /// AppControl appControl = new AppControl();
1271 /// string myValue = string.Empty;
1272 /// bool result = appControl.ExtraData.TryGet("myKey", out myValue);
1273 /// if (result != null)
1279 /// <since_tizen> 3 </since_tizen>
1280 public bool TryGet(string key, out string value)
1282 if (string.IsNullOrEmpty(key))
1284 throw new ArgumentNullException(nameof(key));
1286 Interop.AppControl.GetExtraData(_handle, key, out value);
1293 value = default(string);
1299 /// Tries getting the extra data.
1301 /// <param name="key">The name of extra data.</param>
1302 /// <param name="value">The value associated with the given key.</param>
1303 /// <returns>The result whether getting the value is done.</returns>
1304 /// <exception cref="ArgumentNullException">Thrown when the key is an invalid parameter.</exception>
1305 /// <exception cref="KeyNotFoundException">Thrown when the key is not found.</exception>
1306 /// <exception cref="ArgumentException">Thrown when the key is rejected.</exception>
1309 /// AppControl appControl = new AppControl();
1310 /// IEnumerable<string> myValue = null;
1311 /// bool result = appControl.ExtraData.TryGet("myKey", out myValue);
1314 /// foreach (string value in myValue)
1321 /// <since_tizen> 3 </since_tizen>
1322 public bool TryGet(string key, out IEnumerable<string> value)
1324 if (string.IsNullOrEmpty(key))
1326 throw new ArgumentNullException(nameof(key));
1328 IntPtr valuePtr = IntPtr.Zero;
1330 Interop.AppControl.ErrorCode err = Interop.AppControl.GetExtraDataArray(_handle, key, out valuePtr, out len);
1331 if (err == Interop.AppControl.ErrorCode.None && valuePtr != IntPtr.Zero)
1333 List<string> stringList = new List<string>();
1334 for (int i = 0; i < len; ++i)
1336 IntPtr charArr = Marshal.ReadIntPtr(valuePtr, IntPtr.Size * i);
1337 stringList.Add(Marshal.PtrToStringAnsi(charArr));
1338 Marshal.FreeHGlobal(charArr);
1340 Marshal.FreeHGlobal(valuePtr);
1346 value = default(IEnumerable<string>);
1352 /// Removes the extra data.
1354 /// <param name="key">The name of the extra data.</param>
1355 /// <exception cref="ArgumentNullException">Thrown when the key is a zero-length string.</exception>
1356 /// <exception cref="KeyNotFoundException">Thrown when the key is not found.</exception>
1357 /// <exception cref="ArgumentException">Thrown when the key is rejected.</exception>
1360 /// AppControl appControl = new AppControl();
1361 /// appControl.ExtraData.Remove("myKey");
1364 /// <since_tizen> 3 </since_tizen>
1365 public void Remove(string key)
1367 if (string.IsNullOrEmpty(key))
1369 throw new ArgumentNullException(nameof(key));
1371 Interop.AppControl.ErrorCode err = Interop.AppControl.RemoveExtraData(_handle, key);
1372 if (err != Interop.AppControl.ErrorCode.None)
1376 case Interop.AppControl.ErrorCode.InvalidParameter:
1377 throw new ArgumentException("Invalid parameter: key is a zero-length string");
1378 case Interop.AppControl.ErrorCode.KeyNotFound:
1379 throw new KeyNotFoundException("Key is not found"); ;
1380 case Interop.AppControl.ErrorCode.KeyRejected:
1381 throw new ArgumentException("Key is rejected: the key is system-defined key.");
1383 throw new InvalidOperationException("Error = " + err);
1389 /// Counts keys in the extra data.
1391 /// <returns>The number of counting keys.</returns>
1392 /// <exception cref="InvalidOperationException">Thrown when the key is an invalid parameter.</exception>
1395 /// AppControl appControl = new AppControl();
1396 /// int numberOfKeys = appControl.ExtraData.Count();
1399 /// <since_tizen> 3 </since_tizen>
1402 return GetKeys().Count();
1406 /// Checks whether the extra data associated with the given key is of the collection data type.
1408 /// <param name="key">The name of the extra data.</param>
1409 /// <returns>If true, the extra data is of the array data type, otherwise false.</returns>
1410 /// <exception cref="ArgumentNullException">Thrown when the key is a zero-length string.</exception>
1411 /// <exception cref="InvalidOperationException">Thrown when failed to check the key.</exception>
1414 /// AppControl appControl = new AppControl();
1415 /// bool result = appControl.ExtraData.IsCollection("myKey");
1418 /// <since_tizen> 3 </since_tizen>
1419 public bool IsCollection(string key)
1421 if (string.IsNullOrEmpty(key))
1423 throw new ArgumentNullException(nameof(key));
1425 bool isArray = false;
1426 Interop.AppControl.ErrorCode err = Interop.AppControl.IsExtraDataArray(_handle, key, out isArray);
1427 if (err != Interop.AppControl.ErrorCode.None)
1429 throw new InvalidOperationException("Error = " + err);
1434 private string GetData(string key)
1436 if (string.IsNullOrEmpty(key))
1438 throw new ArgumentNullException(nameof(key));
1440 string value = string.Empty;
1441 Interop.AppControl.ErrorCode err = Interop.AppControl.GetExtraData(_handle, key, out value);
1442 if (err != Interop.AppControl.ErrorCode.None)
1446 case Interop.AppControl.ErrorCode.InvalidParameter:
1447 throw new ArgumentException("Invalid parameter: key is a zero-length string");
1448 case Interop.AppControl.ErrorCode.KeyNotFound:
1449 throw new KeyNotFoundException("Key is not found"); ;
1450 case Interop.AppControl.ErrorCode.InvalidDataType:
1451 throw new ArgumentException("Invalid data type: value is data collection type");
1452 case Interop.AppControl.ErrorCode.KeyRejected:
1453 throw new ArgumentException("Key is rejected: the key is system-defined key.");
1455 throw new InvalidOperationException("Error = " + err);
1461 private IEnumerable<string> GetDataCollection(string key)
1463 if (string.IsNullOrEmpty(key))
1465 throw new ArgumentNullException(nameof(key));
1467 IntPtr valuePtr = IntPtr.Zero;
1469 Interop.AppControl.ErrorCode err = Interop.AppControl.GetExtraDataArray(_handle, key, out valuePtr, out len);
1470 if (err != Interop.AppControl.ErrorCode.None)
1474 case Interop.AppControl.ErrorCode.InvalidParameter:
1475 throw new ArgumentException("Invalid parameter: key is a zero-length string");
1476 case Interop.AppControl.ErrorCode.KeyNotFound:
1477 throw new KeyNotFoundException("Key is not found"); ;
1478 case Interop.AppControl.ErrorCode.InvalidDataType:
1479 throw new ArgumentException("Invalid data type: value is data collection type");
1480 case Interop.AppControl.ErrorCode.KeyRejected:
1481 throw new ArgumentException("Key is rejected: the key is system-defined key.");
1483 throw new InvalidOperationException("Error = " + err);
1487 List<string> valueArray = new List<string>();
1488 if (valuePtr != IntPtr.Zero)
1490 for (int i = 0; i < len; ++i)
1492 IntPtr charArr = Marshal.ReadIntPtr(valuePtr, IntPtr.Size * i);
1493 valueArray.Add(Marshal.PtrToStringAnsi(charArr));
1494 Marshal.FreeHGlobal(charArr);
1496 Marshal.FreeHGlobal(valuePtr);