iosEnablePush.js 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. /*
  2. * Author: Derek Chia <snipking@gmail.com>
  3. * Cordova plugin after hook to enable `Push Notification` capability for XCode 8
  4. */
  5. const fs = require('fs');
  6. const path = require('path');
  7. let commonFuncs = require('./common');
  8. /**
  9. * add APNS env to cordova project Entitlements-Debug.plist and Entitlements-Release.plist
  10. * This two file will work when xcode archive app
  11. */
  12. let enablePushNotificationForCI = (basePath, xcodeprojName) => {
  13. commonFuncs.addAPNSinEntitlements(basePath + xcodeprojName + '/Entitlements-Debug.plist', false);
  14. commonFuncs.addAPNSinEntitlements(basePath + xcodeprojName + '/Entitlements-Release.plist', true);
  15. }
  16. /**
  17. * add APNS env to entitlement file; enable Push Notification capability in .pbxproj file
  18. * This two file will work when xcode archive app
  19. */
  20. let enablePushNotificationForXCode = (entitlementsPath, pbxprojPath, cordovaBuildConfig) => {
  21. console.log('will enable push notification capability for XCode');
  22. let needAddEntitlementToPbxproj = false;
  23. /**
  24. * add APNS env to entitlement file
  25. * without this file will cause a worning in xcode
  26. */
  27. if( fs.existsSync(entitlementsPath) ) {
  28. commonFuncs.addAPNSinEntitlements(entitlementsPath, false);
  29. } else {
  30. // copy default entitlements file
  31. fs.readFile(__dirname + '/apns.entitlements', 'utf8', function(err, data) {
  32. if (err) {
  33. throw err;
  34. }
  35. fs.writeFileSync(entitlementsPath, data);
  36. console.log(entitlementsPath + " written successfully");
  37. });
  38. needAddEntitlementToPbxproj = true;
  39. }
  40. /**
  41. * enable Push Notification capability in .pbxproj file
  42. * equally enable "Push Notification" switch in xcode
  43. */
  44. fs.readFile(pbxprojPath, "utf8", function(err, data) {
  45. if (err) {
  46. throw err;
  47. }
  48. console.log("Reading pbxproj file asynchronously");
  49. // add Push Notification Capability
  50. let re1 = new RegExp('isa = PBXProject;(.|[\r\n])*TargetAttributes', 'g');
  51. let re1rep = new RegExp('isa = PBXProject;(.|[\r\n])*attributes = {', 'g');
  52. let re2 = new RegExp('(?:isa = PBXProject;(.|[\r\n])*TargetAttributes(.|[\r\n])*)SystemCapabilities', 'g');
  53. let re2rep = new RegExp('isa = PBXProject;(.|[\r\n])*TargetAttributes = {', 'g');
  54. let re3 = new RegExp('(?:isa = PBXProject;(.|[\r\n])*TargetAttributes(.|[\r\n])*SystemCapabilities(.|[\r\n])*)com\.apple\.Push', 'g');
  55. let re3rep = new RegExp('isa = PBXProject;(.|[\r\n])*TargetAttributes(.|[\r\n])*SystemCapabilities = {', 'g');
  56. let re4rep = new RegExp('isa = PBXProject;(.|[\r\n])*TargetAttributes(.|[\r\n])*SystemCapabilities(.|[\r\n])*com\.apple\.Push = {(.|[\r\n])*enabled = [01]');
  57. let matched = data.match(re1);
  58. let result;
  59. if (matched === null) {
  60. console.log('re1 not match, no TargetAttributes');
  61. result = data.replace(re1rep, 'isa = PBXProject;\n' +
  62. '\t\t\tattributes = {\n' +
  63. '\t\t\t\tTargetAttributes = {\n' +
  64. '\t\t\t\t\t1D6058900D05DD3D006BFB54 = {\n' +
  65. '\t\t\t\t\t\tDevelopmentTeam = ' + cordovaBuildConfig.ios.release.developmentTeam + ';\n' +
  66. '\t\t\t\t\t\tSystemCapabilities = {\n' +
  67. '\t\t\t\t\t\t\tcom.apple.Push = {\n' +
  68. '\t\t\t\t\t\t\t\tenabled = 1;\n' +
  69. '\t\t\t\t\t\t\t};\n' +
  70. '\t\t\t\t\t\t};\n' +
  71. '\t\t\t\t\t};\n' +
  72. '\t\t\t\t};');
  73. } else {
  74. matched = data.match(re2);
  75. if(matched === null) {
  76. console.log('re2 not match, nothing under TargetAttributes');
  77. let parts = re2rep.exec(data);
  78. result = data.replace(re2rep, parts[0] + '\n' + '\t\t\t\t\t1D6058900D05DD3D006BFB54 = {\n' +
  79. '\t\t\t\t\t\tDevelopmentTeam = ' + cordovaBuildConfig.ios.release.developmentTeam + ';\n' +
  80. '\t\t\t\t\t\tSystemCapabilities = {\n' +
  81. '\t\t\t\t\t\t\tcom.apple.Push = {\n' +
  82. '\t\t\t\t\t\t\t\tenabled = 1;\n' +
  83. '\t\t\t\t\t\t\t};\n' +
  84. '\t\t\t\t\t\t};\n' +
  85. '\t\t\t\t\t};');
  86. } else {
  87. matched = data.match(re3);
  88. if(matched === null) {
  89. console.log('re3 not match, no com.apple.Push defined');
  90. let parts = re3rep.exec(data);
  91. result = data.replace(re3rep, parts[0] + '\n' + '\t\t\t\t\t\t\tcom.apple.Push = {\n' +
  92. '\t\t\t\t\t\t\t\tenabled = 1;\n' +
  93. '\t\t\t\t\t\t\t};');
  94. } else {
  95. console.log('just enable com.apple.Push');
  96. let parts = re4rep.exec(data);
  97. result = data.replace(re4rep, parts[0].substr(0, parts[0].length - 1) + '1');
  98. }
  99. }
  100. }
  101. // add entitlements
  102. if (needAddEntitlementToPbxproj) {
  103. let pathArray = entitlementsPath.split("/");
  104. let entitlementsFileName = pathArray[pathArray.length - 1];
  105. let projectFolderName = pathArray[pathArray.length - 2];
  106. result = result.replace(new RegExp('\\/\\* Begin PBXFileReference section \\*\\/'), '/* Begin PBXFileReference section */\n' +
  107. '\t\tD7BB385F1E4DB54800345BF4 /* ' + entitlementsFileName + ' */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; name = "' + entitlementsFileName + '"; path = "' + projectFolderName + '/' + entitlementsFileName + '"; sourceTree = "<group>"; };');
  108. result = result.replace(new RegExp('\\/\\* CustomTemplate \\*\\/.*\n.*isa = PBXGroup;.*\n.*children = \\('), '/* CustomTemplate */ = {\n' +
  109. '\t\t\tisa = PBXGroup;\n' +
  110. '\t\t\tchildren = (\n' +
  111. '\t\t\t\tD7BB385F1E4DB54800345BF4 /* ' + entitlementsFileName + ' */,');
  112. let re5rep = new RegExp('\\/\\* Debug \\*\\/.*\n.*isa = XCBuildConfiguration;.*\n.*\n.*buildSettings = {');
  113. let parts = result.match(re5rep);
  114. result = result.replace(re5rep, parts + '\n\t\t\t\tCODE_SIGN_ENTITLEMENTS = "' + projectFolderName + '/' + entitlementsFileName + '";');
  115. let re6rep = new RegExp('\\/\\* Release \\*\\/.*\n.*isa = XCBuildConfiguration;.*\n.*\n.*buildSettings = {');
  116. parts = result.match(re6rep);
  117. result = result.replace(re6rep, parts + '\n\t\t\t\tCODE_SIGN_ENTITLEMENTS = "' + projectFolderName + '/' + entitlementsFileName + '";');
  118. }
  119. // write result to project.pbxproj
  120. fs.writeFile(pbxprojPath, result, {"encoding": 'utf8'}, function(err) {
  121. if (err) {
  122. throw err;
  123. }
  124. console.log(pbxprojPath + " written successfully");
  125. });
  126. });
  127. }
  128. module.exports = (context) => {
  129. let basePath = './platforms/ios/';
  130. let buildType = 'dev';
  131. let xcodeprojName = commonFuncs.getXcodeProjName(basePath);
  132. let pbxprojPath = basePath + xcodeprojName + '.xcodeproj/project.pbxproj';
  133. let entitlementsPath = basePath + xcodeprojName + '/' + xcodeprojName + '.entitlements';
  134. let cordovaBuildConfigPath = './build.json'
  135. let cordovaBuildConfig = null;
  136. let willEnablePushNotificationForXCode = true;
  137. try { // try to read ios developmentTeam from build.json
  138. cordovaBuildConfig = JSON.parse(fs.readFileSync(cordovaBuildConfigPath, "utf8"));
  139. if(cordovaBuildConfig.ios.release.developmentTeam === null && cordovaBuildConfig.ios.release.developmentTeam === undefined) {
  140. throw 'no valid developmentTeam found in build.json';
  141. }
  142. } catch(e) {
  143. console.log("Do not detected 'build.json' or ios.release.developmentTeam not avaliable in 'build.json' \n" +
  144. "Will not enable XCode Push Notification Capability. \n" +
  145. "Will only enable Push Notification for CI by add config to '" + basePath + xcodeprojName + "/Entitlements-Debug.plist' and '" + basePath + xcodeprojName + "/Entitlements-Release.plist' \n" +
  146. "Please add 'build.json' to cordova project root folder to make after hook fully functional. \n" +
  147. "Reference [1]https://cordova.apache.org/docs/en/latest/reference/cordova-cli/#cordova-build-command \n" +
  148. "Reference [2]https://cordova.apache.org/docs/en/latest/guide/platforms/ios/#signing-an-app");
  149. willEnablePushNotificationForXCode = false;
  150. }
  151. enablePushNotificationForCI(basePath, xcodeprojName);
  152. if(willEnablePushNotificationForXCode) {
  153. enablePushNotificationForXCode(entitlementsPath, pbxprojPath, cordovaBuildConfig);
  154. }
  155. }