【问题标题】:HealthKit capabilities are not adding through unity c# scriptHealthKit 功能未通过统一 c# 脚本添加
【发布时间】:2021-03-07 12:53:18
【问题描述】:

谁能帮我解决一个统一应用程序的 healthKit 功能问题。 我正在尝试将 healthKit 功能添加到我的统一应用程序中。我正在使用 BEHEALTHKIT 和 HealthKitBuildProcessor.cs 编辑器类来添加功能和其他依赖项。以下是我正在使用的代码。但由于某种原因,healthkit 功能和权利没有通过此代码添加(权限参数正在添加到 plist),并且当我打印 Debug.Log("newEntitlements:" + newEntitlements); 时返回 null我的构建失败并出现错误提示“配置文件不支持 HealthKit 功能” 我已经为 developer.apple.com 的配置文件添加了 HealthKit 功能。 Unity版本:2019.4.4f1

public class HealthKitBuildProcessor : IProcessSceneWithReport
{
    private static string shareString = null;
    private static string updateString = null;
    private static string clinicalString = null;
    
    /*! @brief required by the IProcessScene interface. Set high to let other postprocess scripts run first. */
    public int callbackOrder {
        get { return 100; }
    }

    /*! @brief         Searches for HealthKitDataTypes objects & reads the usage strings for the OnPostprocessBuild phase. 
        @param scene   the scene being processed.
        @param report  a report containing information about the current build
     */
    public void OnProcessScene(Scene scene, BuildReport report) {
        GameObject[] rootObjects = scene.GetRootGameObjects();
        foreach (GameObject obj in rootObjects) {
            HealthKitDataTypes types = obj.GetComponentInChildren<HealthKitDataTypes>();
            if (types != null) {
                if (types.AskForSharePermission()) {
                    HealthKitBuildProcessor.shareString = types.healthShareUsageDescription;
                }

                if (types.AskForUpdatePermission()) {
                    HealthKitBuildProcessor.updateString = types.healthUpdateUsageDescription;
                }

                /*if (types.AskForClinicalPermission()) {
                    HealthKitBuildProcessor.clinicalString = types.clinicalUsageDescription;
                }*/
            }
        }
    }

    /*! @brief              Updates the Xcode project. 
        @param buildTarget  the target build platform
        @param path         the path of the target build
     */
    [PostProcessBuildAttribute(10)]
    public static void OnPostprocessBuild(BuildTarget buildTarget, string path) {
        Debug.Log("--- BEHEALTHKIT POST-PROCESS BUILD ---");
        if (buildTarget == BuildTarget.iOS) {
            //string projPath = path + "/Unity-iPhone.xcodeproj/project.pbxproj";
            //Debug.Log("BE:PROJECT PATH :" + projPath);
            var projPath = PBXProject.GetPBXProjectPath(path);
            var proj = new PBXProject();
            proj.ReadFromString(System.IO.File.ReadAllText(projPath));


#if UNITY_2019_3_OR_NEWER
            string mainTarget = proj.GetUnityMainTargetGuid();
            string frameworkTarget = proj.GetUnityFrameworkTargetGuid();
            Debug.Log("--- BE: UNITY_2019_3_OR_NEWER ---");
            Debug.LogFormat("main target: {0}", mainTarget);
            Debug.LogFormat("framework target: {0}", frameworkTarget);
#else
            string targetName = PBXProject.GetUnityTargetName();
            string mainTarget = proj.TargetGuidByName(targetName);
            Debug.Log("---BE: ELSE  UNITY_2019_3_OR_NEWER ---");
            Debug.Log("main target: {0}", mainTarget);
            Debug.Log("targetName: ", targetName);
#endif
            bool addHealthRecordsCapability = (clinicalString != null);
            //Debug.Log("addHealthRecordsCapability: ", addHealthRecordsCapability);

            // Info.plist
            //-----------
            Debug.Log("---BE: PLIST ---");
            var info = ProcessInfoPList(path, addHealthRecordsCapability);


            // Entitlements
            //--------------
            Debug.Log("---BE: ProcessEntitlements ---");
            string entitlementsRelative = ProcessEntitlements(path, proj, mainTarget, info, addHealthRecordsCapability);

#if UNITY_2019_3_OR_NEWER
            // add HealthKit capability 
            Debug.Log("------projPath "+projPath);  
            ProjectCapabilityManager capabilities = new ProjectCapabilityManager(projPath, "Entitlements.entitlements", null, mainTarget);
            capabilities.AddHealthKit();
            Debug.Log("---BE:Capability UNITY_2019_3_OR_NEWER ---");            
            // add HealthKit Framework
            //proj.AddFrameworkToProject(frameworkTarget, "HealthKit.framework", true);

            // Set a custom link flag
            //proj.AddBuildProperty(frameworkTarget, "OTHER_LDFLAGS", "-ObjC");
#else
            // add HealthKit capability
            Debug.Log("---ELSE BE:Capability UNITY_2019_3_OR_NEWER ---");
            Debug.Log("projectPath:" + projPath);
            Debug.Log("entitlementsRelative:" + entitlementsRelative);
            Debug.Log("targetName:" + targetName);
            ProjectCapabilityManager capabilities = new ProjectCapabilityManager(projPath, entitlementsRelative, targetName);
            capabilities.AddHealthKit();
            
            // add HealthKit Framework
            proj.AddFrameworkToProject(mainTarget, "HealthKit.framework", true);

            // Set a custom link flag
            proj.AddBuildProperty(mainTarget, "OTHER_LDFLAGS", "-ObjC");
#endif
            proj.WriteToFile(projPath);
        }
    }

    // -------------------------------

    internal static PlistDocument ProcessInfoPList(string path, bool addHealthRecordsCapability) {
        string plistPath = Path.Combine(path, "Info.plist");
        PlistDocument info = GetInfoPlist(plistPath);
        PlistElementDict rootDict = info.root;
        // // Add the keys
        if (HealthKitBuildProcessor.shareString != null) {
            rootDict.SetString("NSHealthShareUsageDescription", HealthKitBuildProcessor.shareString);
        }
        else {
            Debug.LogError("unable to read NSHealthShareUsageDescription");
        }
        if (HealthKitBuildProcessor.updateString != null) {
            rootDict.SetString("NSHealthUpdateUsageDescription", HealthKitBuildProcessor.updateString);
        }
        if (addHealthRecordsCapability) {
            rootDict.SetString("NSHealthClinicalHealthRecordsShareUsageDescription", HealthKitBuildProcessor.clinicalString);
        }

        // Write the file
        info.WriteToFile(plistPath);

        return info;
    }

    internal static string ProcessEntitlements(string path, PBXProject proj, string target, PlistDocument info, bool addHealthRecordsCapability) {
        string entitlementsFile;

        string entitlementsRelative;
        string entitlementsPath;
        Debug.Log("PATH: " + path);
        Debug.Log("TARGET: " + target);
        String test= proj.GetUnityMainTargetGuid();
        Debug.Log("TEST proj: " + test);
        entitlementsRelative = proj.GetBuildPropertyForConfig(target, "CODE_SIGN_ENTITLEMENTS");
        Debug.Log("entitlementsRelative: " + entitlementsRelative);
        Debug.LogFormat("get build property [{0}, {1} = {2}]", target, "CODE_SIGN_ENTITLEMENTS", entitlementsRelative);
        PlistDocument entitlements = new PlistDocument();

        if (entitlementsRelative == null) {
            string projectname = GetProjectName(info);
            Debug.Log("projectname: " + projectname);
            entitlementsFile = Path.ChangeExtension("Entitlements", "entitlements");
            Debug.Log("entitlementsFile: " + entitlementsFile);
            entitlementsRelative = Path.Combine(path, entitlementsFile);
            Debug.Log("entitlementsRelative: " + entitlementsRelative);
            entitlementsPath = Path.Combine(path, entitlementsRelative);
            Debug.Log("entitlementsPath: " + entitlementsPath);
            //proj.AddFileToBuild(target, proj.AddFile(entitlementsRelative, entitlementsRelative, PBXSourceTree.Source));

            Debug.LogFormat("add build property [{0}, {1}] => {2}", target, "CODE_SIGN_ENTITLEMENTS", entitlementsRelative);
            proj.AddBuildProperty(target, "CODE_SIGN_ENTITLEMENTS", entitlementsFile);
            string newEntitlements = proj.GetBuildPropertyForConfig(target, "CODE_SIGN_ENTITLEMENTS");
            Debug.Log("newEntitlements: " + newEntitlements);
            Debug.LogFormat("=> {0}", newEntitlements);

        }
        else {
            entitlementsPath = Path.Combine(path, entitlementsRelative);
            Debug.Log("ELSE:entitlementsPath " + entitlementsPath);
        }

        ReadEntitlements(entitlements, entitlementsPath);
        entitlements.root.SetBoolean("com.apple.developer.healthkit", true);
        if (addHealthRecordsCapability) {
            Debug.Log("addHealthRecordsCapability =TRUE ");
            var healthkitAccess = entitlements.root.CreateArray("com.apple.developer.healthkit.access");
            healthkitAccess.AddString("health-records");
        }
        SaveEntitlements(entitlements, entitlementsPath);

        return entitlementsRelative;
    }

    // -------------------------------

    internal static void ReadEntitlements(PlistDocument entitlements, string destinationPath) {
        Debug.Log("READING Entitlements [ReadEntitlements]");
        Debug.Log("READING from destinationPath [ReadEntitlements]"+ destinationPath);
        if (System.IO.File.Exists(destinationPath)) {
            try {
                Debug.LogFormat("reading existing entitlements: '{0}'.", destinationPath);
                entitlements.ReadFromFile(destinationPath);
            }
            catch (Exception e) {
                Debug.LogErrorFormat("error reading from file: {0}", e);
            }
        }
    }
    
    internal static void SaveEntitlements(PlistDocument entitlements, string destinationPath) {
        try {
            Debug.Log("----SaveEntitlements---");
            entitlements.WriteToFile(destinationPath);
        }
        catch (Exception e) {
            Debug.LogErrorFormat("error writing to file: {0}", e);
        }
    }

    internal static PlistDocument GetInfoPlist(string plistPath) {
        // Get the plist file
        PlistDocument plist = new PlistDocument();
        plist.ReadFromFile(plistPath);
        return plist;
    }
    
    internal static string GetProjectName(PlistDocument plist) {
        string projectname = plist.root["CFBundleDisplayName"].AsString();
        return projectname;
    }
}

【问题讨论】:

    标签: c# ios unity3d healthkit


    【解决方案1】:

    我不了解 Unity,但是在 Xcode 中,当您为健康套件添加功能时,它会自行更新权利文件

    【讨论】:

    • 是的,但是我的项目配置方式是通过脚本添加功能。我已经在以同样的方式使用 Apple 登录并且正在工作。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-03-25
    • 1970-01-01
    • 2021-05-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多