Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ionic Framework + Phonegap Build : workflow

I am trying to compile my Ionic app with Phonegap Build (I am working with a Mac so I can't compile to iOS otherwise).

What's is the best workflow ?

Thanks

like image 365
Louis Avatar asked Apr 02 '15 08:04

Louis


People also ask

Can I use PhoneGap Build with Ionic appflow?

One of the appeals of PhoneGap Build was its simplicity to trigger a build, zip up your app, and upload it to PhoneGap Build and a build with then automatically kick-off. While it was possible to connect PhoneGap Build with a Git repository, it was an optional step. Ionic Appflow requires the use of Git as part of its workflow.

What apps can I migrate to ionic appflow?

PhoneGap/Cordova apps written in jQuery Mobile, Framework 7, Sencha, KendoUI, or even your own custom solution can be migrated. An existing Ionic app is not required. Ionic has Advisory servicesavailable if you need migration assistance. note Building your app in the cloud with Ionic Appflow requires a subscription to the Launch plan and above.

How do I integrate my App with appflow?

With your app ready for Appflow integration, it’s time to sign up, link your Git repository, then build the native iOS and Android versions. Begin by signing up for an Appflow account. Once you’re logged into Appflow, navigate to the Apps page then click the “New App” button. Enter your app’s name then click the “Create App” button.

How do I connect my GitHub repository to ionic appflow?

Connect to a Git Host​ Next, head to the Settings -> Git page. Under the “GitHub” or “Bitbucket Cloud” tabs that appear, link your GitHub or Bitbucket account to Ionic Appflow by clicking the "Connect" button then authenticating using the standard OAuth login process. After connecting your account, a list of your code repositories will appear.


2 Answers

After fighting this all night and all morning, i came up with a hackish solution.
Hope it helps someone.

As of ionic v1.0, at least for my simplistic project, the biggest difference is just

  • config.xml
  • all the image assets are in ./resources

What i did:
config.xml changes:

  • created a new file in .www/config_phonegap.xml based on config.xml
  • On widget node changed the namespace to phonegap (xmlns:gap="http://phonegap.com/ns/1.0")
  • used regex search replace to change all the icon and splash tags to the corresponding phonegap equivalent
  • manually created the necessary "gap:plugin" tags for any plugins

gulp additions:

  • created a gulp task to copy .www/ into a ./phonegap folder
  • gulp task also copies over resources
  • gulp task coipies over config_phonegap.xml and renames it as config.xml
  • gulp task to zip up our new www folder. (there should be no top level www in the zip file. i.e. we only want to zip the contents of www)

What this means is that my build workflow (until i need to change something in config.xml) now looks like this:

  1. gulp phonegap
  2. upload phonegap.zip to https://build.phonegap.com

Obviously lots of area for improvement here but I needed something i can use to publish now. Before just making a static config_phonegap.xml i explored a few ideas like xml parsing in JS or making an XSLT file. For the amount of effort, it seemed like low return at this point so i didn't follow through.

Here's relevant code bits for reference
Regex:

### icon regex
# android
<icon src="([\.\w\\-]+)" density="([\w-]+)"/>
<icon src="$1" gap:platform="android" gap:qualifier="$2"/>

# ios
<icon src="([@\.\w\\-]+)" width="([\d]+)" height="([\d]+)"/>
<icon src="$1" gap:platform="ios" width="$2" height="$3" />


### splash regex
# android
<splash src="([\.\w\\-]+)" density="([\w-]+)"/>
<gap:splash src="$1" gap:platform="android" gap:qualifier="$2" />

#ios
<splash src="([~@\.\w\\-]+)" width="([\d]+)" height="([\d]+)"/>
<gap:splash src="$1" gap:platform="ios" width="$2" height="$3" />

sample phonegap compatible config.xml:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<widget id="com.yadda.yadda" version="2.0.0" xmlns="http://www.w3.org/ns/widgets" xmlns:gap="http://phonegap.com/ns/1.0">
  <name>my app name</name>
  <description>
        la di da desc
  </description>
  <author email="[email protected]" href="https://harhar.com/">w--</author>

  <content src="index.html"/>
  <access origin="*"/>

  <preference name="webviewbounce" value="false"/>
  <preference name="UIWebViewBounce" value="false"/>
  <preference name="DisallowOverscroll" value="true"/>
  <preference name="BackupWebStorage" value="none"/>
  <preference name="SplashScreen" value="screen"/>
  <preference name="SplashScreenDelay" value="1500"/>

  <icon src="resources/android/icon/drawable-ldpi-icon.png" gap:platform="android" gap:qualifier="ldpi"/>
  <icon src="resources/android/icon/drawable-mdpi-icon.png" gap:platform="android" gap:qualifier="mdpi"/>
  <icon src="resources/android/icon/drawable-hdpi-icon.png" gap:platform="android" gap:qualifier="hdpi"/>
  <icon src="resources/android/icon/drawable-xhdpi-icon.png" gap:platform="android" gap:qualifier="xhdpi"/>
  <icon src="resources/android/icon/drawable-xxhdpi-icon.png" gap:platform="android" gap:qualifier="xxhdpi"/>
  <icon src="resources/android/icon/drawable-xxxhdpi-icon.png" gap:platform="android" gap:qualifier="xxxhdpi"/>
  <gap:splash src="resources/android/splash/drawable-land-ldpi-screen.png" gap:platform="android" gap:qualifier="land-ldpi" />
  <gap:splash src="resources/android/splash/drawable-land-mdpi-screen.png" gap:platform="android" gap:qualifier="land-mdpi" />
  <gap:splash src="resources/android/splash/drawable-land-hdpi-screen.png" gap:platform="android" gap:qualifier="land-hdpi" />
  <gap:splash src="resources/android/splash/drawable-land-xhdpi-screen.png" gap:platform="android" gap:qualifier="land-xhdpi" />
  <gap:splash src="resources/android/splash/drawable-land-xxhdpi-screen.png" gap:platform="android" gap:qualifier="land-xxhdpi" />
  <gap:splash src="resources/android/splash/drawable-land-xxxhdpi-screen.png" gap:platform="android" gap:qualifier="land-xxxhdpi" />
  <gap:splash src="resources/android/splash/drawable-port-ldpi-screen.png" gap:platform="android" gap:qualifier="port-ldpi" />
  <gap:splash src="resources/android/splash/drawable-port-mdpi-screen.png" gap:platform="android" gap:qualifier="port-mdpi" />
  <gap:splash src="resources/android/splash/drawable-port-hdpi-screen.png" gap:platform="android" gap:qualifier="port-hdpi" />
  <gap:splash src="resources/android/splash/drawable-port-xhdpi-screen.png" gap:platform="android" gap:qualifier="port-xhdpi" />
  <gap:splash src="resources/android/splash/drawable-port-xxhdpi-screen.png" gap:platform="android" gap:qualifier="port-xxhdpi" />
  <gap:splash src="resources/android/splash/drawable-port-xxxhdpi-screen.png" gap:platform="android" gap:qualifier="port-xxxhdpi" />

  <icon src="resources/ios/icon/icon.png" gap:platform="ios" width="57" height="57" />
  <icon src="resources/ios/icon/[email protected]" gap:platform="ios" width="114" height="114" />
  <icon src="resources/ios/icon/icon-40.png" gap:platform="ios" width="40" height="40" />
  <icon src="resources/ios/icon/[email protected]" gap:platform="ios" width="80" height="80" />
  <icon src="resources/ios/icon/icon-50.png" gap:platform="ios" width="50" height="50" />
  <icon src="resources/ios/icon/[email protected]" gap:platform="ios" width="100" height="100" />
  <icon src="resources/ios/icon/icon-60.png" gap:platform="ios" width="60" height="60" />
  <icon src="resources/ios/icon/[email protected]" gap:platform="ios" width="120" height="120" />
  <icon src="resources/ios/icon/[email protected]" gap:platform="ios" width="180" height="180" />
  <icon src="resources/ios/icon/icon-72.png" gap:platform="ios" width="72" height="72" />
  <icon src="resources/ios/icon/[email protected]" gap:platform="ios" width="144" height="144" />
  <icon src="resources/ios/icon/icon-76.png" gap:platform="ios" width="76" height="76" />
  <icon src="resources/ios/icon/[email protected]" gap:platform="ios" width="152" height="152" />
  <icon src="resources/ios/icon/icon-small.png" gap:platform="ios" width="29" height="29" />
  <icon src="resources/ios/icon/[email protected]" gap:platform="ios" width="58" height="58" />
  <icon src="resources/ios/icon/[email protected]" gap:platform="ios" width="87" height="87" />
  <gap:splash src="resources/ios/splash/Default-568h@2x~iphone.png" gap:platform="ios" width="640" height="1136" />
  <gap:splash src="resources/ios/splash/Default-667h.png" gap:platform="ios" width="750" height="1334" />
  <gap:splash src="resources/ios/splash/Default-736h.png" gap:platform="ios" width="1242" height="2208" />
  <gap:splash src="resources/ios/splash/Default-Landscape-736h.png" gap:platform="ios" width="2208" height="1242" />
  <gap:splash src="resources/ios/splash/Default-Landscape@2x~ipad.png" gap:platform="ios" width="2048" height="1536" />
  <gap:splash src="resources/ios/splash/Default-Landscape~ipad.png" gap:platform="ios" width="1024" height="768" />
  <gap:splash src="resources/ios/splash/Default-Portrait@2x~ipad.png" gap:platform="ios" width="1536" height="2048" />
  <gap:splash src="resources/ios/splash/Default-Portrait~ipad.png" gap:platform="ios" width="768" height="1024" />
  <gap:splash src="resources/ios/splash/Default@2x~iphone.png" gap:platform="ios" width="640" height="960" />
  <gap:splash src="resources/ios/splash/Default~iphone.png" gap:platform="ios" width="320" height="480" />

  <icon src="icon.png"/>
  <gap:splash src="splash.png" />

 <!-- so android doesnt' go bat shit crazy -->
  <preference name="permissions" value="none"/>

 <!-- plugins -->
  <feature name="StatusBar">
    <param name="ios-package" value="CDVStatusBar" onload="true"/>
  </feature>
 <gap:plugin name="cordova-plugin-statusbar" source="npm" version="1.0.0">
   <param name="onload" value="true" />
 </gap:plugin>
 <gap:plugin name="cordova-plugin-splashscreen" source="npm" version="2.0.0" />
</widget>

gulp tasks:

// **** Build phonegap *****/
var PHONEGAP_BUILD_FOLDER = '../phonegap',
      PHONEGAP_RAW_FOLDER = 'www',
      IONIC_SOURCE_FOLDER = './www',
      IONIC_RESOURCE_FOLDER = './resources'
      PHONEGAP_ZIP_FILE = 'phonegap_build.zip';

gulp.task('phonegap', function(cb){
  runSequence('clean_phonegap',
              'copy_www',
              'copy_resources',
              'copy_phonegap_config_xml',
              'copy_default_icon',
              'copy_default_splash',
              'zip_phonegap',
              cb);
});

gulp.task('clean_phonegap', function(cb){
  // clean our folder first
  var phonegap_del_pattern = PHONEGAP_BUILD_FOLDER + '/*';
  del([phonegap_del_pattern], {force: true}, cb);
})

gulp.task('copy_www', function(){
  var target_phonegap_folder = PHONEGAP_BUILD_FOLDER + '/' + PHONEGAP_RAW_FOLDER
  return gulp.src([IONIC_SOURCE_FOLDER + '/**'])
              .on('error', swallowError)
              .pipe(gulp.dest(target_phonegap_folder))
})

gulp.task('copy_phonegap_config_xml', function(){
  var target_phonegap_folder = PHONEGAP_BUILD_FOLDER + '/' + PHONEGAP_RAW_FOLDER
  return gulp.src(['config_phonegap.xml'])
              .on('error', swallowError)
              .pipe(rename('config.xml'))
              .pipe(gulp.dest(target_phonegap_folder));
})

gulp.task('copy_resources', function(){
  var target_phonegap_folder = PHONEGAP_BUILD_FOLDER + '/' + PHONEGAP_RAW_FOLDER + '/resources',
      exclude_pattern = '!' + IONIC_RESOURCE_FOLDER + '/_source_assets{,/**}'

  // exclude pattern needs to go first. mother fucker.
  return gulp.src([exclude_pattern, IONIC_RESOURCE_FOLDER + '/**'])
              .on('error', swallowError)
              .pipe(gulp.dest(target_phonegap_folder));
})

gulp.task('copy_default_icon', function(){
  var target_phonegap_folder = PHONEGAP_BUILD_FOLDER + '/' + PHONEGAP_RAW_FOLDER;
  return gulp.src([IONIC_RESOURCE_FOLDER + '/ios/icon.png' ])
              .on('error', swallowError)
              .pipe(gulp.dest(target_phonegap_folder));
})

gulp.task('copy_default_splash', function(){
  var target_phonegap_folder = PHONEGAP_BUILD_FOLDER + '/' + PHONEGAP_RAW_FOLDER;
  return gulp.src([IONIC_RESOURCE_FOLDER + '/splash.png' ])
              .on('error', swallowError)
              .pipe(gulp.dest(target_phonegap_folder));
})


gulp.task('zip_phonegap', function(){
  var sourcephonegap_folder = PHONEGAP_BUILD_FOLDER + '/' + PHONEGAP_RAW_FOLDER
  return gulp.src(sourcephonegap_folder + '/**')
        .pipe(zip('phonegap.zip'))
        .on('error', swallowError)
        .pipe(gulp.dest(PHONEGAP_BUILD_FOLDER));
})
like image 81
w-- Avatar answered Nov 15 '22 09:11

w--


This is my own attempt to answer this (please help me update this so everybody can benefit):

Build your app with Ionic:

ionic start myApp sidemenu
etc...

In a default Ionic app the config.xml file is located in the root directory, above the www/ folder, so move it into the www/ folder for Phonegap Build to find it.

mv config.xml www/

Then zip the www/ folder or git push it from your local machine to the remote git repo that you have linked with Phonegap Build. Only zip or push this directory, because if you let the other directories present in the Ionic root directory, like node_modules, your app will be too large to compile on Phonegap Build.

Then compile on Phonegap Build.

like image 37
Louis Avatar answered Nov 15 '22 08:11

Louis