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("handle");
114 Interop.AppControl.ErrorCode err = Interop.AppControl.DangerousClone(out _handle, handle.DangerousGetHandle());
115 if (err != Interop.AppControl.ErrorCode.None)
117 throw new InvalidOperationException("Failed to clone the appcontrol handle. Err = " + err);
121 private AppControl(IntPtr handle)
123 Interop.AppControl.ErrorCode err = Interop.AppControl.DangerousClone(out _handle, handle);
124 if (err != Interop.AppControl.ErrorCode.None)
126 throw new InvalidOperationException("Failed to clone the appcontrol handle. Err = " + err);
130 private static Interop.AppControl.ReplyCallback s_replyNativeCallback = (launchHandle, replyHandle, result, userData) =>
132 int requestId = (int)userData;
133 lock (s_replyCallbackMaps)
135 if (s_replyCallbackMaps.ContainsKey(requestId))
137 s_replyCallbackMaps[requestId](new AppControl(launchHandle), new AppControl(replyHandle), (AppControlReplyResult)result);
138 if (result != Interop.AppControl.AppStartedStatus)
140 s_replyCallbackMaps.Remove(requestId);
146 #region Public Properties
149 /// Gets the SafeAppControlHandle instance.
151 /// <since_tizen> 3 </since_tizen>
152 public SafeAppControlHandle SafeAppControlHandle
161 /// Gets and sets the operation to be performed.
164 /// The operation is the mandatory information for the launch request. If the operation is not specified,
165 /// AppControlOperations.Default is used for the launch request. If the operation is AppControlOperations.Default,
166 /// the package information is mandatory to explicitly launch the application.
167 /// (if the operation is null for setter, it clears the previous value.)
171 /// AppControl appControl = new AppControl();
172 /// appControl.Operation = AppControlOperations.Default;
173 /// Log.Debug(LogTag, "Operation: " + appControl.Operation);
176 /// <since_tizen> 3 </since_tizen>
177 public string Operation
181 if (String.IsNullOrEmpty(_operation))
183 Interop.AppControl.ErrorCode err = Interop.AppControl.GetOperation(_handle, out _operation);
184 if (err != Interop.AppControl.ErrorCode.None)
186 Log.Warn(LogTag, "Failed to get the operation from the appcontrol. Err = " + err);
193 Interop.AppControl.ErrorCode err = Interop.AppControl.SetOperation(_handle, value);
194 if (err == Interop.AppControl.ErrorCode.None)
200 Log.Warn(LogTag, "Failed to set the operation to the appcontrol. Err = " + err);
206 /// Gets and sets the explicit MIME type of the data.
209 /// (if the mime is null for setter, it clears the previous value.)
213 /// AppControl appControl = new AppControl();
214 /// appControl.Mime = "image/jpg";
215 /// Log.Debug(LogTag, "Mime: " + appControl.Mime);
218 /// <since_tizen> 3 </since_tizen>
223 if (String.IsNullOrEmpty(_mime))
225 Interop.AppControl.ErrorCode err = Interop.AppControl.GetMime(_handle, out _mime);
226 if (err != Interop.AppControl.ErrorCode.None)
228 Log.Warn(LogTag, "Failed to get the mime from the appcontrol. Err = " + err);
235 Interop.AppControl.ErrorCode err = Interop.AppControl.SetMime(_handle, value);
236 if (err == Interop.AppControl.ErrorCode.None)
242 Log.Warn(LogTag, "Failed to set the mime to the appcontrol. Err = " + err);
248 /// Gets and sets the URI of the data.
251 /// Since Tizen 2.4, if the parameter 'uri' is started with 'file://' and
252 /// it is a regular file in this application's data path, which can be obtained
253 /// by property DataPath in ApplicationInfo class,
254 /// it will be shared to the callee application.
255 /// Framework will grant a temporary permission to the callee application for this file and
256 /// revoke it when the callee application is terminated.
257 /// The callee application can just read it.
258 /// (if the uri is null for setter, it clears the previous value.)
262 /// public class AppControlExample : UIApplication
265 /// protected override void OnAppControlReceived(AppControlReceivedEventArgs e)
268 /// AppControl appControl = new AppControl();
269 /// appContrl.Uri = this.ApplicationInfo.DataPath + "image.jpg";
270 /// Log.Debug(LogTag, "Set Uri: " + appControl.Uri);
275 /// <since_tizen> 3 </since_tizen>
280 if (String.IsNullOrEmpty(_uri))
282 Interop.AppControl.ErrorCode err = Interop.AppControl.GetUri(_handle, out _uri);
283 if (err != Interop.AppControl.ErrorCode.None)
285 Log.Warn(LogTag, "Failed to get the uri from the appcontrol. Err = " + err);
292 Interop.AppControl.ErrorCode err = Interop.AppControl.SetUri(_handle, value);
293 if (err == Interop.AppControl.ErrorCode.None)
299 Log.Warn(LogTag, "Failed to set the uri to the appcontrol. Err = " + err);
305 /// Gets and sets the explicit category.
308 /// (if the category is null for setter, it clears the previous value.)
310 /// <since_tizen> 3 </since_tizen>
311 public string Category
315 if (String.IsNullOrEmpty(_category))
317 Interop.AppControl.ErrorCode err = Interop.AppControl.GetCategory(_handle, out _category);
318 if (err != Interop.AppControl.ErrorCode.None)
320 Log.Warn(LogTag, "Failed to get the category from the appcontrol. Err = " + err);
327 Interop.AppControl.ErrorCode err = Interop.AppControl.SetCategory(_handle, value);
328 if (err == Interop.AppControl.ErrorCode.None)
334 Log.Warn(LogTag, "Failed to set the category to the appcontrol. Err = " + err);
340 /// Gets and sets the application ID to explicitly launch.
343 /// (if the application ID is null for setter, it clears the previous value.)
347 /// AppControl appControl = new AppControl();
348 /// appControl.ApplicationId = "org.tizen.calculator";
349 /// Log.Debug(LogTag, "ApplicationId: " + appControl.ApplicationId);
352 /// <since_tizen> 3 </since_tizen>
353 public string ApplicationId
357 if (String.IsNullOrEmpty(_applicationId))
359 Interop.AppControl.ErrorCode err = Interop.AppControl.GetAppId(_handle, out _applicationId);
360 if (err != Interop.AppControl.ErrorCode.None)
362 Log.Warn(LogTag, "Failed to get the application id from the AppControl. Err = " + err);
365 return _applicationId;
369 Interop.AppControl.ErrorCode err = Interop.AppControl.SetAppId(_handle, value);
370 if (err == Interop.AppControl.ErrorCode.None)
372 _applicationId = value;
376 Log.Warn(LogTag, "Failed to set the application id to the AppControl. Err = " + err);
382 /// Gets and sets the launch mode of the application.
385 /// Although, LaunchMode were set as AppControlLaunchMode.Group, the
386 /// callee application would be launched as a single mode
387 /// if the manifest file of callee application defined the launch mode as "single".
388 /// This property can just set the preference of the caller application to launch an application.
389 /// Sub-applications, which were launched as a group mode always have own process.
390 /// Since Tizen 3.0, if launch mode is not set in the caller application control,
391 /// this property returns the AppControlLaunchMode.Single launch mode.
395 /// AppControl appControl = new AppControl();
396 /// appControl.LaunchMode = AppControlLaunchMode.Group;
399 /// <since_tizen> 3 </since_tizen>
400 public AppControlLaunchMode LaunchMode
405 Interop.AppControl.ErrorCode err = Interop.AppControl.GetLaunchMode(_handle, out value);
406 if (err != Interop.AppControl.ErrorCode.None)
408 Log.Warn(LogTag, "Failed to get the LaunchMode from the AppControl. Err = " + err);
410 return (AppControlLaunchMode)value;
414 Interop.AppControl.ErrorCode err = Interop.AppControl.SetLaunchMode(_handle, (int)value);
415 if (err != Interop.AppControl.ErrorCode.None)
417 Log.Warn(LogTag, "Failed to set the LaunchMode to the AppControl. Err = " + err);
423 /// Gets the collection of the extra data.
426 /// Extra data for communication between AppControls.
430 /// AppControl appControl = new AppControl();
431 /// appControl.ExtraData.Add("key", "value");
435 /// <since_tizen> 3 </since_tizen>
436 public ExtraDataCollection ExtraData
440 if (_extraData == null)
441 _extraData = new ExtraDataCollection(_handle);
447 /// Gets and sets the component ID to explicitly launch a component.
450 /// (if the component ID is null for setter, it clears the previous value.)
451 /// From Tizen 5.5, a new application model is supported that is component-based application.
452 /// This property is for launching component-based application. If it's not set, the main component of component-based application will be launched.
453 /// If the target app is not component-based application, setting property is meaningless.
457 /// AppControl appControl = new AppControl();
458 /// appControl.ApplicationId = "org.tizen.component-based-app"; // component-based application
459 /// appControl.ComponentId = "org.tizen.frame-component";
460 /// AppControl.SendLaunchRequest(appControl);
463 /// <since_tizen> 6 </since_tizen>
464 public string ComponentId
468 if (String.IsNullOrEmpty(_componentId))
470 Interop.AppControl.ErrorCode err = Interop.AppControl.GetComponentId(_handle, out _componentId);
471 if (err != Interop.AppControl.ErrorCode.None)
473 Log.Warn(LogTag, "Failed to get the component id from the AppControl. Err = " + err);
480 Interop.AppControl.ErrorCode err = Interop.AppControl.SetComponentId(_handle, value);
481 if (err == Interop.AppControl.ErrorCode.None)
483 _componentId = value;
487 Log.Warn(LogTag, "Failed to set the component id to the AppControl. Err = " + err);
492 #endregion // Public Properties
495 /// Retrieves all applications that can be launched to handle the given app_control request.
497 /// <param name="control">The AppControl.</param>
498 /// <returns>ApplicationIds.</returns>
499 /// <exception cref="InvalidOperationException">Thrown when failed because of an invalid parameter.</exception>
502 /// IEnumerable<string> applicationIds = AppControl.GetMatchedApplicationIds(control);
503 /// if (applicationIds != null)
505 /// foreach (string id in applicationIds)
512 /// <since_tizen> 3 </since_tizen>
513 public static IEnumerable<string> GetMatchedApplicationIds(AppControl control)
517 throw new ArgumentNullException("control");
520 List<string> ids = new List<string>();
521 Interop.AppControl.AppMatchedCallback callback = (handle, applicationId, userData) =>
523 if (applicationId == null)
528 ids.Add(applicationId);
532 Interop.AppControl.ErrorCode err = Interop.AppControl.ForeachAppMatched(control._handle, callback, IntPtr.Zero);
533 if (err != Interop.AppControl.ErrorCode.None)
535 throw new InvalidOperationException("Failed to get matched application ids. err = " + err);
542 /// Sends the launch request.
545 /// The operation is mandatory information for the launch request.
546 /// If the operation is not specified, AppControlOperations.Default is used by default.
547 /// If the operation is AppControlOperations.Default, the application ID is mandatory to explicitly launch the application.<br/>
548 /// Since Tizen 2.4, the launch request of the service application over out of packages is restricted by the platform.
549 /// Also, implicit launch requests are NOT delivered to service applications since 2.4.
550 /// To launch a service application, an explicit launch request with the application ID given by property ApplicationId MUST be sent.
552 /// <param name="launchRequest">The AppControl.</param>
553 /// <exception cref="ArgumentNullException">Thrown when failed because of a null argument.</exception>
554 /// <exception cref="InvalidOperationException">Thrown when failed because of an invalid operation.</exception>
555 /// <exception cref="TimeoutException">Thrown when failed because of timeout.</exception>
556 /// <privilege>http://tizen.org/privilege/appmanager.launch</privilege>
559 /// AppControl appControl = new AppControl();
560 /// appControl.ApplicationId = "org.tizen.calculator";
561 /// AppControl.SendLaunchRequest(appControl);
564 /// <since_tizen> 3 </since_tizen>
565 public static void SendLaunchRequest(AppControl launchRequest)
567 SendLaunchRequest(launchRequest, null);
571 /// Sends the launch request.
574 /// The operation is mandatory information for the launch request.
575 /// If the operation is not specified, AppControlOperations.Default is used by default.
576 /// If the operation is AppControlOperations.Default, the application ID is mandatory to explicitly launch the application.<br/>
577 /// Since Tizen 2.4, the launch request of the service application over out of packages is restricted by the platform.
578 /// Also, implicit launch requests are NOT delivered to service applications since 2.4.
579 /// To launch a service application, an explicit launch request with the application ID given by property ApplicationId MUST be sent.
581 /// <param name="launchRequest">The AppControl.</param>
582 /// <param name="replyAfterLaunching">The callback function to be called when the reply is delivered.</param>
583 /// <exception cref="ArgumentException">Thrown when failed because of the argument is invalid.</exception>
584 /// <exception cref="Exceptions.AppNotFoundException">Thrown when the application to run is not found.</exception>
585 /// <exception cref="Exceptions.LaunchFailedException">Thrown when the request failed to launch the application.</exception>
586 /// <exception cref="Exceptions.LaunchRejectedException">Thrown when the launch request is rejected.</exception>
587 /// <exception cref="Exceptions.OutOfMemoryException">Thrown when the memory is insufficient.</exception>
588 /// <exception cref="Exceptions.PermissionDeniedException">Thrown when the permission is denied.</exception>
589 /// <exception cref="TimeoutException">Thrown when failed because of timeout.</exception>
590 /// <privilege>http://tizen.org/privilege/appmanager.launch</privilege>
593 /// AppControl appControl = new AppControl();
594 /// appControl.ApplicationId = "org.tizen.calculator";
595 /// AppControl.SendLaunchRequest(appControl, (launchRequest, replyRequest, result) => {
600 /// <since_tizen> 3 </since_tizen>
601 public static void SendLaunchRequest(AppControl launchRequest, AppControlReplyCallback replyAfterLaunching)
603 if (launchRequest == null)
605 throw new ArgumentNullException("launchRequest");
608 Interop.AppControl.ErrorCode err;
610 if (replyAfterLaunching != null)
613 lock (s_replyCallbackMaps)
616 s_replyCallbackMaps[id] = replyAfterLaunching;
618 err = Interop.AppControl.SendLaunchRequest(launchRequest._handle, s_replyNativeCallback, (IntPtr)id);
622 err = Interop.AppControl.SendLaunchRequest(launchRequest._handle, null, IntPtr.Zero);
625 if (err != Interop.AppControl.ErrorCode.None)
629 case Interop.AppControl.ErrorCode.InvalidParameter:
630 throw new ArgumentException("Invalid Arguments");
631 case Interop.AppControl.ErrorCode.TimedOut:
632 throw new TimeoutException("Timed out");
633 case Interop.AppControl.ErrorCode.OutOfMemory:
634 throw new Exceptions.OutOfMemoryException("Out-of-memory");
635 case Interop.AppControl.ErrorCode.AppNotFound:
636 throw new Exceptions.AppNotFoundException("App(" + launchRequest.ApplicationId + ") not found. Operation(" + launchRequest.Operation + ")");
637 case Interop.AppControl.ErrorCode.LaunchRejected:
638 throw new Exceptions.LaunchRejectedException("Launch rejected");
639 case Interop.AppControl.ErrorCode.LaunchFailed:
640 throw new Exceptions.LaunchFailedException("Launch failed");
641 case Interop.AppControl.ErrorCode.PermissionDenied:
642 throw new Exceptions.PermissionDeniedException("Permission denied");
645 throw new Exceptions.LaunchRejectedException("Launch rejected");
651 /// Sends the terminate request to the application that is launched by AppControl.
654 /// You are not allowed to terminate other general applications using this API.
655 /// This API can be used to terminate sub-applications, which were launched as a group mode by the caller application.
656 /// Once the callee application is being terminated by this API,
657 /// other applications, which were launched by the callee application as a group mode will be terminated as well.
659 /// <param name="terminateRequest">The AppControl.</param>
660 /// <exception cref="ArgumentException">Thrown when failed because of the argument is invalid.</exception>
661 /// <exception cref="InvalidOperationException">Thrown when failed because of an invalid operation.</exception>
662 /// <exception cref="TimeoutException">Thrown when failed because of timeout.</exception>
665 /// AppControl terminateRequest = new AppControl();
666 /// terminateRequest.ApplicationId = "org.tizen.calculator";
667 /// AppControl.SendTerminateRequest(terminateRequest);
670 /// <since_tizen> 3 </since_tizen>
671 public static void SendTerminateRequest(AppControl terminateRequest)
673 if (terminateRequest == null)
675 throw new ArgumentNullException("terminateRequest");
677 Interop.AppControl.ErrorCode err;
679 err = Interop.AppControl.SendTerminateRequest(terminateRequest._handle);
681 if (err != Interop.AppControl.ErrorCode.None)
685 case Interop.AppControl.ErrorCode.InvalidParameter:
686 throw new ArgumentException("Invalid Arguments");
687 case Interop.AppControl.ErrorCode.TimedOut:
688 throw new TimeoutException("Timed out");
690 throw new InvalidOperationException("Error = " + err);
696 /// Sends the launch request asynchronously.
699 /// The operation is mandatory information for the launch request.
700 /// If the operation is not specified, AppControlOperations.Default is used by default.
701 /// If the operation is AppControlOperations.Default, the application ID is mandatory to explicitly launch the application.<br/>
702 /// Since Tizen 2.4, the launch request of the service application over out of packages is restricted by the platform.
703 /// Also, implicit launch requests are NOT delivered to service applications since 2.4.
704 /// To launch a service application, an explicit launch request with the application ID given by property ApplicationId MUST be sent.
706 /// <param name="launchRequest">The AppControl.</param>
707 /// <param name="replyAfterLaunching">The callback function to be called when the reply is delivered.</param>
708 /// <returns>A task with the result of the launch request.</returns>
709 /// <exception cref="ArgumentException">Thrown when failed because of the argument is invalid.</exception>
710 /// <exception cref="Exceptions.AppNotFoundException">Thrown when the application to run is not found.</exception>
711 /// <exception cref="Exceptions.LaunchRejectedException">Thrown when the launch request is rejected.</exception>
712 /// <privilege>http://tizen.org/privilege/appmanager.launch</privilege>
713 /// <since_tizen> 6 </since_tizen>
714 public static Task<AppControlResult> SendLaunchRequestAsync(AppControl launchRequest, AppControlReplyCallback replyAfterLaunching)
716 if (launchRequest == null)
718 throw new ArgumentNullException(nameof(launchRequest));
721 var task = new TaskCompletionSource<AppControlResult>();
722 Interop.AppControl.ErrorCode err;
725 lock (s_resultNativeCallbackMaps)
727 requestId = s_reaustId++;
728 s_resultNativeCallbackMaps[requestId] = (handle, result, userData) =>
730 task.SetResult((AppControlResult)result);
731 lock (s_resultNativeCallbackMaps)
733 s_resultNativeCallbackMaps.Remove((int)userData);
738 if (replyAfterLaunching != null)
740 lock (s_replyCallbackMaps)
742 s_replyCallbackMaps[requestId] = replyAfterLaunching;
744 err = Interop.AppControl.SendLaunchRequestAsync(launchRequest.SafeAppControlHandle, s_resultNativeCallbackMaps[requestId], s_replyNativeCallback, (IntPtr)requestId);
748 err = Interop.AppControl.SendLaunchRequestAsync(launchRequest.SafeAppControlHandle, s_resultNativeCallbackMaps[requestId], null, (IntPtr)requestId);
751 if (err != Interop.AppControl.ErrorCode.None)
755 case Interop.AppControl.ErrorCode.InvalidParameter:
756 throw new ArgumentException("Invalid Arguments");
757 case Interop.AppControl.ErrorCode.AppNotFound:
758 throw new Exceptions.AppNotFoundException("App(" + launchRequest.ApplicationId + ") not found. Operation(" + launchRequest.Operation + ")");
759 case Interop.AppControl.ErrorCode.LaunchRejected:
760 throw new Exceptions.LaunchRejectedException("Launch rejected");
761 case Interop.AppControl.ErrorCode.PermissionDenied:
762 throw new Exceptions.PermissionDeniedException("Permission denied");
765 throw new Exceptions.LaunchRejectedException("Launch rejected");
773 /// Sets the auto restart.
776 /// The functionality of this method only applies to the caller application.
777 /// The auto restart cannot be applied to other applications. The application ID set in the AppControl is ignored.
778 /// This method is only available for platform level signed applications.
780 /// <param name="appControl">The AppControl.</param>
781 /// <exception cref="ArgumentNullException">Thrown when the argument is null.</exception>
782 /// <exception cref="ArgumentException">Thrown when the argument is invalid.</exception>
783 /// <exception cref="Exceptions.PermissionDeniedException">Thrown when the permission is denied.</exception>
784 /// <exception cref="Exceptions.OutOfMemoryException">Thrown when the memory is insufficient.</exception>
785 /// <exception cref="InvalidOperationException">Thrown when the memory is insufficient.</exception>
786 [EditorBrowsable(EditorBrowsableState.Never)]
787 public static void SetAutoRestart(AppControl appControl)
789 if (appControl == null)
791 throw new ArgumentNullException(nameof(appControl));
794 Interop.AppControl.ErrorCode err = Interop.AppControl.SetAutoRestart(appControl.SafeAppControlHandle);
795 if (err != Interop.AppControl.ErrorCode.None)
799 case Interop.AppControl.ErrorCode.InvalidParameter:
800 throw new ArgumentException("Invalid arguments");
801 case Interop.AppControl.ErrorCode.PermissionDenied:
802 throw new Exceptions.PermissionDeniedException("Permission denied");
803 case Interop.AppControl.ErrorCode.OutOfMemory:
804 throw new Exceptions.OutOfMemoryException("Out of memory");
806 throw new InvalidOperationException("err = " + err);
812 /// Class for extra data.
814 /// <since_tizen> 3 </since_tizen>
815 public class ExtraDataCollection
817 private readonly SafeAppControlHandle _handle;
819 internal ExtraDataCollection(SafeAppControlHandle handle)
828 /// The function replaces any existing value for the given key.
830 /// <param name="key">The name of the extra data.</param>
831 /// <param name="value">The value associated with the given key.</param>
832 /// <exception cref="ArgumentNullException">Thrown when a key or a value is a zero-length string.</exception>
833 /// <exception cref="ArgumentException">Thrown when the application tries to use the same key with the system-defined key.</exception>
836 /// AppControl appControl = new AppControl();
837 /// appControl.ExtraData.Add("myKey", "myValue");
840 /// <since_tizen> 3 </since_tizen>
841 public void Add(string key, string value)
843 if (string.IsNullOrEmpty(key))
845 throw new ArgumentNullException("key");
847 if (string.IsNullOrEmpty(value))
849 throw new ArgumentNullException("value");
851 Interop.AppControl.ErrorCode err = Interop.AppControl.AddExtraData(_handle, key, value);
852 if (err != Interop.AppControl.ErrorCode.None)
856 case Interop.AppControl.ErrorCode.InvalidParameter:
857 throw new ArgumentException("Invalid parameter: key or value is a zero-length string");
858 case Interop.AppControl.ErrorCode.KeyRejected:
859 throw new ArgumentException("Key is rejected: the key is system-defined key.");
861 throw new InvalidOperationException("Error = " + err);
870 /// The function replaces any existing value for the given key.
872 /// <param name="key">The name of the extra data.</param>
873 /// <param name="value">The value associated with the given key.</param>
874 /// <exception cref="ArgumentNullException">Thrown when key or value is a zero-length string.</exception>
875 /// <exception cref="ArgumentException">Thrown when the application tries to use the same key with the system-defined key.</exception>
878 /// AppControl appControl = new AppControl();
879 /// string[] myValues = new string[] { "first", "second", "third" };
880 /// appControl.ExtraData.Add("myKey", myValues);
883 /// <since_tizen> 3 </since_tizen>
884 public void Add(string key, IEnumerable<string> value)
886 if (string.IsNullOrEmpty(key))
888 throw new ArgumentNullException("key");
892 throw new ArgumentNullException("value");
894 string[] valueArray = value.ToArray();
895 Interop.AppControl.ErrorCode err = Interop.AppControl.AddExtraDataArray(_handle, key, valueArray, valueArray.Length);
896 if (err != Interop.AppControl.ErrorCode.None)
900 case Interop.AppControl.ErrorCode.InvalidParameter:
901 throw new ArgumentException("Invalid parameter: key or value is a zero-length string");
902 case Interop.AppControl.ErrorCode.KeyRejected:
903 throw new ArgumentException("Key is rejected: the key is system-defined key.");
905 throw new InvalidOperationException("Error = " + err);
911 /// Gets the extra data.
913 /// <typeparam name="T">Only string and IEnumerable<string></typeparam>
914 /// <param name="key">The name of extra data.</param>
915 /// <returns>The value associated with the given key.</returns>
916 /// <exception cref="ArgumentNullException">Thrown when the key is an invalid parameter.</exception>
917 /// <exception cref="KeyNotFoundException">Thrown when the key is not found.</exception>
918 /// <exception cref="ArgumentException">Thrown when the key is rejected.</exception>
921 /// AppControl appControl = new AppControl();
922 /// string myValue = appControl.ExtraData.Get<string>("myKey");
925 /// <since_tizen> 3 </since_tizen>
926 public T Get<T>(string key)
928 object ret = Get(key);
933 /// Gets the extra data.
935 /// <param name="key">The name of extra data.</param>
936 /// <returns>The value associated with the given key.</returns>
937 /// <exception cref="ArgumentNullException">Thrown when the key is an invalid parameter.</exception>
938 /// <exception cref="KeyNotFoundException">Thrown when the key is not found.</exception>
939 /// <exception cref="ArgumentException">Thrown when the key is rejected.</exception>
942 /// AppControl appControl = new AppControl();
943 /// string myValue = appControl.ExtraData.Get("myKey") as string;
944 /// if (myValue != null)
950 /// <since_tizen> 3 </since_tizen>
951 public object Get(string key)
953 if (IsCollection(key))
955 return GetDataCollection(key);
964 /// Gets all keys in extra data.
966 /// <returns>The keys in the AppControl.</returns>
967 /// <exception cref="InvalidOperationException">Thrown when the key is an invalid parameter.</exception>
970 /// AppControl appControl = new AppControl();
971 /// IEnumerable<string> keys = appControl.GetKeys();
972 /// if (keys != null)
974 /// foreach (string key in keys)
981 /// <since_tizen> 3 </since_tizen>
982 public IEnumerable<string> GetKeys()
984 List<string> keys = new List<string>();
985 Interop.AppControl.ExtraDataCallback callback = (handle, key, userData) =>
996 Interop.AppControl.ErrorCode err = Interop.AppControl.ForeachExtraData(_handle, callback, IntPtr.Zero);
997 if (err != Interop.AppControl.ErrorCode.None)
999 throw new InvalidOperationException("Failed to get keys. err = " + err);
1006 /// Tries getting the extra data.
1008 /// <param name="key">The name of extra data.</param>
1009 /// <param name="value">The value associated with the given key.</param>
1010 /// <returns>The result whether getting the value is done.</returns>
1011 /// <exception cref="ArgumentNullException">Thrown when the key is an invalid parameter.</exception>
1012 /// <exception cref="KeyNotFoundException">Thrown when the key is not found.</exception>
1013 /// <exception cref="ArgumentException">Thrown when the key is rejected.</exception>
1016 /// AppControl appControl = new AppControl();
1017 /// string myValue = string.Empty;
1018 /// bool result = appControl.ExtraData.TryGet("myKey", out myValue);
1019 /// if (result != null)
1025 /// <since_tizen> 3 </since_tizen>
1026 public bool TryGet(string key, out string value)
1028 if (string.IsNullOrEmpty(key))
1030 throw new ArgumentNullException("key");
1032 Interop.AppControl.GetExtraData(_handle, key, out value);
1039 value = default(string);
1045 /// Tries getting the extra data.
1047 /// <param name="key">The name of extra data.</param>
1048 /// <param name="value">The value associated with the given key.</param>
1049 /// <returns>The result whether getting the value is done.</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 /// IEnumerable<string> myValue = null;
1057 /// bool result = appControl.ExtraData.TryGet("myKey", out myValue);
1060 /// foreach (string value in myValue)
1067 /// <since_tizen> 3 </since_tizen>
1068 public bool TryGet(string key, out IEnumerable<string> value)
1070 if (string.IsNullOrEmpty(key))
1072 throw new ArgumentNullException("key");
1074 IntPtr valuePtr = IntPtr.Zero;
1076 Interop.AppControl.ErrorCode err = Interop.AppControl.GetExtraDataArray(_handle, key, out valuePtr, out len);
1077 if (err == Interop.AppControl.ErrorCode.None && valuePtr != IntPtr.Zero)
1079 List<string> stringList = new List<string>();
1080 for (int i = 0; i < len; ++i)
1082 IntPtr charArr = Marshal.ReadIntPtr(valuePtr, IntPtr.Size * i);
1083 stringList.Add(Marshal.PtrToStringAnsi(charArr));
1084 Interop.Libc.Free(charArr);
1086 Interop.Libc.Free(valuePtr);
1092 value = default(IEnumerable<string>);
1098 /// Removes the extra data.
1100 /// <param name="key">The name of the extra data.</param>
1101 /// <exception cref="ArgumentNullException">Thrown when the key is a zero-length string.</exception>
1102 /// <exception cref="KeyNotFoundException">Thrown when the key is not found.</exception>
1103 /// <exception cref="ArgumentException">Thrown when the key is rejected.</exception>
1106 /// AppControl appControl = new AppControl();
1107 /// appControl.ExtraData.Remove("myKey");
1110 /// <since_tizen> 3 </since_tizen>
1111 public void Remove(string key)
1113 if (string.IsNullOrEmpty(key))
1115 throw new ArgumentNullException("key");
1117 Interop.AppControl.ErrorCode err = Interop.AppControl.RemoveExtraData(_handle, key);
1118 if (err != Interop.AppControl.ErrorCode.None)
1122 case Interop.AppControl.ErrorCode.InvalidParameter:
1123 throw new ArgumentException("Invalid parameter: key is a zero-length string");
1124 case Interop.AppControl.ErrorCode.KeyNotFound:
1125 throw new KeyNotFoundException("Key is not found"); ;
1126 case Interop.AppControl.ErrorCode.KeyRejected:
1127 throw new ArgumentException("Key is rejected: the key is system-defined key.");
1129 throw new InvalidOperationException("Error = " + err);
1135 /// Counts keys in the extra data.
1137 /// <returns>The number of counting keys.</returns>
1138 /// <exception cref="InvalidOperationException">Thrown when the key is an invalid parameter.</exception>
1141 /// AppControl appControl = new AppControl();
1142 /// int numberOfKeys = appControl.ExtraData.Count();
1145 /// <since_tizen> 3 </since_tizen>
1148 return GetKeys().Count();
1152 /// Checks whether the extra data associated with the given key is of the collection data type.
1154 /// <param name="key">The name of the extra data.</param>
1155 /// <returns>If true, the extra data is of the array data type, otherwise false.</returns>
1156 /// <exception cref="ArgumentNullException">Thrown when the key is a zero-length string.</exception>
1157 /// <exception cref="InvalidOperationException">Thrown when failed to check the key.</exception>
1160 /// AppControl appControl = new AppControl();
1161 /// bool result = appControl.ExtraData.IsCollection("myKey");
1164 /// <since_tizen> 3 </since_tizen>
1165 public bool IsCollection(string key)
1167 if (string.IsNullOrEmpty(key))
1169 throw new ArgumentNullException("key");
1171 bool isArray = false;
1172 Interop.AppControl.ErrorCode err = Interop.AppControl.IsExtraDataArray(_handle, key, out isArray);
1173 if (err != Interop.AppControl.ErrorCode.None)
1175 throw new InvalidOperationException("Error = " + err);
1180 private string GetData(string key)
1182 if (string.IsNullOrEmpty(key))
1184 throw new ArgumentNullException("key");
1186 string value = string.Empty;
1187 Interop.AppControl.ErrorCode err = Interop.AppControl.GetExtraData(_handle, key, out value);
1188 if (err != Interop.AppControl.ErrorCode.None)
1192 case Interop.AppControl.ErrorCode.InvalidParameter:
1193 throw new ArgumentException("Invalid parameter: key is a zero-length string");
1194 case Interop.AppControl.ErrorCode.KeyNotFound:
1195 throw new KeyNotFoundException("Key is not found"); ;
1196 case Interop.AppControl.ErrorCode.InvalidDataType:
1197 throw new ArgumentException("Invalid data type: value is data collection type");
1198 case Interop.AppControl.ErrorCode.KeyRejected:
1199 throw new ArgumentException("Key is rejected: the key is system-defined key.");
1201 throw new InvalidOperationException("Error = " + err);
1207 private IEnumerable<string> GetDataCollection(string key)
1209 if (string.IsNullOrEmpty(key))
1211 throw new ArgumentNullException("key");
1213 IntPtr valuePtr = IntPtr.Zero;
1215 Interop.AppControl.ErrorCode err = Interop.AppControl.GetExtraDataArray(_handle, key, out valuePtr, out len);
1216 if (err != Interop.AppControl.ErrorCode.None)
1220 case Interop.AppControl.ErrorCode.InvalidParameter:
1221 throw new ArgumentException("Invalid parameter: key is a zero-length string");
1222 case Interop.AppControl.ErrorCode.KeyNotFound:
1223 throw new KeyNotFoundException("Key is not found"); ;
1224 case Interop.AppControl.ErrorCode.InvalidDataType:
1225 throw new ArgumentException("Invalid data type: value is data collection type");
1226 case Interop.AppControl.ErrorCode.KeyRejected:
1227 throw new ArgumentException("Key is rejected: the key is system-defined key.");
1229 throw new InvalidOperationException("Error = " + err);
1233 List<string> valueArray = new List<string>();
1234 if (valuePtr != IntPtr.Zero)
1236 for (int i = 0; i < len; ++i)
1238 IntPtr charArr = Marshal.ReadIntPtr(valuePtr, IntPtr.Size * i);
1239 valueArray.Add(Marshal.PtrToStringAnsi(charArr));
1240 Interop.Libc.Free(charArr);
1242 Interop.Libc.Free(valuePtr);