I recently started a Capacitor based Ionic project. After years of working with Cordova, the framework initally felt jarring. However, with even a bit of use, I'm already buying into Capacitor's benefits. The Cordova approach of generating Android and iOS projects often worked great, but at times the approach showed itself to be quite fragile. Something would change in the iOS world and you'd be at the mercy of Cordova to update the build process to catch up with this. Not so with Capacitor, which embraces the notion of working directly on Android and iOS native projects.
I do however miss a number of nicities that Cordova offered. Take versioning. It seems obvious that there would be a central location where your project's version number was set and the iOS and Android apps pulled from this. And yet, this isn't the case with Capacitor. The thought of having to launch two different IDE's to manually change the app's version number seems like a recipe for disaster.
Speaking of launching IDE's, the thought of giving up command line building and running of apps is another step backwards.
Fortunately, with a bit of shell scripting the versionining and building challenge for Android can be addressed. Building from the command line on iOS is possible but it will take a bit more research befor I get it figured out. I added this functionality to my ionicassist command line tool. It's now possible to say:
ionicassist android-cap ionicassist ios-cap
To push the version number found in capacitor.config.json to both Android and iOS and build and install the Android project from the command line. The source code for ionicassist is below. Most of the code is straightfoward, though dealing with the ridiculous Info.plist format took some work. xmlstarlet and jq both proved invaluable for this little project.
#!/bin/bash
##
## Scrip to help with ionic dev
##
action=$1 ; shift
case $(uname) in
Darwin)
PLATFORM_TOOLS=$HOME/Library/Android/sdk/platform-tools/
APK_DEST="$HOME/Google Drive (ben@ideas2executables.com)/Clients/Uchi/APKs/"
;;
CYGWIN_NT-10.0)
PLATFORM_TOOLS=/d/tools/android/platform-tools/
APK_DEST="/d/Google_Drive_i2x/Clients/Uchi/APKs/"
;;
esac
ADB=$PLATFORM_TOOLS/adb
case "$action" in
grab-apk)
name=$(xmlstarlet sel -N x=http://www.w3.org/ns/widgets -t -v '/x:widget/x:name' config.xml | sed 's/[^A-Za-z0-9_-]//g')
version=$(xmlstarlet sel -N x=http://www.w3.org/ns/widgets -t -v '/x:widget/@version' config.xml)
cp -v platforms/android/app/build/outputs/apk/debug/app-debug.apk "$APK_DEST/$name-$version.apk"
;;
grab-release-apk)
name=$(xmlstarlet sel -N x=http://www.w3.org/ns/widgets -t -v '/x:widget/x:name' config.xml | sed 's/[^A-Za-z0-9_-]//g')
version=$(xmlstarlet sel -N x=http://www.w3.org/ns/widgets -t -v '/x:widget/@version' config.xml)
cp -v platforms/android/app/build/outputs/apk/release/app-release.apk "$APK_DEST/$name-$version.apk"
;;
screencap)
if [ -z "$1" ] ; then
echo "Usage: $(basename $0) screencap {file}"
exit
else
file=$1 ; shift
$ADB shell screencap /sdcard/screen.png
$ADB pull /sdcard/screen.png $file
fi
;;
screenrec)
if [ -z "$1" -o -z "$2" ] ; then
echo "Usage: $(basename $0) screencap {file} {duration}"
exit
else
file=$1 ; shift
duration=$1 ; shift
$ADB shell screenrecord --verbose --time-limit $duration /sdcard/screen.mp4
$ADB pull /sdcard/screen.mp4 $file
fi
;;
adb)
exec $ADB "$@"
;;
sync-cap)
cap_conf=capacitor.config.json
and_conf=android/app/build.gradle
ios_conf=ios/App/App/Info.plist
if [ -f "$cap_conf" ] ; then
version_name=$(cat $cap_conf | jq -r .appVersion)
version_code=$(cat $cap_conf | jq -r .appVersionCode)
if [ -f "$and_conf" ] ; then
mv $and_conf $and_conf.prev
sed -e "s/versionCode .*/versionCode $version_code/" \
-e "s/versionName .*/versionName \"$version_name\"/" \
< $and_conf.prev > $and_conf
rm $and_conf.prev
else
echo "Android: $and_conf not found, skipping"
fi
if [ -f "$ios_conf" ] ; then
mv $ios_conf $ios_conf.prev
xmlstarlet ed -u '/plist/dict/key[text() = "CFBundleShortVersionString"]/following-sibling::string[1]' \
-v $version_name $ios_conf.prev > $ios_conf
mv $ios_conf $ios_conf.prev
xmlstarlet ed -u '/plist/dict/key[text() = "CFBundleVersion"]/following-sibling::string[1]' \
-v $version_name $ios_conf.prev > $ios_conf
rm $ios_conf.prev
else
echo "iOS: $ios_conf missing, skipping"
fi
else
echo "$cap_conf not found. Giving up."
exit
fi
;;
android-cap)
cap_conf=capacitor.config.json
if [ -f $cap_conf ] ; then
app_pkg=$(cat $cap_conf | jq -r .appId)
ionic cap copy
ionicassist sync-cap
cd android ; ./gradlew installDebug
$ADB shell monkey -p $app_pkg 1
else
echo "$cap_conf not found. Giving up";
fi
;;
ios-cap)
ionic cap copy
ionicassist sync-cap
ionic cap open ios
;;
*)
echo "Usage: $(basename $0) {grab-apk|grab-release-apk|screencap|adb|sync-cap|android-cap}"
exit 1
;;
esac
No comments:
Post a Comment