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;
20 using System.Runtime.InteropServices;
21 using System.Threading.Tasks;
23 namespace Tizen.Applications
26 /// Represents the control message to exchange between applications.
30 /// public class AppControlExample : UIApplication
33 /// protected override void OnAppControlReceived(AppControlReceivedEventArgs e)
35 /// AppControl appControl = new AppControl();
36 /// appControl.ApplicationId = "org.tizen.calculator";
37 /// AppControl.SendLaunchRequest(appControl, (launchRequest, replyRequest, result) => {
44 /// <since_tizen> 3 </since_tizen>
45 public class AppControl
47 private const string LogTag = "Tizen.Applications";
49 private static Dictionary<int, Interop.AppControl.ResultCallback> s_resultNativeCallbackMaps = new Dictionary<int, Interop.AppControl.ResultCallback>();
50 private static Dictionary<int, AppControlReplyCallback> s_replyCallbackMaps = new Dictionary<int, AppControlReplyCallback>();
51 private static int s_reaustId = 0;
53 private readonly SafeAppControlHandle _handle;
55 private string _operation = null;
56 private string _mime = null;
57 private string _uri = null;
58 private string _category = null;
59 private string _applicationId = null;
60 private ExtraDataCollection _extraData = null;
61 private string _componentId = null;
64 /// Initializes the instance of the AppControl class.
66 /// <exception cref="InvalidOperationException">Thrown when failed to create the AppControl handle.</exception>
67 /// <since_tizen> 3 </since_tizen>
70 Interop.AppControl.ErrorCode err = Interop.AppControl.Create(out _handle);
71 if (err != Interop.AppControl.ErrorCode.None)
73 throw new InvalidOperationException("Failed to create the appcontrol handle. Err = " + err);
78 /// Initializes the instance of the AppControl class with a parameter.
80 /// <param name="enableAppStartedResultEvent">The flag value to receive an additional launch result event on the launch request.</param>
81 /// <exception cref="InvalidOperationException">Thrown when failed to create the AppControl handle.</exception>
82 /// <since_tizen> 3 </since_tizen>
83 public AppControl(bool enableAppStartedResultEvent)
85 Interop.AppControl.ErrorCode err = Interop.AppControl.Create(out _handle);
86 if (err != Interop.AppControl.ErrorCode.None)
88 throw new InvalidOperationException("Failed to create the appcontrol handle. Err = " + err);
91 if (enableAppStartedResultEvent)
93 err = Interop.AppControl.EnableAppStartedResultEvent(_handle);
94 if (err != Interop.AppControl.ErrorCode.None)
96 throw new InvalidOperationException("Failed to set EnableAppStartedResultEvent");
102 /// Initializes the instance of the AppControl class with the SafeAppControlHandle.
104 /// <param name="handle"></param>
105 /// <since_tizen> 3 </since_tizen>
106 public AppControl(SafeAppControlHandle handle)
110 throw new ArgumentNullException("handle");
113 Interop.AppControl.ErrorCode err = Interop.AppControl.DangerousClone(out _handle, handle.DangerousGetHandle());
114 if (err != Interop.AppControl.ErrorCode.None)
116 throw new InvalidOperationException("Failed to clone the appcontrol handle. Err = " + err);
120 private AppControl(IntPtr handle)
122 Interop.AppControl.ErrorCode err = Interop.AppControl.DangerousClone(out _handle, handle);
123 if (err != Interop.AppControl.ErrorCode.None)
125 throw new InvalidOperationException("Failed to clone the appcontrol handle. Err = " + err);
129 private static Interop.AppControl.ReplyCallback s_replyNativeCallback = (launchHandle, replyHandle, result, userData) =>
131 int requestId = (int)userData;
132 lock (s_replyCallbackMaps)
134 if (s_replyCallbackMaps.ContainsKey(requestId))
136 s_replyCallbackMaps[requestId](new AppControl(launchHandle), new AppControl(replyHandle), (AppControlReplyResult)result);
137 if (result != Interop.AppControl.AppStartedStatus)
139 lock (s_replyCallbackMaps)
141 s_replyCallbackMaps.Remove(requestId);
148 #region Public Properties
151 /// Gets the SafeAppControlHandle instance.
153 /// <since_tizen> 3 </since_tizen>
154 public SafeAppControlHandle SafeAppControlHandle
163 /// Gets and sets the operation to be performed.
166 /// The operation is the mandatory information for the launch request. If the operation is not specified,
167 /// AppControlOperations.Default is used for the launch request. If the operation is AppControlOperations.Default,
168 /// the package information is mandatory to explicitly launch the application.
169 /// (if the operation is null for setter, it clears the previous value.)
173 /// AppControl appControl = new AppControl();
174 /// appControl.Operation = AppControlOperations.Default;
175 /// Log.Debug(LogTag, "Operation: " + appControl.Operation);
178 /// <since_tizen> 3 </since_tizen>
179 public string Operation
183 if (String.IsNullOrEmpty(_operation))
185 Interop.AppControl.ErrorCode err = Interop.AppControl.GetOperation(_handle, out _operation);
186 if (err != Interop.AppControl.ErrorCode.None)
188 Log.Warn(LogTag, "Failed to get the operation from the appcontrol. Err = " + err);
195 Interop.AppControl.ErrorCode err = Interop.AppControl.SetOperation(_handle, value);
196 if (err == Interop.AppControl.ErrorCode.None)
202 Log.Warn(LogTag, "Failed to set the operation to the appcontrol. Err = " + err);
208 /// Gets and sets the explicit MIME type of the data.
211 /// (if the mime is null for setter, it clears the previous value.)
215 /// AppControl appControl = new AppControl();
216 /// appControl.Mime = "image/jpg";
217 /// Log.Debug(LogTag, "Mime: " + appControl.Mime);
220 /// <since_tizen> 3 </since_tizen>
225 if (String.IsNullOrEmpty(_mime))
227 Interop.AppControl.ErrorCode err = Interop.AppControl.GetMime(_handle, out _mime);
228 if (err != Interop.AppControl.ErrorCode.None)
230 Log.Warn(LogTag, "Failed to get the mime from the appcontrol. Err = " + err);
237 Interop.AppControl.ErrorCode err = Interop.AppControl.SetMime(_handle, value);
238 if (err == Interop.AppControl.ErrorCode.None)
244 Log.Warn(LogTag, "Failed to set the mime to the appcontrol. Err = " + err);
250 /// Gets and sets the URI of the data.
253 /// Since Tizen 2.4, if the parameter 'uri' is started with 'file://' and
254 /// it is a regular file in this application's data path, which can be obtained
255 /// by property DataPath in ApplicationInfo class,
256 /// it will be shared to the callee application.
257 /// Framework will grant a temporary permission to the callee application for this file and
258 /// revoke it when the callee application is terminated.
259 /// The callee application can just read it.
260 /// (if the uri is null for setter, it clears the previous value.)
264 /// public class AppControlExample : UIApplication
267 /// protected override void OnAppControlReceived(AppControlReceivedEventArgs e)
270 /// AppControl appControl = new AppControl();
271 /// appContrl.Uri = this.ApplicationInfo.DataPath + "image.jpg";
272 /// Log.Debug(LogTag, "Set Uri: " + appControl.Uri);
277 /// <since_tizen> 3 </since_tizen>
282 if (String.IsNullOrEmpty(_uri))
284 Interop.AppControl.ErrorCode err = Interop.AppControl.GetUri(_handle, out _uri);
285 if (err != Interop.AppControl.ErrorCode.None)
287 Log.Warn(LogTag, "Failed to get the uri from the appcontrol. Err = " + err);
294 Interop.AppControl.ErrorCode err = Interop.AppControl.SetUri(_handle, value);
295 if (err == Interop.AppControl.ErrorCode.None)
301 Log.Warn(LogTag, "Failed to set the uri to the appcontrol. Err = " + err);
307 /// Gets and sets the explicit category.
310 /// (if the category is null for setter, it clears the previous value.)
312 /// <since_tizen> 3 </since_tizen>
313 public string Category
317 if (String.IsNullOrEmpty(_category))
319 Interop.AppControl.ErrorCode err = Interop.AppControl.GetCategory(_handle, out _category);
320 if (err != Interop.AppControl.ErrorCode.None)
322 Log.Warn(LogTag, "Failed to get the category from the appcontrol. Err = " + err);
329 Interop.AppControl.ErrorCode err = Interop.AppControl.SetCategory(_handle, value);
330 if (err == Interop.AppControl.ErrorCode.None)
336 Log.Warn(LogTag, "Failed to set the category to the appcontrol. Err = " + err);
342 /// Gets and sets the application ID to explicitly launch.
345 /// (if the application ID is null for setter, it clears the previous value.)
349 /// AppControl appControl = new AppControl();
350 /// appControl.ApplicationId = "org.tizen.calculator";
351 /// Log.Debug(LogTag, "ApplicationId: " + appControl.ApplicationId);
354 /// <since_tizen> 3 </since_tizen>
355 public string ApplicationId
359 if (String.IsNullOrEmpty(_applicationId))
361 Interop.AppControl.ErrorCode err = Interop.AppControl.GetAppId(_handle, out _applicationId);
362 if (err != Interop.AppControl.ErrorCode.None)
364 Log.Warn(LogTag, "Failed to get the application id from the AppControl. Err = " + err);
367 return _applicationId;
371 Interop.AppControl.ErrorCode err = Interop.AppControl.SetAppId(_handle, value);
372 if (err == Interop.AppControl.ErrorCode.None)
374 _applicationId = value;
378 Log.Warn(LogTag, "Failed to set the application id to the AppControl. Err = " + err);
384 /// Gets and sets the launch mode of the application.
387 /// Although, LaunchMode were set as AppControlLaunchMode.Group, the
388 /// callee application would be launched as a single mode
389 /// if the manifest file of callee application defined the launch mode as "single".
390 /// This property can just set the preference of the caller application to launch an application.
391 /// Sub-applications, which were launched as a group mode always have own process.
392 /// Since Tizen 3.0, if launch mode is not set in the caller application control,
393 /// this property returns the AppControlLaunchMode.Single launch mode.
397 /// AppControl appControl = new AppControl();
398 /// appControl.LaunchMode = AppControlLaunchMode.Group;
401 /// <since_tizen> 3 </since_tizen>
402 public AppControlLaunchMode LaunchMode
407 Interop.AppControl.ErrorCode err = Interop.AppControl.GetLaunchMode(_handle, out value);
408 if (err != Interop.AppControl.ErrorCode.None)
410 Log.Warn(LogTag, "Failed to get the LaunchMode from the AppControl. Err = " + err);
412 return (AppControlLaunchMode)value;
416 Interop.AppControl.ErrorCode err = Interop.AppControl.SetLaunchMode(_handle, (int)value);
417 if (err != Interop.AppControl.ErrorCode.None)
419 Log.Warn(LogTag, "Failed to set the LaunchMode to the AppControl. Err = " + err);
425 /// Gets the collection of the extra data.
428 /// Extra data for communication between AppControls.
432 /// AppControl appControl = new AppControl();
433 /// appControl.ExtraData.Add("key", "value");
437 /// <since_tizen> 3 </since_tizen>
438 public ExtraDataCollection ExtraData
442 if (_extraData == null)
443 _extraData = new ExtraDataCollection(_handle);
449 /// Gets and sets the component ID to explicitly launch a component.
452 /// (if the component ID is null for setter, it clears the previous value.)
453 /// From Tizen 5.5, a new application model is supported that is component-based application.
454 /// This property is for launching component-based application. If it's not set, the main component of component-based application will be launched.
455 /// If the target app is not component-based application, setting property is meaningless.
459 /// AppControl appControl = new AppControl();
460 /// appControl.ApplicationId = "org.tizen.component-based-app"; // component-based application
461 /// appControl.ComponentId = "org.tizen.frame-component";
462 /// AppControl.SendLaunchRequest(appControl);
465 /// <since_tizen> 6 </since_tizen>
466 public string ComponentId
470 if (String.IsNullOrEmpty(_componentId))
472 Interop.AppControl.ErrorCode err = Interop.AppControl.GetComponentId(_handle, out _componentId);
473 if (err != Interop.AppControl.ErrorCode.None)
475 Log.Warn(LogTag, "Failed to get the component id from the AppControl. Err = " + err);
482 Interop.AppControl.ErrorCode err = Interop.AppControl.SetComponentId(_handle, value);
483 if (err == Interop.AppControl.ErrorCode.None)
485 _componentId = value;
489 Log.Warn(LogTag, "Failed to set the component id to the AppControl. Err = " + err);
494 #endregion // Public Properties
497 /// Retrieves all applications that can be launched to handle the given app_control request.
499 /// <param name="control">The AppControl.</param>
500 /// <returns>ApplicationIds.</returns>
501 /// <exception cref="InvalidOperationException">Thrown when failed because of an invalid parameter.</exception>
504 /// IEnumerable<string> applicationIds = AppControl.GetMatchedApplicationIds(control);
505 /// if (applicationIds != null)
507 /// foreach (string id in applicationIds)
514 /// <since_tizen> 3 </since_tizen>
515 public static IEnumerable<string> GetMatchedApplicationIds(AppControl control)
519 throw new ArgumentNullException("control");
522 List<string> ids = new List<string>();
523 Interop.AppControl.AppMatchedCallback callback = (handle, applicationId, userData) =>
525 if (applicationId == null)
530 ids.Add(applicationId);
534 Interop.AppControl.ErrorCode err = Interop.AppControl.ForeachAppMatched(control._handle, callback, IntPtr.Zero);
535 if (err != Interop.AppControl.ErrorCode.None)
537 throw new InvalidOperationException("Failed to get matched application ids. err = " + err);
544 /// Sends the launch request.
547 /// The operation is mandatory information for the launch request.
548 /// If the operation is not specified, AppControlOperations.Default is used by default.
549 /// If the operation is AppControlOperations.Default, the application ID is mandatory to explicitly launch the application.<br/>
550 /// Since Tizen 2.4, the launch request of the service application over out of packages is restricted by the platform.
551 /// Also, implicit launch requests are NOT delivered to service applications since 2.4.
552 /// To launch a service application, an explicit launch request with the application ID given by property ApplicationId MUST be sent.
554 /// <param name="launchRequest">The AppControl.</param>
555 /// <exception cref="ArgumentNullException">Thrown when failed because of a null argument.</exception>
556 /// <exception cref="InvalidOperationException">Thrown when failed because of an invalid operation.</exception>
557 /// <exception cref="TimeoutException">Thrown when failed because of timeout.</exception>
558 /// <privilege>http://tizen.org/privilege/appmanager.launch</privilege>
561 /// AppControl appControl = new AppControl();
562 /// appControl.ApplicationId = "org.tizen.calculator";
563 /// AppControl.SendLaunchRequest(appControl);
566 /// <since_tizen> 3 </since_tizen>
567 public static void SendLaunchRequest(AppControl launchRequest)
569 SendLaunchRequest(launchRequest, null);
573 /// Sends the launch request.
576 /// The operation is mandatory information for the launch request.
577 /// If the operation is not specified, AppControlOperations.Default is used by default.
578 /// If the operation is AppControlOperations.Default, the application ID is mandatory to explicitly launch the application.<br/>
579 /// Since Tizen 2.4, the launch request of the service application over out of packages is restricted by the platform.
580 /// Also, implicit launch requests are NOT delivered to service applications since 2.4.
581 /// To launch a service application, an explicit launch request with the application ID given by property ApplicationId MUST be sent.
583 /// <param name="launchRequest">The AppControl.</param>
584 /// <param name="replyAfterLaunching">The callback function to be called when the reply is delivered.</param>
585 /// <exception cref="ArgumentException">Thrown when failed because of the argument is invalid.</exception>
586 /// <exception cref="Exceptions.AppNotFoundException">Thrown when the application to run is not found.</exception>
587 /// <exception cref="Exceptions.LaunchFailedException">Thrown when the request failed to launch the application.</exception>
588 /// <exception cref="Exceptions.LaunchRejectedException">Thrown when the launch request is rejected.</exception>
589 /// <exception cref="Exceptions.OutOfMemoryException">Thrown when the memory is insufficient.</exception>
590 /// <exception cref="Exceptions.PermissionDeniedException">Thrown when the permission is denied.</exception>
591 /// <exception cref="TimeoutException">Thrown when failed because of timeout.</exception>
592 /// <privilege>http://tizen.org/privilege/appmanager.launch</privilege>
595 /// AppControl appControl = new AppControl();
596 /// appControl.ApplicationId = "org.tizen.calculator";
597 /// AppControl.SendLaunchRequest(appControl, (launchRequest, replyRequest, result) => {
602 /// <since_tizen> 3 </since_tizen>
603 public static void SendLaunchRequest(AppControl launchRequest, AppControlReplyCallback replyAfterLaunching)
605 if (launchRequest == null)
607 throw new ArgumentNullException("launchRequest");
610 Interop.AppControl.ErrorCode err;
612 if (replyAfterLaunching != null)
615 lock (s_replyCallbackMaps)
618 s_replyCallbackMaps[id] = replyAfterLaunching;
620 err = Interop.AppControl.SendLaunchRequest(launchRequest._handle, s_replyNativeCallback, (IntPtr)id);
624 err = Interop.AppControl.SendLaunchRequest(launchRequest._handle, null, IntPtr.Zero);
627 if (err != Interop.AppControl.ErrorCode.None)
631 case Interop.AppControl.ErrorCode.InvalidParameter:
632 throw new ArgumentException("Invalid Arguments");
633 case Interop.AppControl.ErrorCode.TimedOut:
634 throw new TimeoutException("Timed out");
635 case Interop.AppControl.ErrorCode.OutOfMemory:
636 throw new Exceptions.OutOfMemoryException("Out-of-memory");
637 case Interop.AppControl.ErrorCode.AppNotFound:
638 throw new Exceptions.AppNotFoundException("App(" + launchRequest.ApplicationId + ") not found. Operation(" + launchRequest.Operation + ")");
639 case Interop.AppControl.ErrorCode.LaunchRejected:
640 throw new Exceptions.LaunchRejectedException("Launch rejected");
641 case Interop.AppControl.ErrorCode.LaunchFailed:
642 throw new Exceptions.LaunchFailedException("Launch failed");
643 case Interop.AppControl.ErrorCode.PermissionDenied:
644 throw new Exceptions.PermissionDeniedException("Permission denied");
647 throw new Exceptions.LaunchRejectedException("Launch rejected");
653 /// Sends the terminate request to the application that is launched by AppControl.
656 /// You are not allowed to terminate other general applications using this API.
657 /// This API can be used to terminate sub-applications, which were launched as a group mode by the caller application.
658 /// Once the callee application is being terminated by this API,
659 /// other applications, which were launched by the callee application as a group mode will be terminated as well.
661 /// <param name="terminateRequest">The AppControl.</param>
662 /// <exception cref="ArgumentException">Thrown when failed because of the argument is invalid.</exception>
663 /// <exception cref="InvalidOperationException">Thrown when failed because of an invalid operation.</exception>
664 /// <exception cref="TimeoutException">Thrown when failed because of timeout.</exception>
667 /// AppControl terminateRequest = new AppControl();
668 /// terminateRequest.ApplicationId = "org.tizen.calculator";
669 /// AppControl.SendTerminateRequest(terminateRequest);
672 /// <since_tizen> 3 </since_tizen>
673 public static void SendTerminateRequest(AppControl terminateRequest)
675 if (terminateRequest == null)
677 throw new ArgumentNullException("terminateRequest");
679 Interop.AppControl.ErrorCode err;
681 err = Interop.AppControl.SendTerminateRequest(terminateRequest._handle);
683 if (err != Interop.AppControl.ErrorCode.None)
687 case Interop.AppControl.ErrorCode.InvalidParameter:
688 throw new ArgumentException("Invalid Arguments");
689 case Interop.AppControl.ErrorCode.TimedOut:
690 throw new TimeoutException("Timed out");
692 throw new InvalidOperationException("Error = " + err);
698 /// Sends the launch request asynchronously.
701 /// The operation is mandatory information for the launch request.
702 /// If the operation is not specified, AppControlOperations.Default is used by default.
703 /// If the operation is AppControlOperations.Default, the application ID is mandatory to explicitly launch the application.<br/>
704 /// Since Tizen 2.4, the launch request of the service application over out of packages is restricted by the platform.
705 /// Also, implicit launch requests are NOT delivered to service applications since 2.4.
706 /// To launch a service application, an explicit launch request with the application ID given by property ApplicationId MUST be sent.
708 /// <param name="launchRequest">The AppControl.</param>
709 /// <param name="replyAfterLaunching">The callback function to be called when the reply is delivered.</param>
710 /// <returns>A task with the result of the launch request.</returns>
711 /// <exception cref="ArgumentException">Thrown when failed because of the argument is invalid.</exception>
712 /// <exception cref="Exceptions.AppNotFoundException">Thrown when the application to run is not found.</exception>
713 /// <exception cref="Exceptions.LaunchRejectedException">Thrown when the launch request is rejected.</exception>
714 /// <privilege>http://tizen.org/privilege/appmanager.launch</privilege>
715 /// <since_tizen> 6 </since_tizen>
716 public static Task<AppControlResult> SendLaunchRequestAsync(AppControl launchRequest, AppControlReplyCallback replyAfterLaunching)
718 if (launchRequest == null)
720 throw new ArgumentNullException(nameof(launchRequest));
723 var task = new TaskCompletionSource<AppControlResult>();
724 Interop.AppControl.ErrorCode err;
727 lock (s_resultNativeCallbackMaps)
729 requestId = s_reaustId++;
730 s_resultNativeCallbackMaps[requestId] = (handle, result, userData) =>
732 task.SetResult((AppControlResult)result);
733 lock (s_resultNativeCallbackMaps)
735 s_resultNativeCallbackMaps.Remove((int)userData);
740 if (replyAfterLaunching != null)
742 lock (s_replyCallbackMaps)
744 s_replyCallbackMaps[requestId] = replyAfterLaunching;
746 err = Interop.AppControl.SendLaunchRequestAsync(launchRequest.SafeAppControlHandle, s_resultNativeCallbackMaps[requestId], s_replyNativeCallback, (IntPtr)requestId);
750 err = Interop.AppControl.SendLaunchRequestAsync(launchRequest.SafeAppControlHandle, s_resultNativeCallbackMaps[requestId], null, (IntPtr)requestId);
753 if (err != Interop.AppControl.ErrorCode.None)
757 case Interop.AppControl.ErrorCode.InvalidParameter:
758 throw new ArgumentException("Invalid Arguments");
759 case Interop.AppControl.ErrorCode.AppNotFound:
760 throw new Exceptions.AppNotFoundException("App(" + launchRequest.ApplicationId + ") not found. Operation(" + launchRequest.Operation + ")");
761 case Interop.AppControl.ErrorCode.LaunchRejected:
762 throw new Exceptions.LaunchRejectedException("Launch rejected");
763 case Interop.AppControl.ErrorCode.PermissionDenied:
764 throw new Exceptions.PermissionDeniedException("Permission denied");
767 throw new Exceptions.LaunchRejectedException("Launch rejected");
775 /// Class for extra data.
777 /// <since_tizen> 3 </since_tizen>
778 public class ExtraDataCollection
780 private readonly SafeAppControlHandle _handle;
782 internal ExtraDataCollection(SafeAppControlHandle handle)
791 /// The function replaces any existing value for the given key.
793 /// <param name="key">The name of the extra data.</param>
794 /// <param name="value">The value associated with the given key.</param>
795 /// <exception cref="ArgumentNullException">Thrown when a key or a value is a zero-length string.</exception>
796 /// <exception cref="ArgumentException">Thrown when the application tries to use the same key with the system-defined key.</exception>
799 /// AppControl appControl = new AppControl();
800 /// appControl.ExtraData.Add("myKey", "myValue");
803 /// <since_tizen> 3 </since_tizen>
804 public void Add(string key, string value)
806 if (string.IsNullOrEmpty(key))
808 throw new ArgumentNullException("key");
810 if (string.IsNullOrEmpty(value))
812 throw new ArgumentNullException("value");
814 Interop.AppControl.ErrorCode err = Interop.AppControl.AddExtraData(_handle, key, value);
815 if (err != Interop.AppControl.ErrorCode.None)
819 case Interop.AppControl.ErrorCode.InvalidParameter:
820 throw new ArgumentException("Invalid parameter: key or value is a zero-length string");
821 case Interop.AppControl.ErrorCode.KeyRejected:
822 throw new ArgumentException("Key is rejected: the key is system-defined key.");
824 throw new InvalidOperationException("Error = " + err);
833 /// The function replaces any existing value for the given key.
835 /// <param name="key">The name of the extra data.</param>
836 /// <param name="value">The value associated with the given key.</param>
837 /// <exception cref="ArgumentNullException">Thrown when key or value is a zero-length string.</exception>
838 /// <exception cref="ArgumentException">Thrown when the application tries to use the same key with the system-defined key.</exception>
841 /// AppControl appControl = new AppControl();
842 /// string[] myValues = new string[] { "first", "second", "third" };
843 /// appControl.ExtraData.Add("myKey", myValues);
846 /// <since_tizen> 3 </since_tizen>
847 public void Add(string key, IEnumerable<string> value)
849 if (string.IsNullOrEmpty(key))
851 throw new ArgumentNullException("key");
855 throw new ArgumentNullException("value");
857 string[] valueArray = value.ToArray();
858 Interop.AppControl.ErrorCode err = Interop.AppControl.AddExtraDataArray(_handle, key, valueArray, valueArray.Length);
859 if (err != Interop.AppControl.ErrorCode.None)
863 case Interop.AppControl.ErrorCode.InvalidParameter:
864 throw new ArgumentException("Invalid parameter: key or value is a zero-length string");
865 case Interop.AppControl.ErrorCode.KeyRejected:
866 throw new ArgumentException("Key is rejected: the key is system-defined key.");
868 throw new InvalidOperationException("Error = " + err);
874 /// Gets the extra data.
876 /// <typeparam name="T">Only string and IEnumerable<string></typeparam>
877 /// <param name="key">The name of extra data.</param>
878 /// <returns>The value associated with the given key.</returns>
879 /// <exception cref="ArgumentNullException">Thrown when the key is an invalid parameter.</exception>
880 /// <exception cref="KeyNotFoundException">Thrown when the key is not found.</exception>
881 /// <exception cref="ArgumentException">Thrown when the key is rejected.</exception>
884 /// AppControl appControl = new AppControl();
885 /// string myValue = appControl.ExtraData.Get<string>("myKey");
888 /// <since_tizen> 3 </since_tizen>
889 public T Get<T>(string key)
891 object ret = Get(key);
896 /// Gets the extra data.
898 /// <param name="key">The name of extra data.</param>
899 /// <returns>The value associated with the given key.</returns>
900 /// <exception cref="ArgumentNullException">Thrown when the key is an invalid parameter.</exception>
901 /// <exception cref="KeyNotFoundException">Thrown when the key is not found.</exception>
902 /// <exception cref="ArgumentException">Thrown when the key is rejected.</exception>
905 /// AppControl appControl = new AppControl();
906 /// string myValue = appControl.ExtraData.Get("myKey") as string;
907 /// if (myValue != null)
913 /// <since_tizen> 3 </since_tizen>
914 public object Get(string key)
916 if (IsCollection(key))
918 return GetDataCollection(key);
927 /// Gets all keys in extra data.
929 /// <returns>The keys in the AppControl.</returns>
930 /// <exception cref="InvalidOperationException">Thrown when the key is an invalid parameter.</exception>
933 /// AppControl appControl = new AppControl();
934 /// IEnumerable<string> keys = appControl.GetKeys();
935 /// if (keys != null)
937 /// foreach (string key in keys)
944 /// <since_tizen> 3 </since_tizen>
945 public IEnumerable<string> GetKeys()
947 List<string> keys = new List<string>();
948 Interop.AppControl.ExtraDataCallback callback = (handle, key, userData) =>
959 Interop.AppControl.ErrorCode err = Interop.AppControl.ForeachExtraData(_handle, callback, IntPtr.Zero);
960 if (err != Interop.AppControl.ErrorCode.None)
962 throw new InvalidOperationException("Failed to get keys. err = " + err);
969 /// Tries getting the extra data.
971 /// <param name="key">The name of extra data.</param>
972 /// <param name="value">The value associated with the given key.</param>
973 /// <returns>The result whether getting the value is done.</returns>
974 /// <exception cref="ArgumentNullException">Thrown when the key is an invalid parameter.</exception>
975 /// <exception cref="KeyNotFoundException">Thrown when the key is not found.</exception>
976 /// <exception cref="ArgumentException">Thrown when the key is rejected.</exception>
979 /// AppControl appControl = new AppControl();
980 /// string myValue = string.Empty;
981 /// bool result = appControl.ExtraData.TryGet("myKey", out myValue);
982 /// if (result != null)
988 /// <since_tizen> 3 </since_tizen>
989 public bool TryGet(string key, out string value)
991 if (string.IsNullOrEmpty(key))
993 throw new ArgumentNullException("key");
995 Interop.AppControl.GetExtraData(_handle, key, out value);
1002 value = default(string);
1008 /// Tries getting the extra data.
1010 /// <param name="key">The name of extra data.</param>
1011 /// <param name="value">The value associated with the given key.</param>
1012 /// <returns>The result whether getting the value is done.</returns>
1013 /// <exception cref="ArgumentNullException">Thrown when the key is an invalid parameter.</exception>
1014 /// <exception cref="KeyNotFoundException">Thrown when the key is not found.</exception>
1015 /// <exception cref="ArgumentException">Thrown when the key is rejected.</exception>
1018 /// AppControl appControl = new AppControl();
1019 /// IEnumerable<string> myValue = null;
1020 /// bool result = appControl.ExtraData.TryGet("myKey", out myValue);
1023 /// foreach (string value in myValue)
1030 /// <since_tizen> 3 </since_tizen>
1031 public bool TryGet(string key, out IEnumerable<string> value)
1033 if (string.IsNullOrEmpty(key))
1035 throw new ArgumentNullException("key");
1037 IntPtr valuePtr = IntPtr.Zero;
1039 Interop.AppControl.ErrorCode err = Interop.AppControl.GetExtraDataArray(_handle, key, out valuePtr, out len);
1040 if (err == Interop.AppControl.ErrorCode.None && valuePtr != IntPtr.Zero)
1042 List<string> stringList = new List<string>();
1043 for (int i = 0; i < len; ++i)
1045 IntPtr charArr = Marshal.ReadIntPtr(valuePtr, IntPtr.Size * i);
1046 stringList.Add(Marshal.PtrToStringAnsi(charArr));
1047 Interop.Libc.Free(charArr);
1049 Interop.Libc.Free(valuePtr);
1055 value = default(IEnumerable<string>);
1061 /// Removes the extra data.
1063 /// <param name="key">The name of the extra data.</param>
1064 /// <exception cref="ArgumentNullException">Thrown when the key is a zero-length string.</exception>
1065 /// <exception cref="KeyNotFoundException">Thrown when the key is not found.</exception>
1066 /// <exception cref="ArgumentException">Thrown when the key is rejected.</exception>
1069 /// AppControl appControl = new AppControl();
1070 /// appControl.ExtraData.Remove("myKey");
1073 /// <since_tizen> 3 </since_tizen>
1074 public void Remove(string key)
1076 if (string.IsNullOrEmpty(key))
1078 throw new ArgumentNullException("key");
1080 Interop.AppControl.ErrorCode err = Interop.AppControl.RemoveExtraData(_handle, key);
1081 if (err != Interop.AppControl.ErrorCode.None)
1085 case Interop.AppControl.ErrorCode.InvalidParameter:
1086 throw new ArgumentException("Invalid parameter: key is a zero-length string");
1087 case Interop.AppControl.ErrorCode.KeyNotFound:
1088 throw new KeyNotFoundException("Key is not found"); ;
1089 case Interop.AppControl.ErrorCode.KeyRejected:
1090 throw new ArgumentException("Key is rejected: the key is system-defined key.");
1092 throw new InvalidOperationException("Error = " + err);
1098 /// Counts keys in the extra data.
1100 /// <returns>The number of counting keys.</returns>
1101 /// <exception cref="InvalidOperationException">Thrown when the key is an invalid parameter.</exception>
1104 /// AppControl appControl = new AppControl();
1105 /// int numberOfKeys = appControl.ExtraData.Count();
1108 /// <since_tizen> 3 </since_tizen>
1111 return GetKeys().Count();
1115 /// Checks whether the extra data associated with the given key is of the collection data type.
1117 /// <param name="key">The name of the extra data.</param>
1118 /// <returns>If true, the extra data is of the array data type, otherwise false.</returns>
1119 /// <exception cref="ArgumentNullException">Thrown when the key is a zero-length string.</exception>
1120 /// <exception cref="InvalidOperationException">Thrown when failed to check the key.</exception>
1123 /// AppControl appControl = new AppControl();
1124 /// bool result = appControl.ExtraData.IsCollection("myKey");
1127 /// <since_tizen> 3 </since_tizen>
1128 public bool IsCollection(string key)
1130 if (string.IsNullOrEmpty(key))
1132 throw new ArgumentNullException("key");
1134 bool isArray = false;
1135 Interop.AppControl.ErrorCode err = Interop.AppControl.IsExtraDataArray(_handle, key, out isArray);
1136 if (err != Interop.AppControl.ErrorCode.None)
1138 throw new InvalidOperationException("Error = " + err);
1143 private string GetData(string key)
1145 if (string.IsNullOrEmpty(key))
1147 throw new ArgumentNullException("key");
1149 string value = string.Empty;
1150 Interop.AppControl.ErrorCode err = Interop.AppControl.GetExtraData(_handle, key, out value);
1151 if (err != Interop.AppControl.ErrorCode.None)
1155 case Interop.AppControl.ErrorCode.InvalidParameter:
1156 throw new ArgumentException("Invalid parameter: key is a zero-length string");
1157 case Interop.AppControl.ErrorCode.KeyNotFound:
1158 throw new KeyNotFoundException("Key is not found"); ;
1159 case Interop.AppControl.ErrorCode.InvalidDataType:
1160 throw new ArgumentException("Invalid data type: value is data collection type");
1161 case Interop.AppControl.ErrorCode.KeyRejected:
1162 throw new ArgumentException("Key is rejected: the key is system-defined key.");
1164 throw new InvalidOperationException("Error = " + err);
1170 private IEnumerable<string> GetDataCollection(string key)
1172 if (string.IsNullOrEmpty(key))
1174 throw new ArgumentNullException("key");
1176 IntPtr valuePtr = IntPtr.Zero;
1178 Interop.AppControl.ErrorCode err = Interop.AppControl.GetExtraDataArray(_handle, key, out valuePtr, out len);
1179 if (err != Interop.AppControl.ErrorCode.None)
1183 case Interop.AppControl.ErrorCode.InvalidParameter:
1184 throw new ArgumentException("Invalid parameter: key is a zero-length string");
1185 case Interop.AppControl.ErrorCode.KeyNotFound:
1186 throw new KeyNotFoundException("Key is not found"); ;
1187 case Interop.AppControl.ErrorCode.InvalidDataType:
1188 throw new ArgumentException("Invalid data type: value is data collection type");
1189 case Interop.AppControl.ErrorCode.KeyRejected:
1190 throw new ArgumentException("Key is rejected: the key is system-defined key.");
1192 throw new InvalidOperationException("Error = " + err);
1196 List<string> valueArray = new List<string>();
1197 if (valuePtr != IntPtr.Zero)
1199 for (int i = 0; i < len; ++i)
1201 IntPtr charArr = Marshal.ReadIntPtr(valuePtr, IntPtr.Size * i);
1202 valueArray.Add(Marshal.PtrToStringAnsi(charArr));
1203 Interop.Libc.Free(charArr);
1205 Interop.Libc.Free(valuePtr);