Base Android implementation
This commit is contained in:
+62
-3
@@ -113,7 +113,10 @@ class Project extends HXProject
|
||||
*/
|
||||
static final ANDROID_TARGET_SDK_VERSION:Int = 35;
|
||||
|
||||
static final ANDROID_EXTENSIONS:Array<String> = ["funkin.extensions.CallbackUtil"];
|
||||
static final ANDROID_EXTENSIONS:Array<String> = [
|
||||
"funkin.extensions.CallbackUtil",
|
||||
"funkin.extensions.FNFCExtension"
|
||||
];
|
||||
|
||||
/**
|
||||
* The team ID to use for the iOS app. Configured in XCode.
|
||||
@@ -1088,6 +1091,7 @@ class Project extends HXProject
|
||||
}
|
||||
}
|
||||
|
||||
// Custom android.application XML Children for the AndroidManifest
|
||||
final modsFolderProvider:Xml = Xml.createElement('provider');
|
||||
modsFolderProvider.set('android:authorities', '$PACKAGE_NAME.docprovider');
|
||||
modsFolderProvider.set('android:name', 'funkin.provider.DataFolderProvider');
|
||||
@@ -1107,14 +1111,69 @@ class Project extends HXProject
|
||||
{
|
||||
if (config.get('android.application').xmlChildren != null)
|
||||
{
|
||||
config.get('android.application').xmlChildren.push(Printer.print(modsFolderProvider));
|
||||
config.get('android.application').xmlChildren.push(Printer.print(modsFolderProvider, true));
|
||||
}
|
||||
else
|
||||
{
|
||||
config.get('android.application').xmlChildren = [Printer.print(modsFolderProvider)];
|
||||
config.get('android.application').xmlChildren = [Printer.print(modsFolderProvider, true)];
|
||||
}
|
||||
}
|
||||
|
||||
// Custom android.activity XML Children for the AndroidManifest
|
||||
final intentFilter:Xml = Xml.createElement('intent-filter');
|
||||
|
||||
final action:Xml = Xml.createElement('action');
|
||||
action.set('android:name', 'android.intent.action.VIEW');
|
||||
intentFilter.addChild(action);
|
||||
|
||||
final intentFilterCategories:Array<String> = [
|
||||
"android.intent.category.DEFAULT",
|
||||
"android.intent.category.BROWSABLE"
|
||||
];
|
||||
|
||||
for (categoryName in intentFilterCategories)
|
||||
{
|
||||
final category:Xml = Xml.createElement('category');
|
||||
category.set('android:name', categoryName);
|
||||
intentFilter.addChild(category);
|
||||
}
|
||||
|
||||
final intentFilterDatas:Map<String, Array<String>> = [
|
||||
"android:mimeType" => ["application/zip"],
|
||||
// When this is added, it makes the game show up only when it's a FNFC file.
|
||||
// But it also for some reason make it not show up at all in ZArchiver no matter what the file is...
|
||||
// "android:host" => ["*"],
|
||||
"android:scheme" => ["file", "content"],
|
||||
// I think having all these makes it so the extension check would work even when the files has dots like "epic-song-v2.0.fnfc"
|
||||
"android:pathPattern" => [
|
||||
".*\\.fnfc", ".*\\..*\\.fnfc",
|
||||
".*\\..*\\..*\\.fnfc",
|
||||
".*\\..*\\..*\\..*\\.fnfc",
|
||||
".*\\..*\\..*\\..*\\..*\\.fnfc"
|
||||
]
|
||||
];
|
||||
|
||||
for (key => values in intentFilterDatas) {
|
||||
for (value in values) {
|
||||
final data:Xml = Xml.createElement("data");
|
||||
data.set(key, value);
|
||||
intentFilter.addChild(data);
|
||||
}
|
||||
}
|
||||
|
||||
@:nullSafety(Off)
|
||||
{
|
||||
if (config.get('android.activity').xmlChildren != null)
|
||||
{
|
||||
config.get('android.activity').xmlChildren.push(Printer.print(intentFilter, true));
|
||||
}
|
||||
else
|
||||
{
|
||||
config.get('android.activity').xmlChildren = [Printer.print(intentFilter, true)];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
final extensions:Null<Array<String>> = config.getArrayString('android.extension');
|
||||
|
||||
for (extension in ANDROID_EXTENSIONS)
|
||||
|
||||
+21
@@ -30,6 +30,13 @@ class CallbackUtil
|
||||
*/
|
||||
public static var onActivityResult:FlxTypedSignal<Int->Int->Void> = new FlxTypedSignal<Int->Int->Void>();
|
||||
|
||||
/**
|
||||
* Signal triggered when the user opens a FNFC file with the game in runtime.
|
||||
*
|
||||
* First argument is the FNFC file path.
|
||||
*/
|
||||
public static var onOpenFNFC:FlxTypedSignal<String->Void> = new FlxTypedSignal<String->Void>();
|
||||
|
||||
/**
|
||||
* Initializes the callback utility.
|
||||
*/
|
||||
@@ -66,5 +73,19 @@ class CallbackHandler #if (lime >= "8.0.0") implements JNISafety #end
|
||||
{
|
||||
if (CallbackUtil.onActivityResult != null) CallbackUtil.onActivityResult.dispatch(requestCode, resultCode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the onOpenFNFC callback from native code.
|
||||
*
|
||||
* @param file Path to the FNFC file that was opened.
|
||||
*/
|
||||
@:keep
|
||||
#if (lime >= "8.0.0")
|
||||
@:runOnMainThread
|
||||
#end
|
||||
public function onOpenFNFC(file:String):Void
|
||||
{
|
||||
if (CallbackUtil.onOpenFNFC != null) CallbackUtil.onOpenFNFC.dispatch(file);
|
||||
}
|
||||
}
|
||||
#end
|
||||
|
||||
@@ -25,10 +25,22 @@ public class CallbackUtil extends Extension
|
||||
CallbackUtil.haxeObject = haxeObject;
|
||||
}
|
||||
|
||||
public static void callMethod(String methodName, Object[] args)
|
||||
{
|
||||
if (haxeObject != null)
|
||||
haxeObject.call(methodName, args);
|
||||
}
|
||||
|
||||
public static void callMethodVoid(String methodName)
|
||||
{
|
||||
if (haxeObject != null)
|
||||
haxeObject.call0(methodName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onActivityResult(int requestCode, int resultCode, Intent data)
|
||||
{
|
||||
if (haxeObject != null)
|
||||
if (haxeObject != null)
|
||||
haxeObject.call2("onActivityResult", requestCode, resultCode);
|
||||
|
||||
return true;
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
package funkin.extensions;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
|
||||
import funkin.extensions.CallbackUtil;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.net.URI;
|
||||
|
||||
import org.haxe.extension.Extension;
|
||||
|
||||
import org.haxe.lime.HaxeObject;
|
||||
|
||||
public class FNFCExtension extends Extension
|
||||
{
|
||||
public static String launchedFile = null;
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
Intent intent = mainActivity.getIntent();
|
||||
if (intent != null && intent.getData() != null) {
|
||||
handleIntent(intent, false);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNewIntent(Intent intent) {
|
||||
super.onNewIntent(intent);
|
||||
|
||||
if (intent != null && intent.getData() != null) {
|
||||
handleIntent(mainActivity.getIntent(), true);
|
||||
}
|
||||
}
|
||||
|
||||
public static String queryLaunchedFNFC()
|
||||
{
|
||||
return launchedFile;
|
||||
}
|
||||
|
||||
|
||||
private static void handleIntent(Intent intent, boolean doCallback)
|
||||
{
|
||||
if (Intent.ACTION_VIEW.equals(intent.getAction())) {
|
||||
Uri uri = intent.getData();
|
||||
if (uri != null) {
|
||||
File output = new File(mainContext.getCacheDir(), new File("fnfc", uri.getPath()).getName());
|
||||
|
||||
try {
|
||||
InputStream in = mainContext.getContentResolver().openInputStream(uri);
|
||||
OutputStream out = new FileOutputStream(output);
|
||||
byte[] buffer = new byte[8192];
|
||||
int len;
|
||||
while ((len = in.read(buffer)) > 0) {
|
||||
out.write(buffer, 0, len);
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
Log.e("Exception", e.getMessage());
|
||||
}
|
||||
|
||||
launchedFile = output.getAbsolutePath();
|
||||
|
||||
if (doCallback)
|
||||
{
|
||||
Object[] args = new Object[1];
|
||||
args[0] = launchedFile;
|
||||
CallbackUtil.callMethod("onOpenFNFC", args);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user