Gọi các phương thức không tĩnh trên các plugin Unity Android tùy chỉnh


8

Tôi đang cố gắng hiểu cách xây dựng các plugin Android của riêng mình cho Android.

Tôi đạt được để gọi các phương thức tĩnh trên lớp Java của tôi (một phương thức được tạo trên AndroidStudio), nhưng tôi thực sự KHÔNG THỂ gọi các phương thức không tĩnh.

Tôi kiểm tra các liên kết đó:

Nhưng không có tác dụng.

Tôi đang cố gắng nhận cuộc gọi từ một nút từ Unity như:

AndroidJavaClass UnityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
AndroidJavaObject currentActivity = UnityPlayer.Get<AndroidJavaObject>("currentActivity");
currentActivity.Call("SayHi");

Và hoạt động của tôi trên Android trông giống như:

public class MainActivity extends UnityPlayerActivity {
    private static final String TAG = "LibraryTest";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.d(TAG, "Created!");
    }

    public void SayHi()
    {
        Log.d(TAG, "HI_");
    }
}

ADB của tôi đang gửi thông điệp này: nhập mô tả hình ảnh ở đây

Tôi cũng đã thử gọi thay vì UnityPlayer gọi nó như sau:

AndroidJavaClass pluginClass = new AndroidJavaClass("com.example.eric.librarytest.MainActivity");

EDIT: Đây là AndroidManifest.xml của tôi

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.eric.librarytest"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="24"
        android:targetSdkVersion="28" />

    <application android:label="@string/app_name" >
        <activity
            android:name="com.example.eric.librarytest.MainActivity"
            android:configChanges="fontScale|keyboard|keyboardHidden|locale|mnc|mcc|navigation|orientation|screenLayout|screenSize|smallestScreenSize|uiMode|touchscreen"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

Nhưng không hoạt động cho các phương thức không tĩnh, nó chỉ hoạt động cho các phương thức tĩnh nếu tôi làm pluginClass.CallStatic(""), có ý tưởng nào không?

EDIT 2:

  • Taras Leskiv đề nghị thay đổi UnityPlayer.Get thành UnityPlayer.GetStatic, nhưng sau đó tôi gặp lỗi sau:

    lỗi: java.lang.NoSuchMethodError: không có phương thức không tĩnh với tên = 'SayHi' chữ ký = '() V' trong lớp Ljava.lang.Object;

  • Proguard không hoạt động.

Bạn có thể thêm AndroidManifest.xml của mình không? Bạn có MainActivity bên trong không?
JeanLuc

@JeanLuc đã thêm vào bài đăng, và vâng, nó ở bên trong như bạn có thể thấy :(
Lotan

Có thực sự hoạt động của bạn trở lại? Nếu vậy Unity có thể không biết về loại đó và nghĩ rằng đó là một Activity. Vì vậy, bạn có thể cần phải đúc nó bằng cách nào đó.
tynn

@tynn đó là câu trả lời của Jean Bouvattier, nhưng nó không giải thích làm thế nào để đạt được dàn diễn viên này.
Lotan

Câu trả lời:


1

Khi bạn đang làm điều này:

AndroidJavaClass UnityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
AndroidJavaObject currentActivity = UnityPlayer.Get<AndroidJavaObject>("currentActivity");
currentActivity.Call("SayHi");

Nó không hoạt động vì currentActivitytrường tĩnh, điều bạn nên làm là:

AndroidJavaClass UnityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
AndroidJavaObject currentActivity = UnityPlayer.GetStatic<AndroidJavaObject>("currentActivity");
currentActivity.Call("SayHi");

Chú ý UnityPlayer.GetStatic phần

Đây là đoạn tiện lợi khác từ một trong các plugin của tôi:

    static AndroidJavaObject _activity;

    public static AndroidJavaObject Activity
    {
        get
        {
            if (_activity == null)
            {
                var unityPlayer = new AndroidJavaClass(C.ComUnity3DPlayerUnityPlayer);
                _activity = unityPlayer.GetStatic<AndroidJavaObject>("currentActivity");
            }
            return _activity;
        }
    }

Sau đó, tôi nhận được lỗi sau: java.lang.NoSuchMethodError: không có phương thức không tĩnh với name = 'SayHi' chữ ký = '() V' trong lớp Ljava.lang.Object; :(
Lotan

Được rồi, đó là lỗi tiếp theo, cũng có thể kiểm tra xem bạn đã bật proguad chưa vì nó có thể làm xáo trộn mã java khi xây dựng
Taras Leskiv

Không, proguard bị vô hiệu hóa vì tôi không có thư mục proguard, còn gì nữa không?
Lotan

Tôi cũng đang sử dụng app-debug.aar thay vì phát hành, để chắc chắn rằng Proguard không thực hiện thu nhỏ.
Lotan

0

Có lẽ nó phải làm với sự kế thừa java: AndroidJavaObject hiện tại của bạn là của lớp com.unity3d.player.UnityPlayer nhưng lớp này không có SayHiphương thức, bạn nên truyền đối tượng của mình MainActivitytrước khi gọi phương thức của bạn.


Nhưng MainActivity cũng là một AndroidJavaClass, bạn sẽ làm thế nào? Bạn có thể gửi một ví dụ xin vui lòng?
Lotan

Tôi không thể giúp bạn nhiều hơn bây giờ, nhưng liên kết này có thể sẽ giúp bạn: devua.co/2016/07/30/NH
Jean Bouvattier

Tôi đã thử liên kết nhưng không hoạt động, có lẽ tôi đang làm gì đó với diễn viên? oO
Lotan

0

Mã của tôi đã đúng, vấn đề là cấu trúc Project.

Dự án của tôi là như sau:

Assets
├── Plugins
   ├── classes.jar

Và nên như thế nào:

Assets
├── Plugins
   ├── Android
      ├── classes.jar

Do obvius (không phải cho tôi) gây ra lỗi spam thư không thể tìm thấy chữ ký, vì vậy phần mềm không thể đọc các lớp đó.


-1

Tất cả những gì bạn cần làm là khai báo bối cảnh tĩnh của riêng bạn trong lớp hoạt động:

public class MainActivity extends UnityPlayerActivity {
    private static final String TAG = "LibraryTest";
    public static Context mContext;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mContext = this;
        Log.d(TAG, "Created!");
    }

    public void SayHi()
    {
        Log.d(TAG, "HI_");
    }
}

Và sau đó chỉ cần gọi bất kỳ phương thức không tĩnh nào từ C # như thế này:

public static void AndroidCallFunction()
{
    using (AndroidJavaClass javaClass = new AndroidJavaClass("com.example.eric.librarytest.MainActivity"))
    {
        using (AndroidJavaObject activity = javaClass.GetStatic<AndroidJavaObject>("mContext"))
        {
            activity.Call("SayHi");
        }
    }
}

NO phương pháp khác với các phương pháp gọi trực tiếp từ mã java. Bạn có thể thực hiện hệ thống nhắn tin của riêng mình bằng các lệnh AndroidJavaProxy và Broadcast mà không cần hoạt động, nhưng đó là một câu hỏi khác.


Cách tiếp cận này (trường ngữ cảnh tĩnh) gây rò rỉ bộ nhớ.
0xBFE1A8

đúng, nhưng nếu có quá nhiều trường tĩnh, thì điều này được thực hiện để giải quyết cách thức hoạt động của ajo
Nikolay Gonza

Một tham chiếu tĩnh không phải là một lựa chọn nào cả. Trước tiên, bạn không biết có bao nhiêu trong số các hoạt động này kết thúc trong ngăn xếp. Nếu bạn thực sự cần phải làm điều đó, hãy chắc chắn để dọn dẹp sau khi bạn vào onDestroy.
tynn

Bạn chỉ có 1 hoạt động thực hiện trình phát thống nhất, đối với những thứ khác (ví dụ: dịch vụ, hoạt động khác), bạn luôn có thể sử dụng chương trình phát sóng. Đây là giải pháp rất đơn giản và cổ điển
Nikolay Gonza

xin lỗi vì đã trả lời trễ @NikolayGonza, nhưng với mã của bạn, hoạt động là Null :(
Lotan
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.