一、说明
首先要明确,无论是越狱真机调试还是越狱 ipa 打包,都是需要进行代码签名的,唯一的区别是使用苹果签发的证书或者自签名证书进行代码签名。
可配置 Xcode 支持无证书编译,但是如果不签名,就算是越狱机器也会提示:无法安装此App,因为无法验证其完整性。
- 真机调试流程:
- 用 Xcode 进行无证书编译;
- 编译完成,用自签名证书进行代码签名;
- Xcode 连接越狱真机调试;
- 越狱 ipa 打包(企业签)流程:
- 用 Xcode 进行无证书编译;
- 编译完成,用自签名证书对
.xcarchive
进行代码签名; - 把
.xcarchive
打包成ipa
文件;
二、准备
- 越狱成功的苹果手机或者iPad等设备;
- 越狱设备必须安装
AppSync
插件,该插件绕过 iOS 系统的签名验证,使自签名 app 可以正常运行; - 使用
钥匙串访问
创建自签名证书; - 环境:macOS14.6.1 + Xcode16.2
三、Xcode 无证书编译
1. Xcode 配置
修改以下配置文件,版本不同路径有区别。使用 Xcode 修改,注意权限问题。
vi /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS18.2.sdk/SDKSettings.plist
DefaultProperties.ENTITLEMENTS_REQUIRED = NO
DefaultProperties.CODE_SIGNING_REQUIRED = NO
vi /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Info.plist
DefaultProperties.CODE_SIGN_CONTEXT_CLASS = XCCodeSignContext
2. Xcode 工程编译设置
选主 TARGERT 点击 Build Settings
,点左上“+”号:Add User-Defined Setting
CODE_SIGNING_ALLOWED = NO
可在自动编译 C# 源码添加:
proj.AddBuildProperty("Unity-iPhone", "CODE_SIGNING_ALLOWED", "NO");
四、越狱真机调试
1. Xcdoe 设置
主 TARGERT 添加 Build Phases/Run Script
,给 app 和 framework 进行签名:
if [ "${CODE_SIGNING_ALLOWED}" == "NO" ]; then
cd "${PROJECT_DIR}/../iOSBuild"
sh XcodeSigning.sh "${PRODUCT_BUNDLE_IDENTIFIER}" "${PROVISIONING_PROFILE}" "${BUILT_PRODUCTS_DIR}/${WRAPPER_NAME}/"
sh XcodeSigning.sh "${PRODUCT_BUNDLE_IDENTIFIER}" "${PROVISIONING_PROFILE}" "${BUILT_PRODUCTS_DIR}/${WRAPPER_NAME}/Frameworks/UnityFramework.framework/"
fi
可在自动编译 C# 源码添加:
proj.AddShellScriptBuildPhase("Unity-iPhone", "Run Script", "", "<同以上脚本>");
XcodeSigning.sh
脚本贴在最后。
2. 调试
连上越狱真机,即可正常编译调试。
五、越狱 ipa 打包
1. 编译
先编译出 .xcarchive
包;
2. 打包
使用脚本进行打包,BuildIPA.sh
脚本贴在最后。
sh BuildIPA.sh <path_to>.xcarchive/Products/Applications/<your_app>.app/
3. 重签
脚本支持重签,可改成从 .mobileprovision
文件中读取生成 entitlements.plist
文件:
/usr/libexec/PlistBuddy -x -c "print:Entitlements" /dev/stdin <<< $(security cms -D -i "${PROVISION}") > entitlements.plist
六、附:脚本
XcodeSigning.sh
#!/bin/bash
APP_ID="$1"
APP_CERT="$2"
APP_TARGET="$3"
TEAM_ID="$4"
if [ "$TEAM_ID" == "" ]; then
TEAM_ID="team"
fi
if [ "$APP_ID" == "" ] || [ "$APP_CERT" == "" ] || [ "$APP_TARGET" == "" ] || [ "$TEAM_ID" == "" ]; then
echo "Usage: $(basename $0) APP_ID APP_CERT APP_TARGET [TEAM_ID]"
echo " $(basename $0) "'"${PRODUCT_BUNDLE_IDENTIFIER}" "${PROVISIONING_PROFILE}" "${BUILT_PRODUCTS_DIR}/${WRAPPER_NAME}/"'
exit 1
fi
echo "Gen entitlements plist file..."
ENT_PLIST="$(mktemp)"
cat > $ENT_PLIST <<EOF
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>application-identifier</key>
<string>${TEAM_ID}.${APP_ID}</string>
<key>aps-environment</key>
<string>production</string>
<key>com.apple.developer.associated-domains</key>
<string>*</string>
<key>com.apple.developer.team-identifier</key>
<string>${TEAM_ID}</string>
<key>com.apple.security.application-groups</key>
<array>
<string>group.${APP_ID}.appshortcallid</string>
<string>group.${APP_ID}.appcallid</string>
</array>
<key>get-task-allow</key>
<true/>
<key>keychain-access-groups</key>
<array>
<string>${TEAM_ID}.*</string>
<string>com.apple.token</string>
</array>
</dict>
</plist>
EOF
echo "Code signing..."
set -x
codesign -f -s "$APP_CERT" --entitlements $ENT_PLIST "${APP_TARGET}" || exit $?
BuildIPA.sh
#!/bin/bash
APP_ID="com.team.app"
APP_CERT="test"
TEAM_ID="team"
if [ "$1" == "" ]; then
echo "Usage: $(basename $0) <path_to>.xcarchive/Products/Applications/<your_app>.app/"
exit 1
fi
APP_PATH=${1/.app\//.app}
APP_NAME=$(basename "$APP_PATH")
APP_NAME="${APP_NAME%.*}"
APP_TARGET="Payload/${APP_NAME}.app"
echo "App name: ${APP_NAME}"
echo "Copy app files..."
rm -rf Payload || exit $?
mkdir -p Payload || exit $?
rsync -a "$APP_PATH" Payload || exit $?
# signing
sh XcodeSigning.sh "$APP_ID" "$APP_CERT" "$APP_TARGET" "$TEAM_ID" || exit $?
sh XcodeSigning.sh "$APP_ID" "$APP_CERT" "$APP_TARGET/Frameworks/UnityFramework.framework" "$TEAM_ID" || exit $?
echo "Packaging..."
zip -rq "${APP_NAME}.ipa" Payload || exit $?
echo "Done: ${APP_NAME}.ipa"