通过Cordova config.xml向iOS .plist文件添加条目

85

我是 Cordova CLI 的新手。

我需要通过 Cordova 来以编程方式执行以下步骤:

  1. 在项目的 .plist 文件中添加一行新的内容;
  2. 在新行中输入以下值:
  3. Key: GDLibraryMode Type:String (default) Value:GDEnterpriseSimulation

我认为我需要在我的项目根目录下的 config.xml 文件中进行操作(或者也有可能是“platforms”文件夹中的文件)。

有人能向我解释如何通过 config.xml 添加条目,以便在编译时添加上述条目吗?

我正在使用 Cordova 3.3.1-0.42 版本(我知道这不是最新版本)。我已经建好了我的项目,一切正常,我只需要将此条目添加到 pList 中即可。


编辑时间:2/8/21
根据此问题下的一条评论:

对于那些较晚看到这个问题的人来说,通过 Cordova CLI 版本 7 或更高版本 来设置项目 plist 的值是被支持的。


4
对于任何来晚了的人,现在Cordova CLI 7及以上版本支持在项目plist中设置值。参考链接 - decates
14个回答

68

我认为你不能直接通过修改 config.xml 来完成这个任务。至少在文档中我没有看到相关说明:http://cordova.apache.org/docs/en/3.3.0/config_ref_index.md.html

我认为你需要创建一个插件,因为它们可以插入 plist 条目:http://docs.phonegap.com/en/3.3.0/plugin_ref_spec.md.html#Plugin%20Specification

请参考“config-file”元素部分。以下是 plugin.xml 中相关部分的猜测:

<platform name="ios">
<config-file target="*-Info.plist" parent="CFBundleURLTypes">
<array>
    <dict>
        <key>GDLibraryMode</key>
        <string>GDEnterpriseSimulation</string>
    </dict>
</array>
</config-file>
</platform>

然后您可以安装插件:cordova plugin add <您的插件名称或文件位置>


1
@mooreds 抱歉,我误解了你的答案...我以为你的解决方案是使用 gap: config-file。现在,我理解了你的方法(创建一个专门的插件来修改特定的plist),我会尝试一下。谢谢! - Fafaman
6
@mooreds,Cordova/PhoneGap文档存在误导。我发现关键字应该在“parent”中指定,而值部分应该是内部XML。 在这种特定情况下,应该按如下方式进行配置:<config-file target="*-Info.plist" parent="GDLibraryMode"> <string>GDEnterpriseSimulation</string> </config-file> - Herman Kan
4
这个插件很好用。https://github.com/leecrossley/cordova-plugin-transport-security - rjhilgefort
1
感谢 @rjhilgefort,这样就容易多了! :) - josebailo
3
供参考,从Cordova CLI 7+版本开始,可以通过在config.xml中使用<config-file>元素来完成此操作-有关如何执行此操作的详细信息,请参阅其他答案。 - decates
显示剩余5条评论

45

我非常喜欢@james的解决方案,使用Cordova钩子。然而,有两个问题。 文档表明:

  • “我们强烈建议使用Node.js编写您的钩子”
  • /hooks目录已被认为是不推荐使用的,可以使用config.xml中的hook元素”

以下是使用plist NPM包的Node.js实现:

var fs    = require('fs');     // nodejs.org/api/fs.html
var plist = require('plist');  // www.npmjs.com/package/plist

var FILEPATH = 'platforms/ios/.../...-Info.plist';

module.exports = function (context) {

    var xml = fs.readFileSync(FILEPATH, 'utf8');
    var obj = plist.parse(xml);

    obj.GDLibraryMode = 'GDEnterpriseSimulation';

    xml = plist.build(obj);
    fs.writeFileSync(FILEPATH, xml, { encoding: 'utf8' });

};

在 Cordova 提供的所有钩子类型中,与您的情况相关的是:

  • after_prepare
  • before_compile

选择一个钩子类型,然后将其添加到您的 config.xml 文件中:

<platform name="ios">
    <hook type="after_prepare" src="scripts/my-hook.js" />
</platform>

节点plist库在解析我的plist文件时出现了一些问题,因此我无法使用这个解决方案,转而采用了James的解决方案,它使用了Mac上包含的PListBuddy可执行文件。如果plist库更加可靠,那么这将是一个好的解决方案。我按照您的建议从config.xml文件中引用了我的脚本。 - stephen.hanson
不错!无需使用任何额外的插件,而且运行得非常好!所有其他解决方案似乎都过时了或者对于这样一个简单的问题来说过于复杂。 - Arno van Oordt
plist npm 模块存在严重问题。当源文件包含空值时,它会生成无效的 .plist 文件。请改用 simple-plist。 - cleong
我在使用cordova@8时添加本地插件遇到了很多麻烦,这个解决方案在我的情况下更好并且更简单。 - jbgt

32
你可以在Cordova hook脚本中使用PlistBuddy实用程序来修改*-Info.plist文件。
例如,我有以下脚本位于<project-root>/hooks/after_prepare/010_modify_plist.sh下,它添加了一个字典属性并在该字典中添加了一个条目:
#!/bin/bash

PLIST=platforms/ios/*/*-Info.plist

cat << EOF |
Add :NSAppTransportSecurity dict
Add :NSAppTransportSecurity:NSAllowsArbitraryLoads bool YES
EOF
while read line
do
    /usr/libexec/PlistBuddy -c "$line" $PLIST
done

true

请确保将脚本设置为可执行(chmod +x)。
脚本末尾的true是因为如果要添加的键已经存在,PlistBuddy会返回一个错误退出代码,并且没有提供检测键是否已经存在的方法。如果钩子脚本以错误状态退出,Cordova将报告构建错误。更好的错误处理可能是可行的,但实现起来很麻烦。

它起作用了!我尝试了你和TachyonVortex的解决方案。TachyonVortex的解决方案使用的node.js库没有正确解析我的PList文件,而你答案中使用的Mac内置的PListBuddy却可以。不过,我确实像TachyonVortex建议的那样从config.xml引用了钩子。 - stephen.hanson
1
如果您想每次更新plist时都更新密钥,即使密钥已经存在,那么请在添加语句之前添加“Remove:NSAppTransportSecurity”,它将首先删除NSAppTransportSecurity,然后再添加它。这不应该导致任何崩溃。 - Samuel Thompson

25

这是我最终采取的步骤,使我的应用程序能够通过 itunes 在设备之间共享文件。

1.在您的应用程序中导航到 config.xml。在平台标签下,将此代码片段键入您的配置中 <platform name="ios">

 <config-file platform="ios" target="*-Info.plist" parent="UIFileSharingEnabled">
      <true/>
  </config-file>

2. 然后打开您的命令行工具并键入:cordova prepare

  1. 在设备上卸载并重新安装您的应用程序,您将看到您的应用程序出现在iTunes中,以便您在设备之间共享任何文件。

几件事情,请确保cordova已经更新,并且已经添加了iOS平台。

npm install -g cordova

这个命令安装 Cordova。

cordova platform add ios

这个命令会添加 iOS 平台。

当你运行 cordova prepare 命令时,实际上是使用苹果的 Xcode SDK 生成在 platform/ios 文件夹中的内容。你可以在这里看到为你的应用程序生成的 plist 文件,标签为 "yourApp-info.plist"。在那里,你可以看到 XML 布局中产生的新键和字符串,如下所示:

 <key>UIFileSharingEnabled</key>
 <true/>

还有一个警告,我的公司几周前向我交付了这个ionic框架应用程序(时间非常紧)。我所说的一切都是基于几周的学习。因此,这可能不是最佳实践,但我希望它能帮助到某些人。

编辑

文档链接


4
需要其他什么才能使这个工作?我正在使用 Cordova 6.2(最新版本),尽管我已经在 config.xml 文件中添加了条目,但我在 plist 中看不到它。你是否有安装 Cordova 自定义配置插件(https://github.com/dpa99c/cordova-custom-config)? - Tomer Cagan
1
运行得很顺利。谢谢。 - Logus Graphics
<config-file> 元素是在 Cordova CLI 版本 7 中添加的,因此使用最新版本的 Cordova CLI 即可正常工作(参见 此 github 问题以获取 cordova-custom-config 的作者提供的可重现证明)。 - decates
这对我有用!然而,在标签上指定平台作为属性似乎是多余的,特别是它已经放在了iOS平台下面。在我的设备上没有加那个也可以正常工作。 - Eric Ferreira

14

一些核心插件作者表示,现在使用config.xml是可行的。例如,在Cordova相机插件的文档中,他们讨论了iOS 10中提供plist中权限消息字符串的新要求。为了实现这一点,他们建议执行带参数的插件添加命令,如下所示:

cordova plugin add cordova-plugin-camera --variable CAMERA_USAGE_DESCRIPTION="My App would like to access your camera, to take photos of your documents."

这样做的结果不仅会向config.xml添加一个新的<plugin>,而且还会有一个<variable>子标记:

<plugin name="cordova-plugin-camera" spec="~2.3.0">
    <variable name="CAMERA_USAGE_DESCRIPTION" value="My App would like to access your camera, to take photos of your documents." />
</plugin>

那似乎与我的info.plist中的新键相关,或许在运行时传递值?

  <key>NSCameraUsageDescription</key>
  <string/>
  <key>NSPhotoLibraryUsageDescription</key>
  <string/>

如果我说我完全知道它是如何工作的,那我就是在撒谎,但它似乎指引着前方。


CAMERA_USAGE_DESCRIPTION会传递到NSCameraUsageDescription。如果您想为NSPhotoLibraryUsageDescription添加一个值,您还需要添加<variable name="PHOTOLIBRARY_USAGE_DESCRIPTION" value="whatever" /> - Nico Westerdale
1
如果您正在使用PhoneGap Build服务,则建议使用此方法来设置这些值。 - Nico Westerdale
我不得不在<key>NSCameraUsageDescription</key>下方添加一个<string>Random camera usage text</string>,以使我的构建获得接受。配置不会自动添加该文本。 - Slartibartfast

10

更新:针对想在iOS >= 10上使用相机的用户。

这意味着,通常情况下,您可以在插件中进行配置:

 <!-- ios -->
 <platform name="ios">

     <config-file target="*-Info.plist" parent="NSLocationWhenInUseUsageDescription">
         <string></string>
     </config-file>
     <config-file target="*-Info.plist" parent="NSCameraUsageDescription">
         <string></string>
     </config-file>
      <config-file target="*-Info.plist" parent="NSPhotoLibraryUsageDescription">
         <string></string>
     </config-file>

 </platform>

但是目前,你不能在插件中配置NSCameraUsageDescriptionNSPhotoLibraryUsageDescription。你需要在平台->iOS项目中通过Xcode或者*-Info.plist文件进行配置。

iOS 10及以上版本强制要求在info.plist中添加NSCameraUsageDescription和NSPhotoLibraryUsageDescription。

了解更多:https://www.npmjs.com/package/cordova-plugin-camera


10

我在ionic 3中使用以下内容,无需任何额外的插件或导入,我认为这可能对其他人有所帮助:

<platform name="ios">
    <edit-config file="*-Info.plist" mode="merge" target="NSLocationWhenInUseUsageDescription">
        <string>Location is required so we can show you your nearby projects to support.</string>
    </edit-config>
    <edit-config file="*-Info.plist" mode="merge" target="NSCameraUsageDescription">
        <string>Camera accesss required in order to let you select profile picture from camera.</string>
    </edit-config>
    <edit-config file="*-Info.plist" mode="merge" target="NSPhotoLibraryUsageDescription">
        <string>Photo library accesss required in order to let you select profile picture from gallery / library.</string>
    </edit-config>
</platform>

mode属性上,我使用了overwrite而不是merge,然后运行了cordova prepare ios来成功地将config.xml文件中的edit-config标签应用到了我的xCode项目的example-info.plist文件中。 - tyler.frankenstein

5
您可以通过直接编辑插件目录中的ios.json,在应用程序的plist中设置显示名称。
将以下内容添加到ios.json文件的config_munge.files部分即可完成操作,即使使用CLI,也会保持不变。
"*-Info.plist": {

    "parents": {
        "CFBundleDisplayName": [
            {
                "xml": "<string>RevMob Ads Cordova Plugin Demo</string>",
                "count": 1
            }
        ]
    }
}

这里有一个完整的示例:链接

1
请注意,当从Visual Studio Tools for Cordova运行时,这种方法不起作用,因为ios.json会被工具覆盖。 - Herman Kan
2
这个答案有两个问题。首先,当运行 cordova platform remove ios 然后是 cordova platform add ios 时,对 /plugins/ios.json 的任何手动编辑都将丢失。其次,@Red2678 要求“通过 Cordova 在编译时以编程方式执行编辑...以便在编译时添加新条目的解决方案”。 - TachyonVortex

4

可以的!

我正在使用Cordova 9.0.0 (cordova-lib@9.0.1)。

例如,这是我用来将新字符串值插入到Info.plist中的配置文件:

<platform name="ios">
    <edit-config file="*-Info.plist" mode="merge" target="NSMicrophoneUsageDescription">
        <string>My awesome app wish to hear your awesome voice through Microphone. Not for fancy stuff, just want to hear you.</string>
    </edit-config>
    <edit-config file="*-Info.plist" mode="merge" target="---Key configuration---">
        <string>---string value---</string>
    </edit-config>
</platform>

在此之后,不要忘记通过终端运行以下两个命令来重建您的分段文件:
cordova platform rm ios
cordova platform add ios

为了确认更改,您可以通过使用xCode打开新生成的.plist文件来检查。

-Info.plist文件位于:

./platform/ios/[your app name]/[your app name]-Info.plist

edit-config 假设目标已经存在于您的 plist 中。只是为了明确起见,如果您想添加新的键/字符串对,应该使用 config-file,它会将新的子项添加到 xml 树中。 - Daniel Lizik

3

@TachyonVortex的解决方案似乎是最好的选择,但在我的情况下崩溃了。问题是由一个空的NSMainNibFile字段引起的,这个字段没有被plist NPM包正确转换。在.plist文件中。

    <key>NSMainNibFile</key>
    <string></string>
    <key>NSMainNibFile~ipad</key>
    <string></string>

被转换为:

    <key>NSMainNibFile</key>
    <string>NSMainNibFile~ipad</string>

我在脚本中添加了以下内容来修复它:
    obj.NSMainNibFile = '';
    obj['NSMainNibFile~ipad'] = '';

脚本最终看起来像这样(scripts/my-hook.js):
var fs    = require('fs');     // nodejs.org/api/fs.html
var plist = require('plist');  // www.npmjs.com/package/plist

var FILEPATH = 'platforms/ios/***/***-Info.plist';

module.exports = function (context) {

    var xml = fs.readFileSync(FILEPATH, 'utf8');
    var obj = plist.parse(xml);

    obj.GDLibraryMode = 'GDEnterpriseSimulation';
    obj.NSMainNibFile = '';
    obj['NSMainNibFile~ipad'] = '';

    xml = plist.build(obj);
    fs.writeFileSync(FILEPATH, xml, { encoding: 'utf8' });

};

并且config.xml文件:

<platform name="ios">
    <hook type="before_build" src="scripts/my-hook.js" />
</platform>

我在hooks/after_platform_add目录下编写了一个名为patch_plist.js的文件,并添加了以下代码。但是我的plist文件中仍然出现了<key>NSMainNibFile</key><string>NSMainNibFile~ipad</string>。请问有什么解决办法吗? - Romain R.

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接