简体   繁体   English

将我的 android 活动与主要的 unity3D 活动分开运行

[英]Run my android activity separate to the main unity3D activity

I am working on an an app for a client and extending the unity player activity to help me do some android specific tasks.我正在为客户开发一个应用程序并扩展统一播放器活动以帮助我完成一些 android 特定任务。

I do this so I can capture results from a startActivityForResult call, and so I can return from my activities back to Unity.我这样做是为了捕获startActivityForResult调用的结果,这样我就可以从我的活动返回到 Unity。

What I would like some advice on is how I can change this so it's not mixed in with my extended Unity player activity, but it is it's own activity that still captures the results and return the user back to the main Unity activity when finished.我想要一些建议的是我如何改变它,这样它就不会与我的扩展 Unity 播放器活动混合,但它是它自己的活动仍然捕获结果并在完成后将用户返回到主 Unity 活动。

I am hoping to not have to hide unity and instead have a new activity on the activity stack.我希望不必隐藏统一性,而是在活动堆栈上有一个新活动。 I'm just unsure how I should go about it or if I have the thought process correct (please correct me if I am wrong)我只是不确定我应该怎么做 go 或者我的思考过程是否正确(如果我错了请纠正我)

This is my code that currently works but minimises Unity while it does my task:这是我目前可以运行的代码,但在执行我的任务时将 Unity 最小化:

public class MyActivity extends UnityPlayerActivity
{
    private static final String MyTag = "######";
    private static final int INSTALL_CODE = 100;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.i(MyTag, "onCreate() -------------------------");
    }
 
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        Log.i(MyTag, "onActivityResult() -------------------------"  + requestCode + " --- " + resultCode);
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode == INSTALL_CODE)
        {
            // installed!
            if (resultCode == -1)
                UnityPlayer.UnitySendMessage("Canvas_CloudDeploy", "AndroidAPKInstallCallback", "true");
            else
                UnityPlayer.UnitySendMessage("Canvas_CloudDeploy", "AndroidAPKInstallCallback", "false");
        }
    }
 
    @Override protected void onStop()
    {
        Log.i(MyTag, "onStop() -------------------------");
        super.onStop();
    }
 
    // Quit Unity
    @Override protected void onDestroy ()
    {
        Log.i(MyTag, "onDestroy() -------------------------");
        super.onDestroy();
    }
 
    // Pause Unity
    @Override protected void onPause()
    {
        Log.i(MyTag, "onPause() -------------------------");
        super.onPause();
    }
 
    // Resume Unity
    @Override protected void onResume()
    {
        Log.i(MyTag, "onResume() -------------------------");
        super.onResume();
    }
}

Unity calling code:统一调用代码:

using AndroidJavaClass unityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
using AndroidJavaObject currentActivity = unityPlayer.GetStatic<AndroidJavaObject>("currentActivity");
using AndroidJavaObject unityContext = currentActivity.Call<AndroidJavaObject>("getApplicationContext");

string packageName = unityContext.Call<string>("getPackageName");
string authority = packageName + ".provider";

AndroidJavaClass intentClass = new AndroidJavaClass ("android.content.Intent");
string ACTION_VIEW = intentClass.GetStatic<string>("ACTION_VIEW");
AndroidJavaObject intentObject = new AndroidJavaObject("android.content.Intent", ACTION_VIEW);

int FLAG_GRANT_READ_URI_PERMISSION = intentClass.GetStatic<int>("FLAG_GRANT_READ_URI_PERMISSION");
int FLAG_GRANT_WRITE_URI_PERMISSION = intentClass.GetStatic<int>("FLAG_GRANT_WRITE_URI_PERMISSION");
string EXTRA_RETURN_RESULT = intentClass.GetStatic<string>("EXTRA_RETURN_RESULT");
int FLAG_ACTIVITY_CLEAR_TASK = intentClass.GetStatic<int>("FLAG_ACTIVITY_CLEAR_TASK");

using AndroidJavaObject fileObj = new AndroidJavaObject("java.io.File", apkPath);
using AndroidJavaClass fileProvider = new AndroidJavaClass("androidx.core.content.FileProvider");

object[] providerParams = new object[3];
providerParams[0] = unityContext;
providerParams[1] = authority;
providerParams[2] = fileObj;

using AndroidJavaObject uri = fileProvider.CallStatic<AndroidJavaObject>("getUriForFile", providerParams);

intentObject.Call<AndroidJavaObject>("setDataAndType", uri, "application/vnd.android.package-archive");
intentObject.Call<AndroidJavaObject>("addFlags", FLAG_ACTIVITY_CLEAR_TASK );
intentObject.Call<AndroidJavaObject>("addFlags", FLAG_GRANT_READ_URI_PERMISSION | FLAG_GRANT_WRITE_URI_PERMISSION);
intentObject.Call<AndroidJavaObject>("putExtra", EXTRA_RETURN_RESULT, true);
currentActivity.Call("startActivityForResult", intentObject, 100);

My android Manifest:我的 android 清单:

<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.unity3d.player" xmlns:tools="http://schemas.android.com/tools">
  <application android:requestLegacyExternalStorage="true">
    <activity android:name="net.****.****.MyActivity" android:theme="@style/UnityThemeSelector" android:screenOrientation="landscape" android:launchMode="singleTask" android:configChanges="mcc|mnc|locale|touchscreen|keyboard|keyboardHidden|navigation|orientation|screenLayout|uiMode|screenSize|smallestScreenSize|fontScale|layoutDirection|density" android:hardwareAccelerated="true">
      <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
      </intent-filter>
    </activity>
    <meta-data android:name="unity.splash-mode" android:value="0" />
    <meta-data android:name="unity.splash-enable" android:value="True" />
  </application>
  <uses-feature android:glEsVersion="0x00030000" />
  <uses-feature android:name="android.hardware.vulkan.version" android:required="false" />
  <uses-feature android:name="android.hardware.touchscreen" android:required="false" />
  <uses-feature android:name="android.hardware.touchscreen.multitouch" android:required="false" />
  <uses-feature android:name="android.hardware.touchscreen.multitouch.distinct" android:required="false" />
  <uses-permission android:name="android.permission.WRITE_SETTINGS" />
  <uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
  <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
  <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
  <uses-permission android:name="android.permission.REQUEST_DELETE_PACKAGES" />
  <uses-permission android:name="android.permission.WRITE_INTERNAL_STORAGE" />
  <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
</manifest>

To summarise my questions are:总结一下我的问题是:

  • When my activities run, because of how I call them in Unity, Unity is always stopped, then resumed.当我的活动运行时,由于我在 Unity 中调用它们的方式,Unity 总是停止,然后恢复。 Can it simply be a new android activity running over the top of the Unity activity?它可以只是一个新的 android 活动在 Unity 活动之上运行吗?
  • If so, what's the right way to do it.如果是这样,那么正确的方法是什么。 I believe I need to call my activity from the extended unity class above, and pass in the unity context to it, so it knows how to get back once finished.我相信我需要从上面的扩展统一 class 调用我的活动,并将统一上下文传递给它,所以它知道如何在完成后返回。 But - I am a unsure.但是-我不确定。 Lots of half examples to try and piece together.很多半个例子可以尝试拼凑起来。
  • I need my activity to call back into the main unity activity once finished.我需要我的活动在完成后回调到主要的统一活动中。 It will need to send back the activity result and then resume the unity activity.它将需要发回活动结果,然后恢复统一活动。 I am doing this above, but want this in that separate activity class.我在上面这样做,但希望在单独的活动 class 中这样做。
  • If I use FLAG_ACTIVITY_NEW_TASK I almost get the behaviour I like (Shows android activity on top of mine), but you cant use that flag when requesting an activity result and it wont work as desired.如果我使用FLAG_ACTIVITY_NEW_TASK我几乎得到我喜欢的行为(在我的顶部显示 android 活动), 但是在请求活动结果时你不能使用该标志并且它不会按预期工作。

Based on the above information, try using FLAG_ACTIVITY_NEW_DOCUMENT which starts an activity as the new root of an existing task, allowing the user to navigate back to the previous task when it finishes.根据以上信息,尝试使用FLAG_ACTIVITY_NEW_DOCUMENT启动一个活动作为现有任务的新根,允许用户在完成时导航回上一个任务。 Unlike FLAG_ACTIVITY_NEW_TASK , it doesn't clear the existing task.FLAG_ACTIVITY_NEW_TASK不同,它不会清除现有任务。

Be sure to note that this flag should only be used when the activity is the primary entry point of a task (which it is in your case) and doesn't have any entry point ancestors in the task's stack.请务必注意,仅当活动是任务的主要入口点(在您的情况下)并且任务堆栈中没有任何入口点祖先时,才应使用此标志。

using AndroidJavaClass unityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
using AndroidJavaObject currentActivity = unityPlayer.GetStatic<AndroidJavaObject>("currentActivity");
using AndroidJavaObject unityContext = currentActivity.Call<AndroidJavaObject>("getApplicationContext");

string packageName = unityContext.Call<string>("getPackageName");
string authority = packageName + ".provider";

AndroidJavaClass intentClass = new AndroidJavaClass ("android.content.Intent");
string ACTION_VIEW = intentClass.GetStatic<string>("ACTION_VIEW");
AndroidJavaObject intentObject = new AndroidJavaObject("android.content.Intent", ACTION_VIEW);

int FLAG_GRANT_READ_URI_PERMISSION = intentClass.GetStatic<int>("FLAG_GRANT_READ_URI_PERMISSION");
int FLAG_GRANT_WRITE_URI_PERMISSION = intentClass.GetStatic<int>("FLAG_GRANT_WRITE_URI_PERMISSION");
int FLAG_ACTIVITY_NEW_DOCUMENT = intentClass.GetStatic<int>("FLAG_ACTIVITY_NEW_DOCUMENT");

using AndroidJavaObject fileObj = new AndroidJavaObject("java.io.File", apkPath);
using AndroidJavaClass fileProvider = new AndroidJavaClass("androidx.core.content.FileProvider");

object[] providerParams = new object[3];
providerParams[0] = unityContext;
providerParams[1] = authority;
providerParams[2] = fileObj;

using AndroidJavaObject uri = fileProvider.CallStatic<AndroidJavaObject>("getUriForFile", providerParams);

intentObject.Call<AndroidJavaObject>("setDataAndType", uri, "application/vnd.android.package-archive");
intentObject.Call<AndroidJavaObject>("addFlags", FLAG_ACTIVITY_NEW_DOCUMENT );
intentObject.Call<AndroidJavaObject>("addFlags", FLAG_GRANT_READ_URI_PERMISSION | FLAG_GRANT_WRITE_URI_PERMISSION);
currentActivity.Call("startActivityForResult", intentObject, INSTALL_CODE);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM