Android Native Plugin
One of the more challenging aspects during development was working with Android's Native Plugin. This plugin was poorly documented for Unity and lacked online support for certain features, such as alarm settings.
This necessitated a deeper dive into the plugin and solving persistent issues. Below is an excerpt of the code written in Unity to handle alarms.
Certain challenges arose from C# lacking access to ArrayLists, requiring the creation of custom solutions using Android's Native Plugin.
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class Alarm : MonoBehaviour
{
//https://developer.android.com/guide/components/intents-common#Clock
private const string ACTION_SET_ALARM = "android.intent.action.SET_ALARM";
private const string EXTRA_HOUR = "android.intent.extra.alarm.HOUR";
private const string EXTRA_MINUTES = "android.intent.extra.alarm.MINUTES";
private const string EXTRA_MESSAGE = "android.intent.extra.alarm.MESSAGE";
private const string EXTRA_VIBRATE = "android.intent.extra.alarm.VIBRATE";
private const string EXTRA_DAYS = "android.intent.extra.alarm.DAYS";
// Create an alarm using provided settings
public void OnClick(AlarmSettings settings)
{
string finalName = settings.Name();
if(finalName == string.Empty) finalName = "Sleep Pet";
CreateAlarm(finalName, settings.Hour, settings.Minute, settings.Vibrate(), settings.Days());
}
// Configure and initiate alarm creation
private void CreateAlarm(string message, int hour, int minutes, bool vibrate, List m_Days)
{
// Prepare the Android Intent for alarm creation
var intentAJO = new AndroidJavaObject("android.content.Intent", ACTION_SET_ALARM);
intentAJO
.Call("putExtra", EXTRA_MESSAGE, message)
.Call("putExtra", EXTRA_HOUR, hour)
.Call("putExtra", EXTRA_MINUTES, minutes)
.Call("putExtra", EXTRA_VIBRATE, vibrate);
// Custom ArrayList int
if(m_Days != null && m_Days.Count > 0){ // if days should repeat
// get an instance of a Java ArrayList
AndroidJavaObject arrayList = new AndroidJavaObject("java.util.ArrayList");
// get an instance of java Integer class :
// ArrayLists use generics, so a type doesnt need to be assigned to them on creation
// Java's generics try to match C#'s int against Java data types - in this case int does not exist
// Thus in order to get a suitable match we need to create an instance of an unsigned Integer
AndroidJavaClass integerClass = new AndroidJavaClass("java.lang.Integer");
// Loop through a list of int's that correspond with key's for the Java Calender classes enum for Days
for(int i = 0;i < m_Days.Count;i++){
// using CallStatic over Call lets us access the static method to interpret non-native data types in Java
// This lets us convert the C#/C/C++ implementation of int to Java's Integer type
AndroidJavaObject intToInteger = integerClass.CallStatic("valueOf", m_Days[i]);
// Now that the type is native to Java, it's possible to access the ArrayList like intended
arrayList.Call("add", intToInteger);
}
// Add the list to the EXTRA_DAYS android intents
intentAJO.Call("putExtra", EXTRA_DAYS, arrayList);
}
GetUnityActivity().Call("startActivity", intentAJO);
}
AndroidJavaObject GetUnityActivity()
{
using (var unityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer"))
{
return unityPlayer.GetStatic("currentActivity");
}
}
}