/// <summary> /// Get a string value /// </summary> /// <param name="preferenceFileKey">Desired preferences file. If a preferences file by this name does not exist, it will be created.</param> /// <param name="key">The name of the preference to modify.</param> /// <param name="defaultValue">Value to return if this preference does not exist.</param> /// <param name="mode">Operating mode. Use 0 or MODE_PRIVATE for the default operation.</param> /// <returns>Returns true if the new values were successfully written to persistent storage.</returns> public static string GetString(string preferenceFileKey, string key, string defaultValue, int mode = MODE_PRIVATE) { if (AGUtils.IsNotAndroidCheck()) { return(string.Empty); } if (string.IsNullOrEmpty(preferenceFileKey)) { throw new ArgumentException("preferenceFileKey"); } if (string.IsNullOrEmpty(key)) { throw new ArgumentException("key"); } return(GetValue(preferenceFileKey, key, defaultValue, mode)); }
/// <summary> /// Gets the last known GPS location. /// </summary> /// <returns>The last known GPS location.</returns> public static Location GetLastKnownGPSLocation() { if (AGUtils.IsNotAndroidCheck()) { return(null); } try { var locationAJO = AGSystemService.LocationService.Call <AndroidJavaObject>("getLastKnownLocation", GPS_PROVIDER); return(LocationFromAJO(locationAJO)); } catch (Exception) { return(null); } }
/// <summary> /// Required permissions: /// <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> /// /// Launches the camera app to take a photo and returns resulting Texture2D in callback. The photo is also saved to the device gallery. /// /// IMPORTANT! : You don't need any permissions to use this method. It works using Android intent. /// </summary> /// <param name="onSuccess">On success callback. Image is received as callback parameter</param> /// <param name="onCancel">On cancel callback.</param> /// <param name="maxSize">Max image size. If provided image will be downscaled.</param> /// <param name="albumName">Album where photo will be stored.</param> public static void TakePhoto(Action <ImagePickResult> onSuccess, Action onCancel, ImageResultSize maxSize = ImageResultSize.Original, string albumName = DefaultAlbumName) { if (AGUtils.IsNotAndroidCheck()) { return; } if (onSuccess == null) { throw new ArgumentNullException("onSuccess", "Success callback cannot be null"); } var listener = new AGActivityUtils.OnPickPhotoListener(onSuccess, onCancel); AGUtils.RunOnUiThread(() => AGActivityUtils.TakePhotoBig(listener, maxSize, albumName)); }
/// <summary> /// Remove all values from the preferences. /// </summary> /// <param name="preferenceFileKey">Desired preferences file. If a preferences file by this name does not exist, it will be created.</param> /// <param name="mode">Operating mode. Use 0 or MODE_PRIVATE for the default operation.</param> /// <returns>Returns true if the new values were successfully written to persistent storage.</returns> public static bool Clear(string preferenceFileKey, int mode = MODE_PRIVATE) { if (AGUtils.IsNotAndroidCheck()) { return(false); } if (string.IsNullOrEmpty(preferenceFileKey)) { throw new ArgumentException("preferenceFileKey"); } using (var editor = GetEditorInternal(preferenceFileKey, mode)) { editor.CallAJO("clear"); return(Commit(editor)); } }
/// <summary> /// Opens the provided settings screen /// </summary> /// <param name="action"> /// Screen to open. Use on of actions provided as constants in this class. Check android.provider.Settings java class for more info /// </param> public static void OpenSettingsScreen(string action) { if (AGUtils.IsNotAndroidCheck()) { return; } var intent = new AndroidIntent(action); if (intent.ResolveActivity()) { AGUtils.StartActivity(intent.AJO); } else { Debug.LogWarning("Could not launch " + action + " settings. Check the device API level"); } }
/// <summary> /// DIsplays the prompt to uninstall the app. /// </summary> /// <param name="package">Package to uninstall.</param> public static void UninstallApp(string package) { if (AGUtils.IsNotAndroidCheck()) { return; } try { var uri = AndroidUri.Parse(string.Format("package:{0}", package)); var intent = new AndroidIntent(AndroidIntent.ACTION_DELETE, uri); AGUtils.StartActivity(intent.AJO); } catch { // ignore } }
/// <summary> /// Get a boolean value /// </summary> /// <param name="preferenceFileKey">Desired preferences file. If a preferences file by this name does not exist, it will be created.</param> /// <param name="key">The name of the preference to modify.</param> /// <param name="defaultValue">Value to return if this preference does not exist.</param> /// <param name="mode">Operating mode. Use 0 or MODE_PRIVATE for the default operation.</param> /// <returns>Returns true if the new values were successfully written to persistent storage.</returns> public static bool GetBool(string preferenceFileKey, string key, bool defaultValue, int mode = MODE_PRIVATE) { if (AGUtils.IsNotAndroid()) { return(false); } if (string.IsNullOrEmpty(preferenceFileKey)) { throw new ArgumentException("preferenceFileKey"); } if (string.IsNullOrEmpty(key)) { throw new ArgumentException("key"); } return(GetValue(preferenceFileKey, key, defaultValue, mode)); }
public static List <PackageInfo> GetInstalledPackages() { if (AGUtils.IsNotAndroid()) { return(new List <PackageInfo>()); } using (var pm = AGUtils.PackageManager) { var result = new List <PackageInfo>(); var pkgAppsList = pm.CallAJO("getInstalledPackages", 0).FromJavaList <AndroidJavaObject>(); foreach (var resolveInfo in pkgAppsList) { result.Add(PackageInfo.FromJavaObj(resolveInfo)); } return(result); } }
/// <summary> /// Picks the image from gallery. /// </summary> /// <param name="onSuccess">On success callback. Image is received as callback parameter</param> /// <param name="onCancel">On cancel callback.</param> /// <param name="imageFormat">Image format.</param> /// <param name="maxSize">Max image size. If provided image will be downscaled.</param> public static void PickImageFromGallery(Action <ImagePickResult> onSuccess, Action onCancel, ImageFormat imageFormat = ImageFormat.PNG, ImageResultSize maxSize = ImageResultSize.Original) { if (AGUtils.IsNotAndroidCheck()) { return; } if (onSuccess == null) { throw new ArgumentNullException("onSuccess", "Success callback cannot be null"); } AGUtils.RunOnUiThread( () => AGActivityUtils.PickPhotoFromGallery( new AGActivityUtils.OnPickPhotoListener(onSuccess, onCancel), imageFormat, maxSize)); }
public static bool StopRecording() { if (AGUtils.IsNotAndroid()) { return(false); } if (_mediaRecorder == null) { return(false); } _mediaRecorder.Call("stop"); _mediaRecorder.Call("release"); _mediaRecorder.Dispose(); _mediaRecorder = null; return(true); }
/// <summary> /// Required permissions: /// <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> /// /// Launches the camera app to take a photo and returns resulting Texture2D in callback. The photo is also saved to the device gallery. /// /// IMPORTANT! : You don't need any permissions to use this method. It works using Android intent. /// </summary> /// <param name="onSuccess">On success callback. Image is received as callback parameter</param> /// <param name="onError">On error/cancel callback.</param> /// <param name="maxSize">Max image size. If provided image will be downscaled.</param> /// <param name="shouldGenerateThumbnails">Whether thumbnail images will be generated. Used to show small previews of image.</param> public static void TakePhoto(Action <ImagePickResult> onSuccess, Action <string> onError, ImageResultSize maxSize = ImageResultSize.Original, bool shouldGenerateThumbnails = true) { if (AGUtils.IsNotAndroidCheck()) { return; } if (onSuccess == null) { throw new ArgumentNullException("onSuccess", "Success callback cannot be null"); } _onSuccessAction = onSuccess; _onCancelAction = onError; AGUtils.RunOnUiThread(() => AGActivityUtils.TakePhoto(maxSize, shouldGenerateThumbnails)); }
public static void StartRecording([NotNull] string fullFilePath, OutputFormat format = OutputFormat.THREE_GPP, AudioEncoder audioEncoder = AudioEncoder.AMR_NB) { if (fullFilePath == null) { throw new ArgumentNullException("fullFilePath"); } if (AGUtils.IsNotAndroid()) { return; } if (!AGPermissions.IsPermissionGranted(AGPermissions.RECORD_AUDIO)) { Debug.LogError(AGUtils.GetPermissionErrorMessage(AGPermissions.RECORD_AUDIO)); return; } if (_mediaRecorder != null) { Debug.LogWarning( "Can't start recording while another recording is in progress. Please call StopRecording() to stop previous recording."); return; } try { _mediaRecorder = new AndroidJavaObject(C.AndroidMediaMediaRecorder); _mediaRecorder.Call("setAudioSource", MediaRecorderAudioSourceMIC); _mediaRecorder.Call("setOutputFormat", (int)format); _mediaRecorder.Call("setAudioEncoder", (int)audioEncoder); _mediaRecorder.Call("setOutputFile", fullFilePath); _mediaRecorder.Call("prepare"); _mediaRecorder.Call("start"); } catch (Exception e) { if (Debug.isDebugBuild) { Debug.LogError("Failed to start recording audio"); Debug.LogException(e); } } }
/// <summary> /// Places the phone call immediately. /// /// You need <uses-permission android:name="android.permission.CALL_PHONE" /> to use this method! /// </summary> /// <param name="phoneNumber">Phone number.</param> public static void PlacePhoneCall(string phoneNumber) { if (AGUtils.IsNotAndroid()) { return; } if (!AGPermissions.IsPermissionGranted(AGPermissions.CALL_PHONE)) { Debug.LogError(AGUtils.GetPermissionErrorMessage(AGPermissions.CALL_PHONE)); return; } using (var i = new AndroidIntent(AndroidIntent.ActionCall)) { i.SetData(ParsePhoneNumber(phoneNumber)); AGUtils.StartActivity(i.AJO); } }
/// <summary> /// Set a boolean value /// </summary> /// <param name="preferenceFileKey">Desired preferences file. If a preferences file by this name does not exist, it will be created.</param> /// <param name="key">The name of the preference to modify.</param> /// <param name="value">The new value for the preference.</param> /// <param name="mode">Operating mode. Use 0 or MODE_PRIVATE for the default operation.</param> /// <returns>Returns true if the new values were successfully written to persistent storage.</returns> public static bool SetBool(string preferenceFileKey, string key, bool value, int mode = MODE_PRIVATE) { if (AGUtils.IsNotAndroidCheck()) { return(false); } if (string.IsNullOrEmpty(preferenceFileKey)) { throw new ArgumentException("preferenceFileKey"); } if (string.IsNullOrEmpty(key)) { throw new ArgumentException("key"); } var editor = PutValue(preferenceFileKey, key, value, mode); return(Commit(editor)); }
// Enables Immersive Full-Screen Mode on Android device // Unity 5 has added immersive mode by default, so if your using Unity 5 or above, this method is redundant. public static void EnableImmersiveMode(bool sticky = true) { if (AGUtils.IsNotAndroidCheck()) { return; } GoodiesSceneHelper.IsInImmersiveMode = true; int mode = sticky ? ImmersiveFlagSticky : ImmersiveFlagNonSticky; AGUtils.RunOnUiThread( () => { using (var decorView = AGUtils.ActivityDecorView) { decorView.Call("setSystemUiVisibility", mode); } }); }
/// <summary> /// Shows the default Android time picker. /// </summary> /// <param name="hourOfDay">Hour of day.</param> /// <param name="minute">Minute. Not Zero-base as on Android!</param> /// <param name="onTimePicked">Time was picked callback.</param> /// <param name="onCancel">Dialog was cancelled callback.</param> /// <param name="theme">Dialog theme</param> public static void ShowTimePicker(int hourOfDay, int minute, OnTimePicked onTimePicked, Action onCancel, AGDialogTheme theme = AGDialogTheme.Default) { if (AGUtils.IsNotAndroidCheck()) { return; } AGUtils.RunOnUiThread(() => { var listener = new AGDateTimePicker.OnTimeSetListenerPoxy(onTimePicked); int themeResource = AndroidDialogUtils.GetDialogTheme(theme); var dialog = AndroidDialogUtils.IsDefault(themeResource) ? new AndroidJavaObject(TimePickerClass, AGUtils.Activity, listener, hourOfDay, minute, true) : new AndroidJavaObject(TimePickerClass, AGUtils.Activity, themeResource, listener, hourOfDay, minute, true); dialog.Call("setOnCancelListener", new DialogOnCancelListenerPoxy(onCancel)); dialog.Call("show"); }); }
/// <summary> /// Open application details settings /// </summary> /// <param name="package">Package of the application to open settings</param> public static void OpenApplicationDetailsSettings(string package) { if (AGUtils.IsNotAndroidCheck()) { return; } var intent = new AndroidIntent(ACTION_APPLICATION_DETAILS_SETTINGS); intent.SetData(AndroidUri.Parse(string.Format("package:{0}", package))); if (intent.ResolveActivity()) { AGUtils.StartActivity(intent.AJO); } else { Debug.LogWarning("Could not open application details settings for package " + package + ". Most likely application is not installed."); } }
public CellInfo(AndroidJavaObject ajo) { if (AGUtils.IsNotAndroid() || !Check.IsSdkGreaterOrEqual(AGDeviceInfo.VersionCodes.JELLY_BEAN_MR1)) { return; } if (!Check.IsSdkGreaterOrEqual(AGDeviceInfo.VersionCodes.P)) { cellConnectionStatus = Connection.Unknown; } else { cellConnectionStatus = (Connection)ajo.CallInt("getCellConnectionStatus"); } timeStamp = ajo.CallLong("getTimeStamp"); isRegistered = ajo.CallBool("isRegistered"); }
/// <summary> /// Sends the sms using Android intent. /// </summary> /// <param name="phoneNumber">Phone number.</param> /// <param name="message">Message.</param> /// <param name="withChooser">If set to <c>true</c> with chooser.</param> /// <param name="chooserTitle">Chooser title.</param> public static void SendSms(string phoneNumber, string message, bool withChooser = true, string chooserTitle = "Send SMS...") { if (AGUtils.IsNotAndroidCheck()) { return; } var intent = CreateSmsIntent(phoneNumber, message); if (withChooser) { AGUtils.StartActivityWithChooser(intent.AJO, chooserTitle); } else { AGUtils.StartActivity(intent.AJO); } }
public static void ShowDatePickerWithLimits(int year, int month, int day, OnDatePicked onDatePicked, Action onCancel, DateTime minDate, DateTime maxDate, AGDialogTheme theme = AGDialogTheme.Default) { if (AGUtils.IsNotAndroid()) { return; } AGUtils.RunOnUiThread(() => { var dialog = CreateDatePickerDialog(year, month, day, onDatePicked, onCancel, theme); var picker = dialog.CallAJO("getDatePicker"); picker.Call("setMinDate", minDate.ToMillisSinceEpoch()); picker.Call("setMaxDate", maxDate.ToMillisSinceEpoch()); AndroidDialogUtils.ShowWithImmersiveModeWorkaround(dialog); }); }
/// <summary> /// Shows the default Android time picker. /// </summary> /// <param name="hourOfDay">Hour of day.</param> /// <param name="minute">Minute. Not Zero-base as on Android!</param> /// <param name="onTimePicked">Time was picked callback.</param> /// <param name="onCancel">Dialog was cancelled callback.</param> /// <param name="theme">Dialog theme</param> /// <param name="is24HourFormat">If the picker is in 24 hour format</param> public static void ShowTimePicker(int hourOfDay, int minute, OnTimePicked onTimePicked, Action onCancel, AGDialogTheme theme = AGDialogTheme.Default, bool is24HourFormat = true) { if (AGUtils.IsNotAndroidCheck()) { return; } AGUtils.RunOnUiThread(() => { var listener = new OnTimeSetListenerPoxy(onTimePicked); int themeResource = AndroidDialogUtils.GetDialogTheme(theme); var dialog = AndroidDialogUtils.IsDefault(themeResource) ? new AndroidJavaObject(TimePickerClass, AGUtils.Activity, listener, hourOfDay, minute, is24HourFormat) : new AndroidJavaObject(TimePickerClass, AGUtils.Activity, themeResource, listener, hourOfDay, minute, is24HourFormat); dialog.Call("setOnCancelListener", new DialogOnCancelListenerPoxy(onCancel)); AndroidDialogUtils.ShowWithImmersiveModeWorkaround(dialog); }); }
/// <summary> /// Computes the approximate distance in meters between two locations, and optionally the initial and final bearings of the shortest path between them. /// Distance and bearing are defined using the WGS84 ellipsoid. /// /// The computed distance is stored in results[0]. /// If results has length 2 or greater, the initial bearing is stored in results[1]. /// If results has length 3 or greater, the final bearing is stored in results[2]. /// </summary> /// <param name="startLatitude"></param> /// <param name="startLongitude"></param> /// <param name="endLatitude"></param> /// <param name="endLongitude"></param> /// <param name="results"></param> public static void DistanceBetween( double startLatitude, double startLongitude, double endLatitude, double endLongitude, float[] results) { if (AGUtils.IsNotAndroidCheck()) { return; } if (results == null || results.Length < 1) { throw new ArgumentException("results is null or has length < 1"); } LocationUtils.ComputeDistanceAndBearing(startLatitude, startLongitude, endLatitude, endLongitude, results); }
static bool IsNetworkConnected(int networkType) { if (AGUtils.IsNotAndroidCheck()) { return(false); } AndroidJavaObject networkInfo; try { networkInfo = AGSystemService.ConnectivityService.CallAJO("getNetworkInfo", networkType); } catch (/* Null */ Exception) { return(false); } return(networkInfo.Call <bool>("isConnected")); }
/// <summary> /// Required permission: /// <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> /// Check if device is connected to the internet /// </summary> /// <returns>Whether device is connected to the internet</returns> public static bool IsInternetAvailable() { if (AGUtils.IsNotAndroidCheck()) { return(false); } AndroidJavaObject networkInfo; try { networkInfo = AGSystemService.ConnectivityService.CallAJO("getActiveNetworkInfo"); } catch (/* Null */ Exception) { return(false); } return(networkInfo.Call <bool>("isConnected")); }
/// <summary> /// /// Turns on the camera flashlight if available /// /// Required permissions in manifest: /// <uses-permission android:name="android.permission.CAMERA" /> /// <uses-feature android:name="android.hardware.camera" /> /// /// <uses-permission android:name="android.permission.FLASHLIGHT"/> /// <uses-feature android:name="android.hardware.camera.flash" android:required="false" /> /// </summary> public static void Enable() { if (AGUtils.IsNotAndroidCheck()) { return; } if (!HasFlashlight()) { Debug.LogWarning("This device does not have a flashlight"); return; } if (_camera != null) { Debug.LogWarning("Flashlight is already on"); return; } try { AGUtils.RunOnUiThread(() => { using (var camAJC = new AndroidJavaClass(CameraClass)) { var cam = camAJC.CallStaticAJO("open"); var camParams = cam.CallAJO("getParameters"); camParams.Call("setFlashMode", CameraParameters_FLASH_MODE_TORCH); cam.Call("setParameters", camParams); cam.Call("startPreview"); _camera = cam; } }); } catch (Exception e) { if (Debug.isDebugBuild) { Debug.Log("Could not enable flashlight:" + e.Message); } } }
AudioAttributes(Usage usage, ContentType contentType, Flags flags) { if (AGUtils.IsNotAndroid()) { Debug.LogError("This class should be used only on Android, errors ahead"); return; } if (!Check.IsSdkGreaterOrEqual(AGDeviceInfo.VersionCodes.LOLLIPOP)) { Debug.LogError("This class should be used on API level 21 and higher, errors ahead"); return; } AJO = new AndroidJavaObject(C.AndroidMediaAudioAttributesBuilder) .CallAJO("setUsage", (int)usage) .CallAJO("setContentType", (int)contentType) .CallAJO("setFlags", (int)flags) .CallAJO("build"); }
/// <summary> /// Sends the email using Android intent. /// </summary> /// <param name="recipients">Recipient email addresses.</param> /// <param name="subject">Subject of email.</param> /// <param name="body">Body of email.</param> /// <param name="attachment">Image to send.</param> /// <param name="withChooser">If set to <c>true</c> with chooser.</param> /// <param name="chooserTitle">Chooser title.</param> /// <param name="cc">Cc recipients. Cc stands for "carbon copy." /// Anyone you add to the cc: field of a message receives a copy of that message when you send it. /// All other recipients of that message can see that person you designated as a cc /// </param> /// <param name="bcc">Bcc recipients. Bcc stands for "blind carbon copy." /// Anyone you add to the bcc: field of a message receives a copy of that message when you send it. /// But, bcc: recipients are invisible to all the other recipients of the message including other bcc: recipients. /// </param> public static void SendEmail(string[] recipients, string subject, string body, Texture2D attachment = null, bool withChooser = true, string chooserTitle = "Send mail...", string[] cc = null, string[] bcc = null) { if (AGUtils.IsNotAndroidCheck()) { return; } var intent = CreateEmailIntent(recipients, subject, body, attachment, cc, bcc); if (withChooser) { AGUtils.StartActivityWithChooser(intent.AJO, chooserTitle); } else { AGUtils.StartActivity(intent.AJO); } }
/// <summary> /// Required permission: <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> /// </summary> /// <returns></returns> public static bool IsWifiEnabled() { if (AGUtils.IsNotAndroidCheck()) { return(false); } try { return(AGSystemService.WifiService.Call <bool>("isWifiEnabled")); } catch (/* Null */ Exception e) { if (Debug.isDebugBuild) { Debug.LogWarning("Failed to check if wi-fi is enabled. Error: " + e.Message); } return(false); } }
private static T GetDeviceStrProperty <T>(string className, string propertyName) { if (AGUtils.IsNotAndroidCheck()) { return(default(T)); } try { using (var version = new AndroidJavaClass(className)) { return(version.GetStatic <T>(propertyName)); } } catch (Exception e) { Debug.LogWarning(String.Format("Failed to get property: {0} of class {1}, reason: {2}", propertyName, className, e.Message)); return(default(T)); } }
private static string GetBuildClassStaticStr(string fieldName) { if (AGUtils.IsNotAndroidCheck()) { return(string.Empty); } try { using (var version = new AndroidJavaClass(BuildClass)) { return(version.GetStaticStr(fieldName)); } } catch (Exception e) { Debug.LogWarning("Failed to get property " + fieldName + ". Check device API level. " + e.Message); return(string.Empty); } }