Intermodulation between ue and android
Both methods are performed on top of the Android project packaged by UE.
1. First, UE packages Android, check the following item
If there are multiple scenes, you need to add scenes
The project file is in this path
Then you can open it through Android Studio and select gradle to open
Run it first to see if you can publish to an Android device before proceeding.
2. Create a new MainActivity to start UE
MainActivity should inherit Activity. The test.android package name is the package name when UE releases android.
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
findViewById(R.id.button).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent = new Intent(MainActivity.this, GameActivity.class);
startActivity(intent);
}
});
}
}
Then start the Activity in the Manifest and cancel the automatically generated GameActivity as the started Activity.
<activity android:name="com.test.android.MainActivity"
>
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
There is only one button on this page, which is used to jump to UE.
<?xml version="1.0" encoding="utf-8"?>
<android.widget.RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.test.android.MainActivity">
<Button
android:id="@+id/button"
android:layout_width="177dp"
android:layout_height="155dp"
android:text="Button"
tools:layout_editor_absoluteX="172dp"
tools:layout_editor_absoluteY="351dp" />
</android.widget.RelativeLayout>
Then you can test it. The startup project should be to start your new Activity. Click the button to jump to the UE interface.
3. Click the button of the custom widget in UE to open the Android page. The two on the right are useless and should not be ignored.
1. This is our new c++ class
head File
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "Components/Button.h"
#include "CoreMinimal.h"
#include "Blueprint/UserWidget.h"
#include "DemoUserWidget.generated.h"
/**
*
*/
UCLASS()
class DEMOANDROID_API UDemoUserWidget : public UUserWidget
{
GENERATED_BODY()
protected:
virtual void NativeConstruct() override;
public:
UPROPERTY(meta = (BindWidget))
class UButton* ButtonUEJump;
UPROPERTY(meta = (BindWidget))
class UButton* ButtonHaerbin;
UPROPERTY(meta = (BindWidget))
class UButton* ButtonBeijing;
UFUNCTION()
void ButtonUEJumpClick();
UFUNCTION()
void ButtonHaerbinClick();
UFUNCTION()
void ButtonBeijingClick();
};
cpp file, ButtonHaerbinClick is the callback method when we click the widget button. toAndroidActivity is a java method defined in GameActivity, (Ljava/lang/String;) V. It should be noted that a semicolon must be added after the parameter. V means no return value. CallVoidMethod is to call a method with no return value in java, and str is the parameter to be passed.
void UDemoUserWidget::ButtonHaerbinClick()
{
GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, FString::Printf(TEXT("haerbin")));
#if PLATFORM_ANDROID
if (JNIEnv* Env = FAndroidApplication::GetJavaEnv())
{
bool bIsOptional = false;
static jmethodID toAndroidActivity = FJavaWrapper::FindMethod(Env, FJavaWrapper::GameActivityClassID, "toAndroidActivity", "(Ljava/lang/String;)V", bIsOptional);
char tt[30] = {"--------a--"};
jstring str = Env->NewStringUTF((const char*)tt);
FJavaWrapper::CallVoidMethod(Env, FJavaWrapper::GameActivityThis, toAndroidActivity, str);
UE_LOG(LogTemp, Warning, TEXT("jmethodID is vaild :AndroidThunkJava_GetMessage "));
}
#endif//PALTFORM_ANDROOT
}
2. To create a Widget in UE, you need to inherit the c++ code we wrote before.
The name of the button must be consistent with the name of the c++ header file, because we are using binding.
3. Create two new methods in Android's GameActivty to open the Android interface in the form of a dialog box.
public void toAndroidActivity(String placeName) {
runOnUiThread(new Runnable() {
@Override
public void run() {
showLimit(GameActivity.this);
}
});
}
public void showLimit(Context context) {
final Dialog baseDialog = new Dialog(context);
View view = LayoutInflater.from(context).inflate(R.layout.view_pop_custom, null);
TextView tv_next = view.findViewById(R.id.tv_next);
baseDialog.show();
baseDialog.setCanceledOnTouchOutside(false);
Window window = baseDialog.getWindow();
WindowManager.LayoutParams attributes = window.getAttributes();
attributes.width = 600;
window.setAttributes(attributes);
tv_next.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Log.debug("tv_next.setOnClickListener");
baseDialog.dismiss();
toNewUEPlace();
}
});
window.setContentView(view);
}
4. Click the button on the pop-up Android interface to switch the scene in ue
1. Define a method public native void toNewUEPlace() in the GameActivity class;
2. In DemoUserWidget.cpp in UE
#include "Kismet/GameplayStatics.h"
#if PLATFORM_ANDROID
#include "Runtime/Launch/Public/Android/AndroidJNI.h"
#include "Runtime/ApplicationCore/Public/Android/AndroidApplication.h"
#include "Android/AndroidJavaEnv.h"
#endif//PLATFORM_ANDROID
#if PLATFORM_ANDROID
JNI_METHOD void Java_com_epicgames_unreal_GameActivity_toNewUEPlace(JNIEnv* jenv, jobject thiz)
{
UE_LOG(LogTemp, Warning, TEXT("toNewUEPlace"));
UGameplayStatics::OpenLevel(GWorld, FName("/Game/Maps/abc"), true);
}
#endif//PLATFORM_ANDROID
abc is a map created by yourself