AndroidJavaClass Call non-static method from Jar to return String with CallLog
Hello people,
This is my first time posting a question here so please bear with me. I am trying to build a Unity app that will copy the call details of the last received phone call whenever a button is pressed. I have gotten as far as creating a test method that returns the value "1", so I am sure that the AndroidJavaClass.CallStatic() method is working properly because it returns this value to prove that it's live, however the call log uses a Context variable,, thus I had built a non-static method that should return a String variable into Unity. The Context variable is set to "this" at the beginning of the script.
I have tested it on several devices but the string always returns as 0 despite having no errors in Android Studio.
The line I use in Unity to try an receive the string from the Jav file is:
AndroidJavaClass jc = new AndroidJavaClass("com.package.test.PluginTest");
string call_log = jc.Call("getCallDetails");
I also display the call_log variable on an UI.Text element see, however after the above instruction the text disappears, assuming that the returned string is "".
Can anyone assist me with an Android Studio method that would return the last received call details (duration, number, date&time) as a string with a delimiter?
Answer by Loki606 · Mar 21, 2018 at 05:02 PM
Hello people,
After a couple days of research I managed to figure this out so here's a detailed explanation of what needs to be done:
The android part of the build will be explained first as it was the one I found to be the most vague.
1. Create a new project in Android Studio and add a new Java Class in your "java" folder and the first folder by right clicking, selecting New -> Java Class.
2. As you may have noticed, you are only able to use CallLog.Calls() method from within a non-static method and it was necessary for me to have a "Context" variable. In order for us to be able to get the context variable, I had to first add the following:
public class PluginTest extends Activity {
private static PluginTest m_instance;
public PluginTest() {
m_instance = this;
}
public static PluginTest instance() {
if (m_instance == null) {
m_instance = new PluginTest();
}
return m_instance;
}
The above will be referenced later from Unity. Next I wrote the "getCallDetails" method which took a Context variable as a parameter:
public String[] getCallDetails(Context mContext) {
String[] sb = new String[11];
Cursor managedCursor = mContext.getContentResolver().query(CallLog.Calls.CONTENT_URI, null, null, null, CallLog.Calls.DATE + " DESC");
int number = managedCursor.getColumnIndex(CallLog.Calls.NUMBER);
int type = managedCursor.getColumnIndex(CallLog.Calls.TYPE);
int date = managedCursor.getColumnIndex(CallLog.Calls.DATE);
int duration = managedCursor.getColumnIndex(CallLog.Calls.DURATION);
//sb.append("Call Details :");
int counter = 10;
while (managedCursor.moveToNext() && counter > 0) {
String phNumber = managedCursor.getString(number);
String callType = managedCursor.getString(type);
String callDate = managedCursor.getString(date);
Date callDayTime = new Date(Long.valueOf(callDate));
String callDuration = managedCursor.getString(duration);
String dir = null;
int dircode = Integer.parseInt(callType);
switch (dircode) {
case CallLog.Calls.OUTGOING_TYPE:
dir = "OUTGOING";
break;
case CallLog.Calls.INCOMING_TYPE:
dir = "INCOMING";
break;
case CallLog.Calls.MISSED_TYPE:
dir = "MISSED";
break;
}
sb[counter] = ("\nPhone Number:--- " + phNumber + " \nCall Type:--- "
+ dir + " \nCall Date:--- " + callDayTime
+ " \nCall duration in sec :--- " + callDuration);
counter -= 1;
}
managedCursor.close();
return sb;
}
I never touched the manifest here, but it's worth noting that for some weird reason Unity will not automatically add the required permissions in the manifest so we will have to modify that using another "trickedy" trick.
Next I created the unity part of the app, added a button to get the call log and a text UI element to write to. I also added some text after every AndroidJava related operation to track the issues:
public void test ()
{
System.String[] call_log = new System.String[11];
text.text += "Running";
try{
AndroidJavaClass unitydefault = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
AndroidJavaObject activity = unitydefault.GetStatic<AndroidJavaObject>("currentActivity");
AndroidJavaObject context = activity.Call<AndroidJavaObject>("getApplicationContext");
text.text += "\nContext: "+ context.ToString();
AndroidJavaClass jc = new AndroidJavaClass ("com.easyrider.osiris_pc.testplugin.PluginTest");
AndroidJavaObject jo = jc.CallStatic<AndroidJavaObject>("instance");
text.text += "\nInstance: "+jo.ToString();
call_log = jo.Call<System.String[]>("getCallDetails", activity);
text.text += "\nSuccess: " + call_log[5];
}catch(Exception e){
text.text += "\nError: " + e.ToString ();
}
The plugin was added into the usual path for Unity: Assets/Plugins/Android/libs/ as for the manifest, in order for Unity to add this for the first time I believe you have to build your project so I would advise doing so. You should then be able to find it in the following directory: YourUnityProject\Temp\StagingArea
Once you have it, open that baby up with Visual Studio or your weapon of choice to edit it and add the following:
<uses-permission android:name="android.permission.READ_CALL_LOG"/>
<uses-permission android:name="android.permission.WRITE_CALL_LOG"/>
Normally the "READ_CALL_LOG" permission should be enough for this but I went balls deep this time.
That would be the gist of this "easy peazy lemon squeezy" plugin to get the call log. I guess you can replace the "getCallDetails" method with anything you may need and you have yourself any plugin you could need.
Since there is a serous lack of compact training material online about this in Unity, please feel free to ask anything and I will do my best to answer even though I'm not a wizard either.
Peace my bruddahs, you now kno the wae