UE4連結Android並呼叫解壓縮zip的介面
參考的前輩大佬們的文章
正文
建立一個新的UE4外掛/模組
- 建立外掛:在專案中點選Plugin並建立一個新的空白外掛,這個不再追誰
- 建立模組:如果你想把這個功能合併到某個外掛,可以選擇建立模組,建立新的模組檔案、.build.cs、與模組名稱相同的.h與.cpp檔案放置在目標外掛或專案的source檔案下,最簡單的方法是直接複製一個空白外掛的模組,並更改名稱類名等統一。
注意,模組需要在uplugin或uproject檔案中註冊,我將其填寫 為runtiome型別,載入時間為預設。
新增xml檔案
- 建立xml檔案並放置在build檔案目錄的同級位置,並將名稱改為xxx_UPL,所有複製檔案連結java類庫的操作都在這個xml中實現,我的建議是在複製一份引擎外掛AndroidCamera中的xml檔案,其中已經實現好了各種標籤。
2.在build.cs中註冊該檔案,載入launch模組,並新增同路徑下的UPL檔案
新增JAVA程式碼
- 因為我們這個功能很簡單,不需要link庫,所以只用到了 gameActivityImportAdditions與gameActivityClassAdditions這兩個標籤,前者用於引入包含檔案,後者用來新增函式。
- 我新增了兩個函式,一個用於Java呼叫C++,一個用於C++呼叫Java子執行緒進行解壓縮並回撥,這裡我遇到了一些問題,我看到某教程的課程名顯示Java可以呼叫C++的類成員函式,我並沒有找到方法(教程好貴捨不得花錢),我這裡只是呼叫了類外函式,並且暫時是準備用一個單例接受回撥實現功能了。
<!-- imports -->
<gameActivityImportAdditions>
<insert>
import java.io.*;
import java.util.ArrayList;
import android.os.AsyncTask;
import java.util.Collection;
import java.util.Enumeration;
import java.util.zip.ZipEntry;
import java.util.zip.ZipException;
import java.util.zip.ZipFile;
import java.util.zip.ZipOutputStream;
import java.util.zip.ZipInputStream;
</insert>
</gameActivityImportAdditions>
<!-- Action -->
<gameActivityClassAdditions>
<insert>
<!-- 01 -->
<!-- Java Jni Call C++ Native-->
public native void unZipCallBack(boolean value);
<!-- 02-->
/**
* 解壓操作 ****** ******
*
* @param zipFileString 被解壓的檔案路徑 sdcard/0/a/b/test.zip
* @param outPathString 解壓的目的路徑 sdcard/0/a/b
*/
public void AsyncUnZipFolder(String zipFileString,String outPathString) {
// 子執行緒執行
final String fzipFileString = zipFileString;
final String foutPathString = outPathString;
Thread otherThread = new Thread(new Runnable() {
@Override
public void run()
{
FileInputStream fis = null;
ZipInputStream inZip = null;
boolean res = true;
try {
fis = new FileInputStream (fzipFileString);
inZip = new ZipInputStream (fis);
ZipEntry zipEntry; //zip實體
String szName = "";
while ((zipEntry = inZip.getNextEntry()) != null) {
szName = zipEntry.getName();
if (zipEntry.isDirectory()) {
szName = szName.substring(0, szName.length() - 1);
File folder = new File(foutPathString + File.separator + szName);
folder.mkdirs();
} else {
File file = new File(foutPathString + File.separator + szName);
file.createNewFile();
FileOutputStream out = new FileOutputStream(file);
int length;
byte[] buffer = new byte[1024];
while ((length = inZip.read(buffer)) != -1) {
out.write(buffer, 0, length);
out.flush();
}
if (out != null) {
out.close();
}
}
}
}
catch (FileNotFoundException e)
{
res = false;
e.printStackTrace();
}
catch (IOException e) {
res = false;
e.printStackTrace();
}
catch (Exception e)
{
res = false;
e.printStackTrace();
}
finally {
if (fis != null) {
try
{
fis.close();
}
catch (IOException e)
{
res = false;
e.printStackTrace();
}
}
if (inZip != null) {
try
{
inZip.close();
}
catch (IOException e)
{
res = false;
e.printStackTrace();
}
}
final boolean fres = res;
runOnUiThread(new Runnable() {
@Override
public void run() {
//呼叫上面宣告的函式進行回撥
unZipCallBack(fres);
}
});
}
}
});
otherThread.start();
}
</insert>
</gameActivityClassAdditions>
新增C++呼叫和實現
這裡示例用了BlueprintFuncition,實際應該需要一個物件或單例物件來接受回撥。
- h檔案
#include "Kismet/BlueprintAsyncActionBase.h"
//呼叫用到的JNI標頭檔案
#if PLATFORM_ANDROID
#include "Android/AndroidJNI.h"
#include "Android/AndroidJava.h"
#include "Android/AndroidApplication.h"
#endif
#include "MyBlueprintFunctionLibrary.generated.h"
UCLASS()
class ANDROIDZIP_API UMyBlueprintFunctionLibrary : public UBlueprintFunctionLibrary
{
GENERATED_BODY()
UFUNCTION(BlueprintCallable, Category = Compress)
static void AsyncUnZip(FString targetPath, FString zipFilePath);
};
- 對Java的呼叫,因為我所呼叫的函式傳入兩個String變數且無返回值,所以拼寫函式標籤為(Ljava/lang/String;Ljava/lang/String;)V,具體可以參考連結的文章或者百度搜尋JNI函式簽名表。
void UMyBlueprintFunctionLibrary::AsyncUnZip(FString targetPath, FString zipFilePath)
{
#if PLATFORM_ANDROID
if (JNIEnv* Env = FAndroidApplication::GetJavaEnv())
{
jstring jsTargetPath = Env->NewStringUTF(TCHAR_TO_UTF8(*targetPath));
jstring jsZipFilePath = Env->NewStringUTF(TCHAR_TO_UTF8(*zipFilePath));
static jmethodID AsyncUnZipFolder = FJavaWrapper::FindMethod(Env, FJavaWrapper::GameActivityClassID, "AsyncUnZipFolder", "(Ljava/lang/String;Ljava/lang/String;)V", false);
FJavaWrapper::CallVoidMethod(Env, FJavaWrapper::GameActivityThis, AsyncUnZipFolder, jsZipFilePath, jsTargetPath);
}
#endif
}
- native函式的實現
#if PLATFORM_ANDROID
extern "C"
void Java_com_epicgames_ue4_GameActivity_unZipCallBack(JNIEnv * LocalJNIEnv, jobject LocalThiz, jboolean value)
{
bool b = value;
GEngine->AddOnScreenDebugMessage(-1, 90.f, FColor::Green, FString::Printf(TEXT("JavaCallBack")));
}
#endif
後續
- 目前來說是會使用一個subsystem接受回撥,之後看情況學習更改
- 個人感覺合理的設計應該是將其封裝為一個繼承UBlueprintAsyncActionBase的函式節點,在執行到節點時候建立一個臨時物件,接受回撥,呼叫委託後銷燬自己。
相關文章
- zip解壓縮
- Android總結之Gzip/Zip壓縮Android
- 壓縮解壓命令(tar, zip)
- zip壓縮和解壓縮
- Android程式解壓縮zip檔案,並載入顯示解壓後的檔案內容Android
- 利用Java實現zip壓縮/解壓縮 (轉)Java
- 簡單的zip壓縮和解壓縮
- CentOS中zip壓縮和unzip解壓縮命令詳解CentOS
- Ashampoo ZIP Pro 4,解壓縮
- ZipArchive解壓縮zip檔案Hive
- Linux下zip壓縮和unzip解壓縮命令全解Linux
- php 建立壓縮包zip,並將指定檔案放入zip中PHP
- Android 下載Zip檔案,並解壓到本地Android
- CentOS7中zip壓縮和unzip解壓縮命令詳解CentOS
- zip壓縮檔案處理方案(Zip4j壓縮和解壓)
- vue-前端匯出 pdf 並且壓縮 zipVue前端
- JAVA基礎:利用Java實現zip壓縮解壓縮(轉)Java
- Java使用Zip壓縮Java
- 使用jar與zip壓縮解壓檔案的區別JAR
- Linux科研武器庫 - 檔案壓縮與解壓縮 - zip / unzipLinux
- tar的打包-壓縮與解壓縮,並解壓到指定的目錄
- Laravel 中建立 Zip 壓縮檔案並提供下載Laravel
- 批處理 壓縮zip 並過濾部分檔案
- WinZip Pro 9 for Mac 專業zip壓縮解壓工具Mac
- The Unarchiver - Unzip RAR ZIP Mac - mac解壓縮工具HiveMac
- 使用org.apache.tools.zip實現zip壓縮和解壓Apache
- node ~ zip壓縮 && 檔案加密加密
- Java zip解壓,並遍歷zip中的配置檔案 .cfg或.propertiesJava
- p7zip 解壓超過 4G壓縮包
- rar壓縮解壓工具:RAR Extractor - ZIP Unarchiver中文啟用版Hive
- Java實現檔案壓縮與解壓[zip格式,gzip格式]Java
- ZIP壓縮演算法詳細分析及解壓例項解釋演算法
- Windows的壓縮資料夾(zip/cab)Windows
- java解壓rar,解壓zipJava
- Golang 學習筆記(五)- archive/zip 實現壓縮及解壓Golang筆記Hive
- ZIP壓縮演算法原理分析及解壓例項程式碼演算法
- java 把檔案壓縮成 zipJava
- java 生成 zip格式 壓縮檔案Java