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>
301 if (String.IsNullOrEmpty(_uri))
303 Interop.AppControl.ErrorCode err = Interop.AppControl.GetUri(_handle, out _uri);
304 if (err != Interop.AppControl.ErrorCode.None)
306 Log.Warn(LogTag, "Failed to get the uri from the appcontrol. Err = " + err);
313 Interop.AppControl.ErrorCode err = Interop.AppControl.SetUri(_handle, value);
314 if (err == Interop.AppControl.ErrorCode.None)
320 Log.Warn(LogTag, "Failed to set the uri to the appcontrol. Err = " + err);
326 /// Gets and sets the explicit category.
329 /// (if the category is null for setter, it clears the previous value.)
331 /// <since_tizen> 3 </since_tizen>
332 public string Category
336 if (String.IsNullOrEmpty(_category))
338 Interop.AppControl.ErrorCode err = Interop.AppControl.GetCategory(_handle, out _category);
339 if (err != Interop.AppControl.ErrorCode.None)
341 Log.Warn(LogTag, "Failed to get the category from the appcontrol. Err = " + err);
348 Interop.AppControl.ErrorCode err = Interop.AppControl.SetCategory(_handle, value);
349 if (err == Interop.AppControl.ErrorCode.None)
355 Log.Warn(LogTag, "Failed to set the category to the appcontrol. Err = " + err);
361 /// Gets and sets the application ID to explicitly launch.
364 /// (if the application ID is null for setter, it clears the previous value.)
368 /// AppControl appControl = new AppControl();
369 /// appControl.ApplicationId = "org.tizen.calculator";
370 /// Log.Debug(LogTag, "ApplicationId: " + appControl.ApplicationId);
373 /// <since_tizen> 3 </since_tizen>
374 public string ApplicationId
378 if (String.IsNullOrEmpty(_applicationId))
380 Interop.AppControl.ErrorCode err = Interop.AppControl.GetAppId(_handle, out _applicationId);
381 if (err != Interop.AppControl.ErrorCode.None)
383 Log.Warn(LogTag, "Failed to get the application id from the AppControl. Err = " + err);
386 return _applicationId;
390 Interop.AppControl.ErrorCode err = Interop.AppControl.SetAppId(_handle, value);
391 if (err == Interop.AppControl.ErrorCode.None)
393 _applicationId = value;
397 Log.Warn(LogTag, "Failed to set the application id to the AppControl. Err = " + err);
403 /// Gets and sets the launch mode of the application.
406 /// Although, LaunchMode were set as AppControlLaunchMode.Group, the
407 /// callee application would be launched as a single mode
408 /// if the manifest file of callee application defined the launch mode as "single".
409 /// This property can just set the preference of the caller application to launch an application.
410 /// Sub-applications, which were launched as a group mode always have own process.
411 /// Since Tizen 3.0, if launch mode is not set in the caller application control,
412 /// this property returns the AppControlLaunchMode.Single launch mode.
416 /// AppControl appControl = new AppControl();
417 /// appControl.LaunchMode = AppControlLaunchMode.Group;
420 /// <since_tizen> 3 </since_tizen>
421 public AppControlLaunchMode LaunchMode
426 Interop.AppControl.ErrorCode err = Interop.AppControl.GetLaunchMode(_handle, out value);
427 if (err != Interop.AppControl.ErrorCode.None)
429 Log.Warn(LogTag, "Failed to get the LaunchMode from the AppControl. Err = " + err);
431 return (AppControlLaunchMode)value;
435 Interop.AppControl.ErrorCode err = Interop.AppControl.SetLaunchMode(_handle, (int)value);
436 if (err != Interop.AppControl.ErrorCode.None)
438 Log.Warn(LogTag, "Failed to set the LaunchMode to the AppControl. Err = " + err);
444 /// Gets the collection of the extra data.
447 /// Extra data for communication between AppControls.
451 /// AppControl appControl = new AppControl();
452 /// appControl.ExtraData.Add("key", "value");
456 /// <since_tizen> 3 </since_tizen>
457 public ExtraDataCollection ExtraData
461 if (_extraData == null)
462 _extraData = new ExtraDataCollection(_handle);
468 /// Gets and sets the component ID to explicitly launch a component.
471 /// (if the component ID is null for setter, it clears the previous value.)
472 /// From Tizen 5.5, a new application model is supported that is component-based application.
473 /// This property is for launching component-based application. If it's not set, the main component of component-based application will be launched.
474 /// If the target app is not component-based application, setting property is meaningless.
478 /// AppControl appControl = new AppControl();
479 /// appControl.ApplicationId = "org.tizen.component-based-app"; // component-based application
480 /// appControl.ComponentId = "org.tizen.frame-component";
481 /// AppControl.SendLaunchRequest(appControl);
484 /// <since_tizen> 6 </since_tizen>
485 public string ComponentId
489 if (String.IsNullOrEmpty(_componentId))
491 Interop.AppControl.ErrorCode err = Interop.AppControl.GetComponentId(_handle, out _componentId);
492 if (err != Interop.AppControl.ErrorCode.None)
494 Log.Warn(LogTag, "Failed to get the component id from the AppControl. Err = " + err);
501 Interop.AppControl.ErrorCode err = Interop.AppControl.SetComponentId(_handle, value);
502 if (err == Interop.AppControl.ErrorCode.None)
504 _componentId = value;
508 Log.Warn(LogTag, "Failed to set the component id to the AppControl. Err = " + err);
513 #endregion // Public Properties
516 /// Retrieves all applications that can be launched to handle the given app_control request.
518 /// <param name="control">The AppControl.</param>
519 /// <returns>ApplicationIds.</returns>
520 /// <exception cref="InvalidOperationException">Thrown when failed because of an invalid parameter.</exception>
523 /// IEnumerable<string> applicationIds = AppControl.GetMatchedApplicationIds(control);
524 /// if (applicationIds != null)
526 /// foreach (string id in applicationIds)
533 /// <since_tizen> 3 </since_tizen>
534 public static IEnumerable<string> GetMatchedApplicationIds(AppControl control)
538 throw new ArgumentNullException("control");
541 List<string> ids = new List<string>();
542 Interop.AppControl.AppMatchedCallback callback = (handle, applicationId, userData) =>
544 if (applicationId == null)
549 ids.Add(applicationId);
553 Interop.AppControl.ErrorCode err = Interop.AppControl.ForeachAppMatched(control._handle, callback, IntPtr.Zero);
554 if (err != Interop.AppControl.ErrorCode.None)
556 throw new InvalidOperationException("Failed to get matched application ids. err = " + err);
563 /// Sends the launch request.
566 /// The operation is mandatory information for the launch request.
567 /// If the operation is not specified, AppControlOperations.Default is used by default.
568 /// If the operation is AppControlOperations.Default, the application ID is mandatory to explicitly launch the application.<br/>
569 /// Since Tizen 2.4, the launch request of the service application over out of packages is restricted by the platform.
570 /// Also, implicit launch requests are NOT delivered to service applications since 2.4.
571 /// To launch a service application, an explicit launch request with the application ID given by property ApplicationId MUST be sent.
573 /// <param name="launchRequest">The AppControl.</param>
574 /// <exception cref="ArgumentNullException">Thrown when failed because of a null argument.</exception>
575 /// <exception cref="InvalidOperationException">Thrown when failed because of an invalid operation.</exception>
576 /// <exception cref="TimeoutException">Thrown when failed because of timeout.</exception>
577 /// <privilege>http://tizen.org/privilege/appmanager.launch</privilege>
580 /// AppControl appControl = new AppControl();
581 /// appControl.ApplicationId = "org.tizen.calculator";
582 /// AppControl.SendLaunchRequest(appControl);
585 /// <since_tizen> 3 </since_tizen>
586 public static void SendLaunchRequest(AppControl launchRequest)
588 SendLaunchRequest(launchRequest, null);
592 /// Sends the launch request with setting timeout.
595 /// The operation is mandatory information for the launch request.
596 /// If the operation is not specified, AppControlOperations.Default is used by default.
597 /// If the operation is AppControlOperations.Default, the application ID is mandatory to explicitly launch the application.<br/>
598 /// To launch a service application, an explicit launch request with the application ID given by property ApplicationId MUST be sent.<br/>
599 /// It can set receiving timeout interval using timeout parameter.
600 /// If there is an error that is not related to timeout, the error is returned immediately regardless of the timeout value.
602 /// <param name="launchRequest">The AppControl.</param>
603 /// <param name="timeout">The timeout in milliseconds, the timeout range is 5000 to 30000.</param>
604 /// <exception cref="ArgumentNullException">Thrown when failed because of a null argument.</exception>
605 /// <exception cref="InvalidOperationException">Thrown when failed because of an invalid operation.</exception>
606 /// <exception cref="TimeoutException">Thrown when failed because of timeout.</exception>
607 /// <privilege>http://tizen.org/privilege/appmanager.launch</privilege>
610 /// AppControl appControl = new AppControl();
611 /// appControl.ApplicationId = "org.tizen.calculator";
612 /// AppControl.SendLaunchRequest(appControl, 10000);
615 /// <since_tizen> 7.5 </since_tizen>
616 [EditorBrowsable(EditorBrowsableState.Never)]
617 public static void SendLaunchRequest(AppControl launchRequest, uint timeout)
619 SendLaunchRequest(launchRequest, timeout, null);
623 /// Sends the launch request.
626 /// The operation is mandatory information for the launch request.
627 /// If the operation is not specified, AppControlOperations.Default is used by default.
628 /// If the operation is AppControlOperations.Default, the application ID is mandatory to explicitly launch the application.<br/>
629 /// Since Tizen 2.4, the launch request of the service application over out of packages is restricted by the platform.
630 /// Also, implicit launch requests are NOT delivered to service applications since 2.4.
631 /// To launch a service application, an explicit launch request with the application ID given by property ApplicationId MUST be sent.
633 /// <param name="launchRequest">The AppControl.</param>
634 /// <param name="replyAfterLaunching">The callback function to be called when the reply is delivered.</param>
635 /// <exception cref="ArgumentException">Thrown when failed because of the argument is invalid.</exception>
636 /// <exception cref="Exceptions.AppNotFoundException">Thrown when the application to run is not found.</exception>
637 /// <exception cref="Exceptions.LaunchFailedException">Thrown when the request failed to launch the application.</exception>
638 /// <exception cref="Exceptions.LaunchRejectedException">Thrown when the launch request is rejected.</exception>
639 /// <exception cref="Exceptions.OutOfMemoryException">Thrown when the memory is insufficient.</exception>
640 /// <exception cref="Exceptions.PermissionDeniedException">Thrown when the permission is denied.</exception>
641 /// <exception cref="TimeoutException">Thrown when failed because of timeout.</exception>
642 /// <privilege>http://tizen.org/privilege/appmanager.launch</privilege>
645 /// AppControl appControl = new AppControl();
646 /// appControl.ApplicationId = "org.tizen.calculator";
647 /// AppControl.SendLaunchRequest(appControl, (launchRequest, replyRequest, result) => {
652 /// <since_tizen> 3 </since_tizen>
653 public static void SendLaunchRequest(AppControl launchRequest, AppControlReplyCallback replyAfterLaunching)
655 if (launchRequest == null)
657 throw new ArgumentNullException("launchRequest");
660 Interop.AppControl.ErrorCode err;
662 if (replyAfterLaunching != null)
665 lock (s_replyCallbackMaps)
668 s_replyCallbackMaps[id] = replyAfterLaunching;
670 err = Interop.AppControl.SendLaunchRequest(launchRequest._handle, s_replyNativeCallback, (IntPtr)id);
674 err = Interop.AppControl.SendLaunchRequest(launchRequest._handle, null, IntPtr.Zero);
677 if (err != Interop.AppControl.ErrorCode.None)
681 case Interop.AppControl.ErrorCode.InvalidParameter:
682 throw new ArgumentException("Invalid Arguments");
683 case Interop.AppControl.ErrorCode.TimedOut:
684 throw new TimeoutException("Timed out");
685 case Interop.AppControl.ErrorCode.OutOfMemory:
686 throw new Exceptions.OutOfMemoryException("Out-of-memory");
687 case Interop.AppControl.ErrorCode.AppNotFound:
688 throw new Exceptions.AppNotFoundException("App(" + launchRequest.ApplicationId + ") not found. Operation(" + launchRequest.Operation + ")");
689 case Interop.AppControl.ErrorCode.LaunchRejected:
690 throw new Exceptions.LaunchRejectedException("Launch rejected");
691 case Interop.AppControl.ErrorCode.LaunchFailed:
692 throw new Exceptions.LaunchFailedException("Launch failed");
693 case Interop.AppControl.ErrorCode.PermissionDenied:
694 throw new Exceptions.PermissionDeniedException("Permission denied");
697 throw new Exceptions.LaunchRejectedException("Launch rejected");
703 /// Sends the launch request with setting timeout
706 /// The operation is mandatory information for the launch request.
707 /// If the operation is not specified, AppControlOperations.Default is used by default.
708 /// If the operation is AppControlOperations.Default, the application ID is mandatory to explicitly launch the application.<br/>
709 /// To launch a service application, an explicit launch request with the application ID given by property ApplicationId MUST be sent.<br/>
710 /// It can set receiving timeout interval using timeout parameter.
711 /// If there is an error that is not related to timeout, the error is returned immediately regardless of the timeout value.
713 /// <param name="launchRequest">The AppControl.</param>
714 /// <param name="timeout">The timeout in milliseconds, the timeout range is 5000 to 30000.</param>
715 /// <param name="replyAfterLaunching">The callback function to be called when the reply is delivered.</param>
716 /// <exception cref="ArgumentException">Thrown when failed because of the argument is invalid.</exception>
717 /// <exception cref="Exceptions.AppNotFoundException">Thrown when the application to run is not found.</exception>
718 /// <exception cref="Exceptions.LaunchFailedException">Thrown when the request failed to launch the application.</exception>
719 /// <exception cref="Exceptions.LaunchRejectedException">Thrown when the launch request is rejected.</exception>
720 /// <exception cref="Exceptions.OutOfMemoryException">Thrown when the memory is insufficient.</exception>
721 /// <exception cref="Exceptions.PermissionDeniedException">Thrown when the permission is denied.</exception>
722 /// <exception cref="TimeoutException">Thrown when failed because of timeout. The timeout interval is set by timeout parameter.</exception>
723 /// <privilege>http://tizen.org/privilege/appmanager.launch</privilege>
726 /// AppControl appControl = new AppControl();
727 /// appControl.ApplicationId = "org.tizen.calculator";
728 /// AppControl.SendLaunchRequest(appControl, 10000, (launchRequest, replyRequest, result) => {
733 /// <since_tizen> 7.5 </since_tizen>
734 [EditorBrowsable(EditorBrowsableState.Never)]
735 public static void SendLaunchRequest(AppControl launchRequest, uint timeout, AppControlReplyCallback replyAfterLaunching)
737 if (launchRequest == null)
739 throw new ArgumentNullException("launchRequest");
742 Interop.AppControl.ErrorCode err;
744 if (replyAfterLaunching != null)
747 lock (s_replyCallbackMaps)
750 s_replyCallbackMaps[id] = replyAfterLaunching;
752 err = Interop.AppControl.SendLaunchRequestWithTimeout(launchRequest._handle, timeout, s_replyNativeCallback, (IntPtr)id);
756 err = Interop.AppControl.SendLaunchRequestWithTimeout(launchRequest._handle, timeout, null, IntPtr.Zero);
759 if (err != Interop.AppControl.ErrorCode.None)
763 case Interop.AppControl.ErrorCode.InvalidParameter:
764 throw new ArgumentException("Invalid Arguments");
765 case Interop.AppControl.ErrorCode.TimedOut:
766 throw new TimeoutException("Timed out");
767 case Interop.AppControl.ErrorCode.OutOfMemory:
768 throw new Exceptions.OutOfMemoryException("Out-of-memory");
769 case Interop.AppControl.ErrorCode.AppNotFound:
770 throw new Exceptions.AppNotFoundException("App(" + launchRequest.ApplicationId + ") not found. Operation(" + launchRequest.Operation + ")");
771 case Interop.AppControl.ErrorCode.LaunchRejected:
772 throw new Exceptions.LaunchRejectedException("Launch rejected");
773 case Interop.AppControl.ErrorCode.LaunchFailed:
774 throw new Exceptions.LaunchFailedException("Launch failed");
775 case Interop.AppControl.ErrorCode.PermissionDenied:
776 throw new Exceptions.PermissionDeniedException("Permission denied");
779 throw new Exceptions.LaunchRejectedException("Launch rejected");
785 /// Sends the terminate request to the application that is launched by AppControl.
788 /// You are not allowed to terminate other general applications using this API.
789 /// This API can be used to terminate sub-applications, which were launched as a group mode by the caller application.
790 /// Once the callee application is being terminated by this API,
791 /// other applications, which were launched by the callee application as a group mode will be terminated as well.
793 /// <param name="terminateRequest">The AppControl.</param>
794 /// <exception cref="ArgumentException">Thrown when failed because of the argument is invalid.</exception>
795 /// <exception cref="InvalidOperationException">Thrown when failed because of an invalid operation.</exception>
796 /// <exception cref="TimeoutException">Thrown when failed because of timeout.</exception>
799 /// AppControl terminateRequest = new AppControl();
800 /// terminateRequest.ApplicationId = "org.tizen.calculator";
801 /// AppControl.SendTerminateRequest(terminateRequest);
804 /// <since_tizen> 3 </since_tizen>
805 public static void SendTerminateRequest(AppControl terminateRequest)
807 if (terminateRequest == null)
809 throw new ArgumentNullException("terminateRequest");
811 Interop.AppControl.ErrorCode err;
813 err = Interop.AppControl.SendTerminateRequest(terminateRequest._handle);
815 if (err != Interop.AppControl.ErrorCode.None)
819 case Interop.AppControl.ErrorCode.InvalidParameter:
820 throw new ArgumentException("Invalid Arguments");
821 case Interop.AppControl.ErrorCode.TimedOut:
822 throw new TimeoutException("Timed out");
824 throw new InvalidOperationException("Error = " + err);
830 /// Sends the launch request asynchronously.
833 /// The operation is mandatory information for the launch request.
834 /// If the operation is not specified, AppControlOperations.Default is used by default.
835 /// If the operation is AppControlOperations.Default, the application ID is mandatory to explicitly launch the application.<br/>
836 /// Since Tizen 2.4, the launch request of the service application over out of packages is restricted by the platform.
837 /// Also, implicit launch requests are NOT delivered to service applications since 2.4.
838 /// To launch a service application, an explicit launch request with the application ID given by property ApplicationId MUST be sent.
840 /// <param name="launchRequest">The AppControl.</param>
841 /// <param name="replyAfterLaunching">The callback function to be called when the reply is delivered.</param>
842 /// <returns>A task with the result of the launch request.</returns>
843 /// <exception cref="ArgumentException">Thrown when failed because of the argument is invalid.</exception>
844 /// <exception cref="Exceptions.AppNotFoundException">Thrown when the application to run is not found.</exception>
845 /// <exception cref="Exceptions.LaunchRejectedException">Thrown when the launch request is rejected.</exception>
846 /// <privilege>http://tizen.org/privilege/appmanager.launch</privilege>
847 /// <since_tizen> 6 </since_tizen>
848 public static Task<AppControlResult> SendLaunchRequestAsync(AppControl launchRequest, AppControlReplyCallback replyAfterLaunching)
850 if (launchRequest == null)
852 throw new ArgumentNullException(nameof(launchRequest));
855 var task = new TaskCompletionSource<AppControlResult>();
856 Interop.AppControl.ErrorCode err;
859 lock (s_resultNativeCallbackMaps)
861 requestId = s_reaustId++;
862 s_resultNativeCallbackMaps[requestId] = (handle, result, userData) =>
864 task.SetResult((AppControlResult)result);
865 lock (s_resultNativeCallbackMaps)
867 s_resultNativeCallbackMaps.Remove((int)userData);
872 if (replyAfterLaunching != null)
874 lock (s_replyCallbackMaps)
876 s_replyCallbackMaps[requestId] = replyAfterLaunching;
878 err = Interop.AppControl.SendLaunchRequestAsync(launchRequest.SafeAppControlHandle, s_resultNativeCallbackMaps[requestId], s_replyNativeCallback, (IntPtr)requestId);
882 err = Interop.AppControl.SendLaunchRequestAsync(launchRequest.SafeAppControlHandle, s_resultNativeCallbackMaps[requestId], null, (IntPtr)requestId);
885 if (err != Interop.AppControl.ErrorCode.None)
889 case Interop.AppControl.ErrorCode.InvalidParameter:
890 throw new ArgumentException("Invalid Arguments");
891 case Interop.AppControl.ErrorCode.AppNotFound:
892 throw new Exceptions.AppNotFoundException("App(" + launchRequest.ApplicationId + ") not found. Operation(" + launchRequest.Operation + ")");
893 case Interop.AppControl.ErrorCode.LaunchRejected:
894 throw new Exceptions.LaunchRejectedException("Launch rejected");
895 case Interop.AppControl.ErrorCode.PermissionDenied:
896 throw new Exceptions.PermissionDeniedException("Permission denied");
899 throw new Exceptions.LaunchRejectedException("Launch rejected");
907 /// Sets the auto restart.
910 /// The functionality of this method only applies to the caller application.
911 /// The auto restart cannot be applied to other applications. The application ID set in the AppControl is ignored.
912 /// This method is only available for platform level signed applications.
914 /// <param name="appControl">The AppControl.</param>
915 /// <exception cref="ArgumentNullException">Thrown when the argument is null.</exception>
916 /// <exception cref="ArgumentException">Thrown when the argument is invalid.</exception>
917 /// <exception cref="Exceptions.PermissionDeniedException">Thrown when the permission is denied.</exception>
918 /// <exception cref="Exceptions.OutOfMemoryException">Thrown when the memory is insufficient.</exception>
919 /// <exception cref="InvalidOperationException">Thrown when the memory is insufficient.</exception>
920 [EditorBrowsable(EditorBrowsableState.Never)]
921 public static void SetAutoRestart(AppControl appControl)
923 if (appControl == null)
925 throw new ArgumentNullException(nameof(appControl));
928 Interop.AppControl.ErrorCode err = Interop.AppControl.SetAutoRestart(appControl.SafeAppControlHandle);
929 if (err != Interop.AppControl.ErrorCode.None)
933 case Interop.AppControl.ErrorCode.InvalidParameter:
934 throw new ArgumentException("Invalid arguments");
935 case Interop.AppControl.ErrorCode.PermissionDenied:
936 throw new Exceptions.PermissionDeniedException("Permission denied");
937 case Interop.AppControl.ErrorCode.OutOfMemory:
938 throw new Exceptions.OutOfMemoryException("Out of memory");
940 throw new InvalidOperationException("err = " + err);
946 /// Class for extra data.
948 /// <since_tizen> 3 </since_tizen>
949 public class ExtraDataCollection
951 private readonly SafeAppControlHandle _handle;
953 internal ExtraDataCollection(SafeAppControlHandle handle)
962 /// The function replaces any existing value for the given key.
964 /// <param name="key">The name of the extra data.</param>
965 /// <param name="value">The value associated with the given key.</param>
966 /// <exception cref="ArgumentNullException">Thrown when a key or a value is a zero-length string.</exception>
967 /// <exception cref="ArgumentException">Thrown when the application tries to use the same key with the system-defined key.</exception>
970 /// AppControl appControl = new AppControl();
971 /// appControl.ExtraData.Add("myKey", "myValue");
974 /// <since_tizen> 3 </since_tizen>
975 public void Add(string key, string value)
977 if (string.IsNullOrEmpty(key))
979 throw new ArgumentNullException("key");
981 if (string.IsNullOrEmpty(value))
983 throw new ArgumentNullException("value");
985 Interop.AppControl.ErrorCode err = Interop.AppControl.AddExtraData(_handle, key, value);
986 if (err != Interop.AppControl.ErrorCode.None)
990 case Interop.AppControl.ErrorCode.InvalidParameter:
991 throw new ArgumentException("Invalid parameter: key or value is a zero-length string");
992 case Interop.AppControl.ErrorCode.KeyRejected:
993 throw new ArgumentException("Key is rejected: the key is system-defined key.");
995 throw new InvalidOperationException("Error = " + err);
1001 /// Adds extra data.
1004 /// The function replaces any existing value for the given key.
1006 /// <param name="key">The name of the extra data.</param>
1007 /// <param name="value">The value associated with the given key.</param>
1008 /// <exception cref="ArgumentNullException">Thrown when key or value is a zero-length string.</exception>
1009 /// <exception cref="ArgumentException">Thrown when the application tries to use the same key with the system-defined key.</exception>
1012 /// AppControl appControl = new AppControl();
1013 /// string[] myValues = new string[] { "first", "second", "third" };
1014 /// appControl.ExtraData.Add("myKey", myValues);
1017 /// <since_tizen> 3 </since_tizen>
1018 public void Add(string key, IEnumerable<string> value)
1020 if (string.IsNullOrEmpty(key))
1022 throw new ArgumentNullException("key");
1026 throw new ArgumentNullException("value");
1028 string[] valueArray = value.ToArray();
1029 Interop.AppControl.ErrorCode err = Interop.AppControl.AddExtraDataArray(_handle, key, valueArray, valueArray.Length);
1030 if (err != Interop.AppControl.ErrorCode.None)
1034 case Interop.AppControl.ErrorCode.InvalidParameter:
1035 throw new ArgumentException("Invalid parameter: key or value is a zero-length string");
1036 case Interop.AppControl.ErrorCode.KeyRejected:
1037 throw new ArgumentException("Key is rejected: the key is system-defined key.");
1039 throw new InvalidOperationException("Error = " + err);
1045 /// Gets the extra data.
1047 /// <typeparam name="T">Only string and IEnumerable<string></typeparam>
1048 /// <param name="key">The name of extra data.</param>
1049 /// <returns>The value associated with the given key.</returns>
1050 /// <exception cref="ArgumentNullException">Thrown when the key is an invalid parameter.</exception>
1051 /// <exception cref="KeyNotFoundException">Thrown when the key is not found.</exception>
1052 /// <exception cref="ArgumentException">Thrown when the key is rejected.</exception>
1055 /// AppControl appControl = new AppControl();
1056 /// string myValue = appControl.ExtraData.Get<string>("myKey");
1059 /// <since_tizen> 3 </since_tizen>
1060 public T Get<T>(string key)
1062 object ret = Get(key);
1067 /// Gets the extra data.
1069 /// <param name="key">The name of extra data.</param>
1070 /// <returns>The value associated with the given key.</returns>
1071 /// <exception cref="ArgumentNullException">Thrown when the key is an invalid parameter.</exception>
1072 /// <exception cref="KeyNotFoundException">Thrown when the key is not found.</exception>
1073 /// <exception cref="ArgumentException">Thrown when the key is rejected.</exception>
1076 /// AppControl appControl = new AppControl();
1077 /// string myValue = appControl.ExtraData.Get("myKey") as string;
1078 /// if (myValue != null)
1084 /// <since_tizen> 3 </since_tizen>
1085 public object Get(string key)
1087 if (IsCollection(key))
1089 return GetDataCollection(key);
1093 return GetData(key);
1098 /// Gets all keys in extra data.
1100 /// <returns>The keys in the AppControl.</returns>
1101 /// <exception cref="InvalidOperationException">Thrown when the key is an invalid parameter.</exception>
1104 /// AppControl appControl = new AppControl();
1105 /// IEnumerable<string> keys = appControl.GetKeys();
1106 /// if (keys != null)
1108 /// foreach (string key in keys)
1115 /// <since_tizen> 3 </since_tizen>
1116 public IEnumerable<string> GetKeys()
1118 List<string> keys = new List<string>();
1119 Interop.AppControl.ExtraDataCallback callback = (handle, key, userData) =>
1130 Interop.AppControl.ErrorCode err = Interop.AppControl.ForeachExtraData(_handle, callback, IntPtr.Zero);
1131 if (err != Interop.AppControl.ErrorCode.None)
1133 throw new InvalidOperationException("Failed to get keys. err = " + err);
1140 /// Tries getting the extra data.
1142 /// <param name="key">The name of extra data.</param>
1143 /// <param name="value">The value associated with the given key.</param>
1144 /// <returns>The result whether getting the value is done.</returns>
1145 /// <exception cref="ArgumentNullException">Thrown when the key is an invalid parameter.</exception>
1146 /// <exception cref="KeyNotFoundException">Thrown when the key is not found.</exception>
1147 /// <exception cref="ArgumentException">Thrown when the key is rejected.</exception>
1150 /// AppControl appControl = new AppControl();
1151 /// string myValue = string.Empty;
1152 /// bool result = appControl.ExtraData.TryGet("myKey", out myValue);
1153 /// if (result != null)
1159 /// <since_tizen> 3 </since_tizen>
1160 public bool TryGet(string key, out string value)
1162 if (string.IsNullOrEmpty(key))
1164 throw new ArgumentNullException("key");
1166 Interop.AppControl.GetExtraData(_handle, key, out value);
1173 value = default(string);
1179 /// Tries getting the extra data.
1181 /// <param name="key">The name of extra data.</param>
1182 /// <param name="value">The value associated with the given key.</param>
1183 /// <returns>The result whether getting the value is done.</returns>
1184 /// <exception cref="ArgumentNullException">Thrown when the key is an invalid parameter.</exception>
1185 /// <exception cref="KeyNotFoundException">Thrown when the key is not found.</exception>
1186 /// <exception cref="ArgumentException">Thrown when the key is rejected.</exception>
1189 /// AppControl appControl = new AppControl();
1190 /// IEnumerable<string> myValue = null;
1191 /// bool result = appControl.ExtraData.TryGet("myKey", out myValue);
1194 /// foreach (string value in myValue)
1201 /// <since_tizen> 3 </since_tizen>
1202 public bool TryGet(string key, out IEnumerable<string> value)
1204 if (string.IsNullOrEmpty(key))
1206 throw new ArgumentNullException("key");
1208 IntPtr valuePtr = IntPtr.Zero;
1210 Interop.AppControl.ErrorCode err = Interop.AppControl.GetExtraDataArray(_handle, key, out valuePtr, out len);
1211 if (err == Interop.AppControl.ErrorCode.None && valuePtr != IntPtr.Zero)
1213 List<string> stringList = new List<string>();
1214 for (int i = 0; i < len; ++i)
1216 IntPtr charArr = Marshal.ReadIntPtr(valuePtr, IntPtr.Size * i);
1217 stringList.Add(Marshal.PtrToStringAnsi(charArr));
1218 Interop.Libc.Free(charArr);
1220 Interop.Libc.Free(valuePtr);
1226 value = default(IEnumerable<string>);
1232 /// Removes the extra data.
1234 /// <param name="key">The name of the extra data.</param>
1235 /// <exception cref="ArgumentNullException">Thrown when the key is a zero-length string.</exception>
1236 /// <exception cref="KeyNotFoundException">Thrown when the key is not found.</exception>
1237 /// <exception cref="ArgumentException">Thrown when the key is rejected.</exception>
1240 /// AppControl appControl = new AppControl();
1241 /// appControl.ExtraData.Remove("myKey");
1244 /// <since_tizen> 3 </since_tizen>
1245 public void Remove(string key)
1247 if (string.IsNullOrEmpty(key))
1249 throw new ArgumentNullException("key");
1251 Interop.AppControl.ErrorCode err = Interop.AppControl.RemoveExtraData(_handle, key);
1252 if (err != Interop.AppControl.ErrorCode.None)
1256 case Interop.AppControl.ErrorCode.InvalidParameter:
1257 throw new ArgumentException("Invalid parameter: key is a zero-length string");
1258 case Interop.AppControl.ErrorCode.KeyNotFound:
1259 throw new KeyNotFoundException("Key is not found"); ;
1260 case Interop.AppControl.ErrorCode.KeyRejected:
1261 throw new ArgumentException("Key is rejected: the key is system-defined key.");
1263 throw new InvalidOperationException("Error = " + err);
1269 /// Counts keys in the extra data.
1271 /// <returns>The number of counting keys.</returns>
1272 /// <exception cref="InvalidOperationException">Thrown when the key is an invalid parameter.</exception>
1275 /// AppControl appControl = new AppControl();
1276 /// int numberOfKeys = appControl.ExtraData.Count();
1279 /// <since_tizen> 3 </since_tizen>
1282 return GetKeys().Count();
1286 /// Checks whether the extra data associated with the given key is of the collection data type.
1288 /// <param name="key">The name of the extra data.</param>
1289 /// <returns>If true, the extra data is of the array data type, otherwise false.</returns>
1290 /// <exception cref="ArgumentNullException">Thrown when the key is a zero-length string.</exception>
1291 /// <exception cref="InvalidOperationException">Thrown when failed to check the key.</exception>
1294 /// AppControl appControl = new AppControl();
1295 /// bool result = appControl.ExtraData.IsCollection("myKey");
1298 /// <since_tizen> 3 </since_tizen>
1299 public bool IsCollection(string key)
1301 if (string.IsNullOrEmpty(key))
1303 throw new ArgumentNullException("key");
1305 bool isArray = false;
1306 Interop.AppControl.ErrorCode err = Interop.AppControl.IsExtraDataArray(_handle, key, out isArray);
1307 if (err != Interop.AppControl.ErrorCode.None)
1309 throw new InvalidOperationException("Error = " + err);
1314 private string GetData(string key)
1316 if (string.IsNullOrEmpty(key))
1318 throw new ArgumentNullException("key");
1320 string value = string.Empty;
1321 Interop.AppControl.ErrorCode err = Interop.AppControl.GetExtraData(_handle, key, out value);
1322 if (err != Interop.AppControl.ErrorCode.None)
1326 case Interop.AppControl.ErrorCode.InvalidParameter:
1327 throw new ArgumentException("Invalid parameter: key is a zero-length string");
1328 case Interop.AppControl.ErrorCode.KeyNotFound:
1329 throw new KeyNotFoundException("Key is not found"); ;
1330 case Interop.AppControl.ErrorCode.InvalidDataType:
1331 throw new ArgumentException("Invalid data type: value is data collection type");
1332 case Interop.AppControl.ErrorCode.KeyRejected:
1333 throw new ArgumentException("Key is rejected: the key is system-defined key.");
1335 throw new InvalidOperationException("Error = " + err);
1341 private IEnumerable<string> GetDataCollection(string key)
1343 if (string.IsNullOrEmpty(key))
1345 throw new ArgumentNullException("key");
1347 IntPtr valuePtr = IntPtr.Zero;
1349 Interop.AppControl.ErrorCode err = Interop.AppControl.GetExtraDataArray(_handle, key, out valuePtr, out len);
1350 if (err != Interop.AppControl.ErrorCode.None)
1354 case Interop.AppControl.ErrorCode.InvalidParameter:
1355 throw new ArgumentException("Invalid parameter: key is a zero-length string");
1356 case Interop.AppControl.ErrorCode.KeyNotFound:
1357 throw new KeyNotFoundException("Key is not found"); ;
1358 case Interop.AppControl.ErrorCode.InvalidDataType:
1359 throw new ArgumentException("Invalid data type: value is data collection type");
1360 case Interop.AppControl.ErrorCode.KeyRejected:
1361 throw new ArgumentException("Key is rejected: the key is system-defined key.");
1363 throw new InvalidOperationException("Error = " + err);
1367 List<string> valueArray = new List<string>();
1368 if (valuePtr != IntPtr.Zero)
1370 for (int i = 0; i < len; ++i)
1372 IntPtr charArr = Marshal.ReadIntPtr(valuePtr, IntPtr.Size * i);
1373 valueArray.Add(Marshal.PtrToStringAnsi(charArr));
1374 Interop.Libc.Free(charArr);
1376 Interop.Libc.Free(valuePtr);