Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Allow adding tags to AndroidManifest.xml from project.xml. #1814

Open
wants to merge 9 commits into
base: 8.3.0-Dev
Choose a base branch
from
218 changes: 121 additions & 97 deletions src/lime/tools/ConfigData.hx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,12 @@ import haxe.xml.Fast as Access;

abstract ConfigData(Dynamic) to Dynamic from Dynamic
{
private static inline var ARRAY:String = "___array";
private static inline var ARRAY:String = "config:array_";

/**
If set, `parse()` will add child nodes to this array instead of parsing them.
**/
@:noCompletion public var xmlChildren(get, set):Array<String>;

public function new()
{
Expand Down Expand Up @@ -75,7 +80,7 @@ abstract ConfigData(Dynamic) to Dynamic from Dynamic

if (current != null)
{
array = Reflect.field(current, field + ARRAY);
array = Reflect.field(current, ARRAY + field);

if (array == null && Reflect.hasField(current, field))
{
Expand Down Expand Up @@ -170,7 +175,7 @@ abstract ConfigData(Dynamic) to Dynamic from Dynamic
return defaultValue;
}

public function getKeyValueArray(id:String, defaultValues:Dynamic = null):Array<{ key:Dynamic, value:Dynamic }>
public function getKeyValueArray(id:String, defaultValues:Dynamic = null):Array<{ key:String, value:Dynamic }>
{
var values = {};
if (defaultValues != null)
Expand All @@ -181,7 +186,7 @@ abstract ConfigData(Dynamic) to Dynamic from Dynamic
var data = get(id);
for (key in Reflect.fields(data))
{
if (!StringTools.endsWith (key, ARRAY))
if (!StringTools.startsWith(key, "config:"))
{
Reflect.setField(values, key, Reflect.field(data, key));
}
Expand Down Expand Up @@ -216,72 +221,63 @@ abstract ConfigData(Dynamic) to Dynamic from Dynamic
{
for (field in Reflect.fields(source))
{
if (StringTools.endsWith(field, ARRAY))
if (StringTools.startsWith(field, ARRAY))
{
continue;
}

var doCopy = true;
var exists = Reflect.hasField(destination, field);
var typeDest = null;
var valueSource = Reflect.field(source, field);
var valueDest = Reflect.field(destination, field);
var typeSource = Type.typeof(valueSource).getName();
var typeDest = Type.typeof(valueDest).getName();

if (exists)
// if trying to copy a non object over an object, don't
if (typeSource != "TObject" && typeDest == "TObject")
{
var valueSource = Reflect.field(source, field);
var valueDest = Reflect.field(destination, field);
var typeSource = Type.typeof(valueSource).getName();
typeDest = Type.typeof(valueDest).getName();
continue;
}

// if trying to copy a non object over an object, don't
if (typeSource != "TObject" && typeDest == "TObject")
if (valueSource != valueDest && valueDest != null && typeSource != "TObject" && !#if (haxe_ver >= 4.2) Std.isOfType #else Std.is #end(valueSource, Array))
{
if (!Reflect.hasField(destination, ARRAY + field))
{
doCopy = false;

// if (Log.verbose) {
//
// Log.println (field + " not merged by preference");
//
// }
Reflect.setField(destination, ARRAY + field, [ObjectTools.deepCopy(Reflect.field(destination, field))]);
}

if (doCopy && Reflect.field(source, field) != Reflect.field(destination, field) && typeSource != "TObject")
{
if (!Reflect.hasField(destination, field + ARRAY))
{
Reflect.setField(destination, field + ARRAY, [ObjectTools.deepCopy(Reflect.field(destination, field))]);
}

var array:Array<Dynamic> = Reflect.field(destination, field + ARRAY);

if (Reflect.hasField(source, field + ARRAY))
{
array = array.concat(Reflect.field(source, field + ARRAY));
Reflect.setField(destination, field + ARRAY, array);
}
else
{
array.push(Reflect.field(source, field));
}
var array:Array<Dynamic> = Reflect.field(destination, ARRAY + field);

Reflect.setField(destination, field, Reflect.field(source, field));
doCopy = false;
if (Reflect.hasField(source, ARRAY + field))
{
array = array.concat(Reflect.field(source, ARRAY + field));
Reflect.setField(destination, ARRAY + field, array);
}
else
{
array.push(Reflect.field(source, field));
}

Reflect.setField(destination, field, Reflect.field(source, field));
continue;
}

if (doCopy)
if (typeDest == "TObject")
{
mergeValues(valueSource, valueDest);
}
else if (typeDest == "TClass" && #if (haxe_ver >= 4.2) Std.isOfType #else Std.is #end (valueSource, Array) && #if (haxe_ver >= 4.2) Std.isOfType #else Std.is #end(valueDest, Array))
{
if (typeDest == "TObject")
for (item in (cast valueSource:Array<Dynamic>))
{
mergeValues(Reflect.field(source, field), Reflect.field(destination, field));
(cast valueDest:Array<Dynamic>).push(item);
}
else
{
Reflect.setField(destination, field, Reflect.field(source, field));
}
else
{
Reflect.setField(destination, field, Reflect.field(source, field));

if (Reflect.hasField(source, field + ARRAY))
{
Reflect.setField(destination, field + ARRAY, Reflect.field(source, field + ARRAY));
}
if (Reflect.hasField(source, ARRAY + field))
{
Reflect.setField(destination, ARRAY + field, Reflect.field(source, ARRAY + field));
}
}
}
Expand All @@ -302,6 +298,10 @@ abstract ConfigData(Dynamic) to Dynamic from Dynamic
{
bucketType = elem.att.type;
}
else if (elem.x.exists("config:type"))
{
bucketType = elem.x.get("config:type");
}

if (bucketType != "")
{
Expand All @@ -318,7 +318,7 @@ abstract ConfigData(Dynamic) to Dynamic from Dynamic
{
for (attrName in elem.x.attributes())
{
if (attrName != "type")
if (attrName != "type" && attrName != "config:type")
{
var attrValue = elem.x.get(attrName);
if (substitute != null) attrValue = substitute(attrValue);
Expand All @@ -327,64 +327,77 @@ abstract ConfigData(Dynamic) to Dynamic from Dynamic
}
}

private function parseChildren(elem:Access, bucket:Dynamic, depth:Int = 0, substitute:String->String = null):Void
private function parseChildren(elem:Access, bucket:ConfigData, depth:Int = 0, substitute:String->String = null):Void
{
if (bucket.xmlChildren != null)
{
var children:Array<String> = bucket.xmlChildren;
for (child in elem.elements)
{
children.push(child.x.toString());
}

return;
}

for (child in elem.elements)
{
if (child.name != "config")
if (child.name == "config")
{
// log("config data > child : " + child.name);
continue;
}

var d = depth + 1;
// log("config data > child : " + child.name);

var hasChildren = child.x.elements().hasNext();
var hasAttributes = child.x.attributes().hasNext();
var d = depth + 1;

if (Reflect.hasField(bucket, child.name))
{
var array:Array<Dynamic> = Reflect.field(bucket, child.name + ARRAY);
if (array == null)
{
array = [ObjectTools.deepCopy(Reflect.field(bucket, child.name))];
Reflect.setField(bucket, child.name + ARRAY, array);
}
var hasChildren = child.x.elements().hasNext();
var hasAttributes = child.x.attributes().hasNext();

var arrayBucket = {};
array.push(arrayBucket);
if (Reflect.hasField(bucket, child.name))
{
var array:Array<Dynamic> = Reflect.field(bucket, ARRAY + child.name);
if (array == null)
{
array = [ObjectTools.deepCopy(Reflect.field(bucket, child.name))];
Reflect.setField(bucket, ARRAY + child.name, array);
}

if (hasAttributes)
{
parseAttributes(child, arrayBucket, substitute);
}
var arrayBucket = {};
array.push(arrayBucket);

if (hasChildren)
{
parseChildren(child, arrayBucket, d, substitute);
}
if (hasAttributes)
{
parseAttributes(child, arrayBucket, substitute);
}

if (!hasChildren && !hasAttributes)
{
parseValue(child, arrayBucket, substitute);
}
if (hasChildren)
{
parseChildren(child, arrayBucket, d, substitute);
}

if (!hasChildren && !hasAttributes)
{
parseValue(child, bucket, substitute);
parseValue(child, arrayBucket, substitute);
}
else
{
var childBucket = addBucket(child.name, bucket);
}

if (hasAttributes)
{
parseAttributes(child, childBucket, substitute);
}
if (!hasChildren && !hasAttributes)
{
parseValue(child, bucket, substitute);
}
else
{
var childBucket = addBucket(child.name, bucket);

if (hasChildren)
{
parseChildren(child, childBucket, d, substitute);
}
if (hasAttributes)
{
parseAttributes(child, childBucket, substitute);
}

if (hasChildren)
{
parseChildren(child, childBucket, d, substitute);
}
}
}
Expand Down Expand Up @@ -426,12 +439,12 @@ abstract ConfigData(Dynamic) to Dynamic from Dynamic

if (Reflect.hasField(current, field))
{
var array:Array<Dynamic> = Reflect.field(current, field + ARRAY);
var array:Array<Dynamic> = Reflect.field(current, ARRAY + field);

if (array == null)
{
array = [ObjectTools.deepCopy(Reflect.field(current, field))];
Reflect.setField(current, field + ARRAY, array);
Reflect.setField(current, ARRAY + field, array);
}

if (!unique || array.indexOf(value) == -1)
Expand Down Expand Up @@ -495,11 +508,11 @@ abstract ConfigData(Dynamic) to Dynamic from Dynamic
{
if (typeSource != "TObject")
{
var array:Array<Dynamic> = Reflect.field(bucket, node + ARRAY);
var array:Array<Dynamic> = Reflect.field(bucket, ARRAY + node);
if (array == null)
{
array = [ObjectTools.deepCopy(Reflect.field(bucket, node))];
Reflect.setField(bucket, node + ARRAY, array);
Reflect.setField(bucket, ARRAY + node, array);
}

array.push(value);
Expand All @@ -513,4 +526,15 @@ abstract ConfigData(Dynamic) to Dynamic from Dynamic
Reflect.setField(bucket, node, value);
}
}

// Getters & Setters

private inline function get_xmlChildren():Array<String> {
return Reflect.field(this, "config:xml_children");
}

private inline function set_xmlChildren(value:Array<String>):Array<String> {
Reflect.setField(this, "config:xml_children", value);
return value;
}
}
5 changes: 5 additions & 0 deletions src/lime/tools/HXProject.hx
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,11 @@ class HXProject extends Script
splashScreens = new Array<SplashScreen>();
targetHandlers = new Map<String, String>();

config.set("android", { manifest:{}, application:{}, activity:{} });
config.get("android.manifest").xmlChildren = [];
config.get("android.application").xmlChildren = [];
config.get("android.activity").xmlChildren = [];

initializeDefines();
}

Expand Down
9 changes: 8 additions & 1 deletion templates/android/template/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="::APP_BUILD_NUMBER::" android:versionName="::APP_VERSION::" android:installLocation="::ANDROID_INSTALL_LOCATION::">
<manifest xmlns:android="http://schemas.android.com/apk/res/android" ::foreach ANDROID_MANIFEST::::if ((value != null) && (value != ""))::::key::="::value::" ::end::::end::>

<uses-feature android:glEsVersion="0x00020000" android:required="true" />
<uses-feature android:name="android.hardware.touchscreen" android:required="false" />

::foreach ANDROID_PERMISSIONS::<uses-permission android:name="::__current__::" />
::end::
::foreach ANDROID_MANIFEST_CHILDREN::::__current__::
::end::

<application ::foreach ANDROID_APPLICATION::::if ((value != null) && (value != ""))::::key::="::value::" ::end::::end::>

Expand All @@ -14,6 +16,8 @@
::elseif (WIN_ORIENTATION=="landscape")::
<meta-data android:name="SDL_ENV.SDL_IOS_ORIENTATIONS" android:value="LandscapeLeft LandscapeRight" />
::end::
::foreach ANDROID_APPLICATION_CHILDREN::::__current__::
::end::

<activity ::foreach ANDROID_ACTIVITY::::if ((value != null) && (value != ""))::::key::="::value::" ::end::::end::>

Expand All @@ -35,6 +39,9 @@
</intent-filter>
::end::

::foreach ANDROID_ACTIVITY_CHILDREN::::__current__::
::end::

</activity>

</application>
Expand Down
Loading
Loading