Проблемы при попытке вызова C# метода из Java плагина
У меня есть рабочее android-приложение, которое получает входящие уведомления и выводит их на экран с помощью текста... Я взял фрагмент кода и сделал плагин для Unity. Изначально я пытался вызывать метод который должен срабатывать при получении нового уведомления из C#, но позже по рекомендациям одного человека из данного сообщества я попытался вызвать C# метод из моего Java-класса, и передать ему 2 переменные, в которых и содержатся фрагменты входящего уведомления:
public class ReceiveIncomingNotificationsAndPassThemToMyUnityAppClass extends NotificationListenerService {
private final String UnityCallbackObject = "ReceiveIncomingNotifications";
private final String UnityCallbackMethod = "Receive";
Context context;
public String title;
public String text;
@Override
public void onNotificationPosted(StatusBarNotification sbn) {
String pack = sbn.getPackageName();
String ticker ="";
if(sbn.getNotification().tickerText !=null) {
ticker = sbn.getNotification().tickerText.toString();
}
Bundle extras = sbn.getNotification().extras;
title = extras.getString("android.title");
text = extras.getCharSequence("android.text").toString();
int id1 = extras.getInt(Notification.EXTRA_SMALL_ICON);
Bitmap id = sbn.getNotification().largeIcon;
if(id != null) {
ByteArrayOutputStream stream = new ByteArrayOutputStream();
id.compress(Bitmap.CompressFormat.PNG, 100, stream);
byte[] byteArray = stream.toByteArray();
}
UnityPlayer.UnitySendMessage(UnityCallbackObject, UnityCallbackMethod, title);
UnityPlayer.UnitySendMessage(UnityCallbackObject, UnityCallbackMethod, text);
}
}
Соответственно мой c# код выглядел так:
public void Receive(string title, string text)
{
// var plugin = new AndroidJavaClass("com.alexcompany.receiveincomingnotificationsandpassthemtomyunityapp.ReceiveIncomingNotificationsAndPassThemToMyUnityAppClass");
Title = title;
Text = text;
// Title = plugin.Get<string>("title");
// Text = plugin.Get<string>("text");
TextForTitle.text = Title;
TextForBody.text = Text;
}
}
При этой реализации я не получал никаких ошибок в logcat, но и при получении нового уведомления в моем Unity приложении мой текст оставался пустым...
Дальше я решил сделать как тут:
https://stackoverflow.com/questions/32944478/callback-listener-in-unity-how-to-call-script-file-method-from-unityplayeracti/41018028#41018028
и вот как стал выглядеть мой Java-class:
public class ReceiveIncomingNotificationsAndPassThemToMyUnityAppClass extends NotificationListenerService {
Context context;
public String title;
public String text;
public void onNotificationPosted(StatusBarNotification sbn, PluginCallback callback) {
String pack = sbn.getPackageName();
String ticker ="";
if(sbn.getNotification().tickerText !=null) {
ticker = sbn.getNotification().tickerText.toString();
}
Bundle extras = sbn.getNotification().extras;
title = extras.getString("android.title");
text = extras.getCharSequence("android.text").toString();
int id1 = extras.getInt(Notification.EXTRA_SMALL_ICON);
Bitmap id = sbn.getNotification().largeIcon;
if(id != null) {
ByteArrayOutputStream stream = new ByteArrayOutputStream();
id.compress(Bitmap.CompressFormat.PNG, 100, stream);
byte[] byteArray = stream.toByteArray();
}
callback.Receive(title, text);
}
}
так же был добавлен Java interface:
public interface PluginCallback {
public void Receive(String title, String text);
}
и теперь вот как стал выглядеть мой C# код:
public class AndroidPluginCallback : AndroidJavaProxy
{
public AndroidPluginCallback() : base("com.alexcompany.receiveandpassnotificationsyomyunityapplibrary.PluginCallback") { }
public string Title;
public string Text;
public TextMeshPro TextForTitle;
public TextMeshPro TextForBody;
public void Receive(string title, string text)
{
TextForTitle = GameObject.Find("TextForTitle").GetComponent<TextMeshPro>();
TextForBody = GameObject.Find("TextForBody").GetComponent<TextMeshPro>();
Title = title;
Text = text;
TextForTitle.text = Title;
TextForBody.text = Text;
}
}
И еще один C# код:
public class ReceiveIncomingNotificationsFromJavaClass : MonoBehaviour
{
public void Start()
{
AndroidJavaObject pluginClass = new AndroidJavaObject("com.alexcompany.receiveandpassnotificationsyomyunityapplibrary.ReceiveIncomingNotificationsAndPassThemToMyUnityAppClass");
pluginClass.Call("onNotificationPosted", new AndroidPluginCallback());
}
}
и за одно Android Mainfest из моего плагина сюда:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.alexcompany.receiveandpassnotificationsyomyunityapplibrary">
<uses-permission android:name="android.permission.RECEIVE_SMS" />
<uses-permission android:name="android.permission.READ_SMS" />
<application>
<service
android:name="com.alexcompany.receiveandpassnotificationsyomyunityapplibrary.ReceiveIncomingNotificationsAndPassThemToMyUnityAppClass"
android:permission="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE">
<intent-filter>
<action android:name="android.service.notification.NotificationListenerService" />
</intent-filter>
</service>
</application>
</manifest>
При этой реализации я не получал никаких ошибок в logcat, но и при получении нового уведомления в моем Unity приложении мой текст оставался пустым...
В чем ошибка?
Ответы (1 шт):
Первый вариант:
UnityPlayer.UnitySendMessage(UnityCallbackObject, UnityCallbackMethod, title);
здесь вы пытаетесь вызвать метод Receive, передав ему один параметр title, но сам метод объявили с двумя параметрами - куда уходит вызов неизвестно, но точно не в ваш метод.
Второй вариант: то же, только в обратном направлении: onNotificationPosted у вас с двумя параметрами, а вызвать пытаетесь с одним. Плюс вы изменили сигнатуру метода и система его не вызовет никогда - вы вообще не должны вызывать его сами. Вместо этого можно объявить колбек статическим полем сервиса, из шарпа передать его экземпляр этому полю, на java проверить валидность и вызвать. Что-то вроде:
public class ReceiveIncomingNotificationsAndPassThemToMyUnityAppClass extends NotificationListenerService {
private static PluginCallback callback;
@Override
public void onNotificationPosted(StatusBarNotification sbn) {
if (callback != null) {
Bundle extras = sbn.getNotification().extras;
String title = extras.getString("android.title");
String text = extras.getCharSequence("android.text").toString();
callback.Receive(title, text);
}
}
public static void setCallback(PluginCallback c) {
callback = c;
}
}
public class ReceiveIncomingNotificationsFromJavaClass : MonoBehaviour
{
public void Start()
{
AndroidJavaClass serviceClass = new AndroidJavaClass("com.alexcompany.receiveandpassnotificationsyomyunityapplibrary.ReceiveIncomingNotificationsAndPassThemToMyUnityAppClass");
serviceClass.CallStatic("setCallback", new AndroidPluginCallback());
}
}
P.S. с c# и юнитами знаком очень поверхностно - скорее всего код не совсем корректный и есть более правильное решение.