Tristan Pct
Tristan Pct

Reputation: 614

Missing CFBundleShortVersionString when distribute Flutter app with ShareExtension

I have a Flutter application which use receive_sharing_intent package, and as requested by the plugin, I've created a Share Extension.

My app and the extension build and work correctly, but when I archive and distribute my app (App Store Connect), at the end of the uploading I have the following error messages:

ERROR ITMS-90057: "The bundle 'Payload/Runner.app/PlugIns/ShareExtension.appex' is missing plist key. The Info.plist is missing the required key: CFBundleShortVersionString."

ERROR ITMS-90056: "This bundle 'Payload/Runner.app/PlugIns/ShareExtension.appex' is invalid. The Info.plist is missing the required key: CFBundleVersion."

ERROR ITMS-90360: "Missing Info.plist value. A value for the key 'CFBundleVersion' in bundle Payload/Runner.app/PlugIns/ShareExtension.appex is required."

ERROR ITMS-90360: "Missing Info.plist value. A value for the key 'CFBundleShortVersionString' in bundle Payload/Runner.app/PlugIns/ShareExtension.appex is required."

But in my ios/ShareExtension/Info.plist file I have:

    <key>CFBundleShortVersionString</key>
    <string>$(FLUTTER_BUILD_NAME)</string>
    <key>CFBundleVersion</key>
    <string>$(FLUTTER_BUILD_NUMBER)</string>

I also tried with:

    <key>CFBundleShortVersionString</key>
    <string>$(MARKETING_VERSION)</string>
    <key>CFBundleVersion</key>
    <string>$(CURRENT_PROJECT_VERSION)</string>

which remove the error for CFBundleVersion but CFBundleShortVersionString is still invalid.

By explicitly setting my app version and build number in the extension plist the upload succeed.
But is there a way to use FLUTTER_BUILD_NAME and FLUTTER_BUILD_NUMBER variables in the extension plist?

NOTE:

I'm using Xcode 11.6

Upvotes: 4

Views: 1647

Answers (2)

Witoldio
Witoldio

Reputation: 951

I had the same problem when app version had no version code. With version like 1.0.0 ios app had missing plist key error. Try to add version code like 1.0.0+0

Upvotes: 0

Yaniv Shaked
Yaniv Shaked

Reputation: 758

Sharing my C program per @Aidan David request, but:

  • I don't think this is the correct solution, but only a workaround.
  • Use at your own risk :-)
  • Also adding the zsh script I'm using to inject the required plist values.

ZSH script:

./plist_replace_value ./NotificationService/Info.plist CFBundleVersion `grep ^version: ../pubspec.yaml | awk -F'[\+ ]' '{print $3}'`
./plist_replace_value ./NotificationService/Info.plist CFBundleShortVersionString `grep ^version: ../pubspec.yaml | awk -F'[\+ ]' '{print $2}'`
./plist_replace_value ./Share\ Extension/Info.plist CFBundleVersion `grep ^version: ../pubspec.yaml | awk -F'[\+ ]' '{print $3}'`
./plist_replace_value ./Share\ Extension/Info.plist CFBundleShortVersionString `grep ^version: ../pubspec.yaml | awk -F'[\+ ]' '{print $2}'`

C Program, plist_replace_value.c:

#include <string.h>
#include <stdio.h>

#define MAX_LINE 256

void print_usage(char *programName)
{
    printf("\nUsage:\n%s <plist file> <key> <value>\n", programName);
}

int main(int argc, char *argv[])
{
    FILE *plist_file, *output_file;
    int replaced = 0;
    char line[MAX_LINE];
    printf("Plist key-value parser. Supports replacing values.\n");
    fflush(stdout);
    if (argc < 4)
    {
        fprintf(stderr, "Insufficient number of parameters.");
        print_usage(argv[0]);
        return 1;
    }
    
    plist_file = fopen(argv[1], "r+");
    if (plist_file == NULL)
    {
        fprintf(stderr, "Unable to open %s, aborting...\n", argv[1]);
        return 1;
    }

    output_file = fopen("temp.plist", "w");
    if (output_file == NULL)
    {
        fprintf(stderr, "Unable to create temporary file, aborting...\n");
        return 1;
    }

    fgets(line, MAX_LINE, plist_file);
    while (!feof(plist_file) && !replaced)
    {
        fprintf(output_file, "%s", line);
        if (strstr(line, argv[2]) != NULL)
        {
            fprintf(output_file, "\t<string>%s</string>\n", argv[3]);
            // Skip the next output line
            fgets(line, MAX_LINE, plist_file);
        }
        fgets(line, MAX_LINE, plist_file);
    }

    fclose(output_file);
    fclose(plist_file);
    remove(argv[1]);
    rename("temp.plist", argv[1]);

    return 0;
}

Upvotes: 0

Related Questions