Search code examples
cordovaionic-frameworkionic2phonegap-plugins

Ionic 2: copying resources to android platform


I added some images I want to add to android platform only. I've added the following lines under <platform name="android"> in my config.xml:

<resource-file src="resources/android/ic_stat_push_android/drawable-hdpi.png" target="platforms/android/res/drawable-hdpi/ic_stat_push_android.png" />

However I can't seem to get it to copy. What do I need to run for the resource to be copied?


Solution

  • For anyone who encounters this issue, this is the solution I ended up using.

    1. create a file named android_custom_resources.js:

      var fs = require('fs');
      var path = require('path');
      
      var sourceDir = 'resources/android/custom';
      var platformDir = 'platforms/android';
      var resourceDirs = [
      'res/drawable-ldpi',
      'res/drawable-mdpi',
      'res/drawable-mdpi-v11',
      'res/drawable-hdpi',
      'res/drawable-hdpi-v11',
      'res/drawable-xhdpi',
      'res/drawable-xhdpi-v11',
      'res/drawable-xxhdpi',
      'res/drawable-xxhdpi-v11',
      'res/drawable-xxxhdpi',
      'res/drawable-xxxhdpi-v11'
       ];
      
       module.exports = function(ctx) {
        if (ctx.opts.platforms.indexOf('android') < 0) {
          return;
        }
      
      var Q = ctx.requireCordovaModule('q');
      var deferred = Q.defer();
      var androidPlatformDir = path.join(ctx.opts.projectRoot, platformDir);
      var customResourcesDir = path.join(ctx.opts.projectRoot, sourceDir);
      
      function copy(src, dest) {
        var deferred = Q.defer();
      
        fs.stat(src, function(err, stats) {
          if (err || !stats.isFile()) {
            return deferred.reject(err);
          }
      
          fs.stat(path.dirname(dest), function(err, stats) {
            if (err || !stats.isDirectory()) {
              return deferred.reject(err);
            }
      
          var rs = fs.createReadStream(src);
      
          rs.on('error', function(err) {
            console.error(err.stack);
            deferred.reject(err);
          });
      
          var ws = fs.createWriteStream(dest);
      
          ws.on('error', function(err) {
            console.error(err.stack);
            deferred.reject(err);
          });
      
          ws.on('close', function() {
            deferred.resolve();
          });
      
          rs.pipe(ws);
        });
      });
      
      return deferred.promise;
      }
      
       fs.stat(customResourcesDir, function(err, stats) {
         if (err || !stats.isDirectory()) {
           return deferred.resolve();
        }
      
      fs.readdir(customResourcesDir, function(err, files) {
        var copies = [];
        for (var i in files) {
          var innerDir = path.join(customResourcesDir, files[i]);
          var innerFiles = fs.readdirSync(innerDir);
          for (var k in innerFiles){
            var innerFilePath = path.join(innerDir, innerFiles[k]);
            var innerDestPath = path.join(androidPlatformDir, 'res', files[i], innerFiles[k]);
      
            copies.push([innerFilePath, innerDestPath]);
          }
        }
      
        copies.map(function(args) {
          return copy.apply(copy, args);
        });
      
        Q.all(copies).then(function(r) {
          deferred.resolve();
        }, function(err) {
          console.error(err.stack);
          deferred.reject(err);
           });
         });
       });
      
       return deferred.promise;
      }
      
    2. place it in a folder in your root project directory (in my case I called it package_hooks and reference it from your config.xml

      <hook src="package_hooks/android_custom_resources.js" type="after_prepare" />
      

    this script assumes that inside your <project root>/resources/android/custom directory, files are placed in the folders named the same as the ones you expect them to be copied to. For example, if I have a file <my project>/resources/android/custom/drawable-xxhdpi/myfile.png, it will be copied to: <my project>/platforms/android/res/drawable-xxhdpi/myfile.png

    It will surely break if you have files in the /custom directory itself, but otherwise it did the job for me and I hope it helps someone else looking for a temporary solution.