Extending Android Studio's (Java) AppComapatActivity to work as AAR with Unity C#

Give us as much detail as possible regarding the issue you're experiencing.

Unity Editor version: 2022.2.0b8 :
ML2 OS version: September 2022 B3E.220818.12-R.085 :
MLSDK version: 0.53.3 :
Host OS: Windows 11 : (Windows)

Error: No error. Program stops reading from Java script
** Continuation of App Development: How do I access Android Libraries in Unity C# so the app shows Wifi SSIDs on ML2 device? **

I am trying to sense all Wifi signals in Magic Leap. Unity does not natively seem to read signals through C#. Instead, the solution seems to be creating an Android Studio library, making an AAR and sending to Unity, then using callbacks to the Java code.

There are several YouTube videos that support getting the SSID in Java:
(single, simple):

Creating Android Plugin (AAR) for Unity with Android Toast

However, this file needs to extend from AppCompatActivity. Without this extension, the AAR I included in my Unity's Android/Plugins/unity-module.aar can read simple items like Add(i, j). That is, I can click a UI button in Unity, it reads "var result = _pluginInstance.Call("Add", 10, 10)" through the AAR, and the correct result is displayed in the Magic Leap headset.

However, the reading of the Wifi signals need to use WifiInfo and WifiManager. In Java, when I do not extend AppCompatActivity, these are colored red. When I extend it, it compiles, but my button cannot read the files once it gets to WifiInfo/WifiManager.

I heard several solutions (see my prior ML Forum post in the introduction), which range from:

  1. Write the C# jni equivalent of java code that would be used for accessing the wifi manager" or
  2. Create a .aar plugin of that java code, import it into unity and write the C# jni equivalent to invoke the simpler functions of your aar plugin".

I think I am performing #2 above correctly, just getting stuck on Extending the code.

So far, I have tried:

  1. Finding UnityPlayer.java (which extends Activity) and instead extending AppCompatActivity, which breaks the code.

  2. "Put all the Extended Libraries in Android into Unity's Android/Plugin folder"

Starting AppCompatActivity from Unity C# Script

https://forum.unity.com/threads/starting-appcompatactivity-from-unity-c-script.942679/
... There are tons of External libraries. I included classes.jar into the Plugin folder (read from hovering over the wifimanager import), resulting in no change.

  1. ...or even "Modifying UnityPlayerActivity":
    java - Android UnityPlayerActivity Action Bar - Stack Overflow

It cannot be this hard. Has anyone gotten Magic Leap to read Wifi Signals / RSSI stats? (Basically, all the info in getConnectionInfo()). If so, could you please provide git code, or simple basic steps?

Thanks,
Clint

1 Like

Thank you for your post @Clint. I'd be interested if anyone in the community got this going. I'll check with our engineers and if I'm able to share some insight I will.

1 Like

Thanks, KDowny, I'd appreciate that.

I didn't mention above, but the specific code I'm trying to use is:

  1. Get single SSID (Simple, screenshot at 7 min)):
    How to get SSID of the Wifi using getConnectionInfo API in your Android App? - SDK 29 (Android 10) - YouTube
  • This works on a phone, AND the headset as a 2D android project, but NOT when I call it through Unity. We want Unity for the 3D elements I'll use alongside just getting a value.
  1. Get all SSID's (complex, the one I want):
    how to get wifi list in android programmatically - Solution Code Android\Android Studio Tutorial - YouTube
  • Didn't even get this to work on the phone.

These might help, if working alongside what I'm trying to do. Viewing Wifi signals by either one through the Headset via C# is the goal.

1 Like

Any ML Developer support on this would be helpful.

1 Like

@Clint Have you tried something like this? Android Wifi Manager | Network | Unity Asset Store

1 Like

WiFi SSID, Level, and Security Type were obtained. This asset automatically sets permissions, but the following were not set automatically and need to be added to the manifest.

  <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

@sengleman Thanks, I'll give that a shot. One review states: "Easy to use but deprecated with API 29 (Android 10)", which is my exact problem (i.e., no getConnectionInfo calls, which are needed to get the SSIDs). But some are having success, so I hope to join that crowd.

@tokufxug Glad it's working for you. I'm assuming you used this same Asset Store package that Sengleman is talking about? Either way, I'll download it today and see what I can do, but glad it's working for someone. Also, appreciate the tip about adding the permission (I'm adding all of them, Fine, Coarse, Access/Change Wifi state, Internet, etc.)

If I run into issues, I'll reach out again. Thanks you guys!

1 Like

@Clint

I'm assuming you used this same Asset Store package that Sengleman is talking about?

Yes. The following assets were used

using FSG.Android.Wifi;
using System.Collections;
using UnityEngine;
using TMPro;
using System.Text;

public class WifiExample : MonoBehaviour
{
    [SerializeField]
    private TextMeshProUGUI info;

    void Start()
    {
        StartCoroutine(PrintWifiNetworks());
    }

    private IEnumerator PrintWifiNetworks()
    {
        if (AndroidWifiManager.IsWifiEnabled() == false)
        {
            AndroidWifiManager.SetWifiEnabled(true);
        }
        AndroidWifiManager.StartScan();
        yield return new WaitForSeconds(1);

        var results = AndroidWifiManager.GetScanResults();
        StringBuilder sb = new StringBuilder();
        foreach (AndroidWifiScanResults result in results)
        {
           sb.Append(string.Format("SSID: {0} Signal: {1}dBm Security Type: {2}\n", result.SSID, result.level, result.securityType));
        }
        info.text = sb.ToString();
    }
}

Assets\Plugins\Android\AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.unity3d.player" xmlns:tools="http://schemas.android.com/tools">
  <application>
    <activity android:name="com.unity3d.player.UnityPlayerActivity" android:theme="@style/UnityThemeSelector">
      <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
      </intent-filter>
      <meta-data android:name="unityplayer.UnityActivity" android:value="true" />
    </activity>
  </application>
  <uses-permission android:name="android.permission.CAMERA" />
  <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
  <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
  <uses-permission android:name="com.magicleap.permission.HAND_TRACKING" />
  <uses-permission android:name="com.magicleap.permission.VOICE_INPUT" />
  <uses-permission android:name="com.magicleap.permission.SPATIAL_ANCHOR" />
  <uses-permission android:name="com.magicleap.permission.WEBVIEW" />
  <uses-permission android:name="com.magicleap.permission.WORLD_RECONSTRUCTION" />
  <uses-permission android:name="com.magicleap.permission.MARKER_TRACKING" />
  <uses-permission android:name="com.magicleap.permission.SPATIAL_MAPPING" />
  <uses-permission android:name="com.magicleap.permission.EYE_TRACKING" />
  <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
  <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
  <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
  <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
</manifest>

Thanks @tokufxug , I got my project to work after a bit of tinkering. Looking at how you wrote your code, I'll definitely use some to make my code more robust (yielding, using interfaces, etc.). Sincerely, thanks for your help.

As a recap, I had to ensure that I was using the native Unity SDK, JDK, and NDK. This was the main problem. Along the way I had needed to find an SDK, get a specific NDK (r22b or something), and even the JDK was stolen from Android Studio. Ultimately, had to uninstall Unity completely and reinstall so that Unity could see its own versions in External Tools vs. manually finding those 3.

I did the following configurations changes, as well as wrote some code similar to yours to swap text from phone to ML headset, and it worked:

Installing PHONE Wifi scripts into the working MAGIC LEAP Example scene (2022.0.09b):

  1. Open preconfigured "ML Examples" (installed from ML Hub). Then, import the Unity Store FSG asset.

  2. Change OtherSettings => Rendering => Color Space from Gamma to Linear.

  3. Graphics API’s don’t show if “Auto” is checked. Instead, uncheck the Rendering => Auto Graphics API, remove OpenGLES3, and ensure only Vulkan is listed under “Graphics API” heading.

  4. Change ‘Texture compression format’ from ASTC to DXT+RGTC

  5. Change Identification => Minimum API Level (dropdown) to Android 10 (API level 29)

  6. Change Configuration => Scripting backend => IL2CPP (not Mono)

  7. Change Target Architectures from ARMv7 to “x86-64 (Chrome OS and Magic Leap 2)”

  8. If swapped from older Unity, prefabs and modes might be pink.

  • Change Universal Render Pipeline settings by going to Project Settings => Graphics => Scriptable Render Pipeline Settings.
  • Change from NONE to (find) UPR_PipelineAsset (Uneversal Render Pipeline Asset)