5

アクティビティを持つ Cordova プラグインを開発しています。このアクティビティからアプリケーション R.layout にアクセスして、 を呼び出せるようにする必要がありますsetContentView

私は現在import com.example.hello.RonCreate method I callsetContentView(R.layout.mysurfaceview)` を作成してからこれを行っています:

問題は、アプリケーション名が の場合にのみプラグインが機能することですがcom.example.hello、手動でインポートを行わずにプラグインを別のアプリケーションにインストールする必要があります。

のような一般的なインポートimport <appName>.Rを行う方法、またはそれを行う他の方法はありますか?

4

4 に答える 4

13

実行時にアプリケーションのリソース プールを呼び出し、Resources.getIdentifier()関数を使用して名前で識別子を参照できます。この関数には、リソース名、タイプ、およびパッケージ名が必要です。例えば:

 String package_name = getApplication().getPackageName();
 Resources resources = getApplication().getResources();
 setContentView(resources.getIdentifier("my_activity_layout", "layout", package_name));

ここで、「my_activity_layout」はレイアウト xml ファイルの名前です。文字列、ドローアブル、およびその他のリソースも同じ方法で参照できます。アクティビティにコードを少し追加したら、アクティビティ レイアウト ファイルを plugin.xml ファイルのソース ファイルとして指定し、それを res/layout フォルダーにコピーするように設定できます。

<source-file src="path/to/your/layout/file.xml" target-dir="res/layout"/>

ソースファイル指定の使用について他に質問がある場合は、 Phonegap プラグインの仕様を確認してください。

于 2013-12-30T21:20:44.880 に答える
1

おそらく、AndroidManifest または config.xml からパッケージの名前を解析して、ビルド時に Java インポート ステートメントを変更する ために、 cordova CLI フックを使用します。

あなたが求めているようなワイルドカードパッケージのインポートを行う方法があるとは思いません。

于 2013-11-16T04:22:50.727 に答える
1

mooreds の回答のおかげで、after_plugin_install以下のようにプラグインにフックを作成できます

#!/usr/bin/env node
/*
A hook to add R.java to the draw activiy in Android platform.
*/


var fs = require('fs');
var path = require('path');

var rootdir = process.argv[2];

function replace_string_in_file(filename, to_replace, replace_with) {
    var data = fs.readFileSync(filename, 'utf8');
    var result = data.replace(to_replace, replace_with);
    fs.writeFileSync(filename, result, 'utf8');
}

var target = "stage";
if (process.env.TARGET) {
    target = process.env.TARGET;
}

    var ourconfigfile = path.join( "plugins", "android.json");
    var configobj = JSON.parse(fs.readFileSync(ourconfigfile, 'utf8'));
  // Add java files where you want to add R.java imports in the following array

    var filestoreplace = [
        "platforms/android/src/in/co/geekninja/plugin/SketchActivity.java"
    ];
    filestoreplace.forEach(function(val, index, array) {
        if (fs.existsSync(val)) {
          console.log("Android platform available !");
          //Getting the package name from the android.json file,replace with your plugin's id
          var packageName = configobj.installed_plugins["in.co.geekninja.Draw"]["PACKAGE_NAME"];
          console.log("With the package name: "+packageName);
          console.log("Adding import for R.java");
            replace_string_in_file(val,"package in.co.geekninja.plugin;","package in.co.geekninja.plugin;\n\nimport "+packageName+".R;");

        } else {
            console.log("No android platform found! :(");
        }
    });

<platform name="android"> ... </platform>タグの間に次の行を追加します

<hook type="after_plugin_install" src="hooks/after_plugin_install/hook-add-r-import.js" />
于 2016-07-27T07:06:19.403 に答える
1

@insomniac が述べたように、フックを使用してソース ファイルの内容を置き換え、間違ったインポートを削除したり、リソースの正しいインポートを追加したりできます。

彼の答えに基づいて、ファイルを指定する必要なくそれを行うスクリプトを作成できました。ソース ファイル (拡張子は.java )を見つけようとし、そこに既にあるリソース インポートをすべて削除してから、Cordova アプリケーション パッケージ名を使用して、適切なリソース インポートを (必要に応じて) 配置します。

これはスクリプトです:

#!/usr/bin/env node

/*
 * A hook to add resources class (R.java) import to Android classes which uses it.
 */

function getRegexGroupMatches(string, regex, index) {
    index || (index = 1)

    var matches = [];
    var match;
    if (regex.global) {
        while (match = regex.exec(string)) {
            matches.push(match[index]);
            console.log('Match:', match);
        }
    }
    else {
        if (match = regex.exec(string)) {
            matches.push(match[index]);
        }
    }

    return matches;
}

module.exports = function (ctx) {
    // If Android platform is not installed, don't even execute
    if (ctx.opts.cordova.platforms.indexOf('android') < 0)
        return;

    var fs = ctx.requireCordovaModule('fs'),
        path = ctx.requireCordovaModule('path'),
        Q = ctx.requireCordovaModule('q');

    var deferral = Q.defer();

    var platformSourcesRoot = path.join(ctx.opts.projectRoot, 'platforms/android/src');
    var pluginSourcesRoot = path.join(ctx.opts.plugin.dir, 'src/android');

    var androidPluginsData = JSON.parse(fs.readFileSync(path.join(ctx.opts.projectRoot, 'plugins', 'android.json'), 'utf8'));
    var appPackage = androidPluginsData.installed_plugins[ctx.opts.plugin.id]['PACKAGE_NAME'];

    fs.readdir(pluginSourcesRoot, function (err, files) {
        if (err) {
            console.error('Error when reading file:', err)
            deferral.reject();
            return
        }

        var deferrals = [];

        files.filter(function (file) { return path.extname(file) === '.java'; })
            .forEach(function (file) {
                var deferral = Q.defer();

                var filename = path.basename(file);
                var file = path.join(pluginSourcesRoot, filename);
                fs.readFile(file, 'utf-8', function (err, contents) {
                    if (err) {
                        console.error('Error when reading file:', err)
                        deferral.reject();
                        return
                    }

                    if (contents.match(/[^\.\w]R\./)) {
                        console.log('Trying to get packages from file:', filename);
                        var packages = getRegexGroupMatches(contents, /package ([^;]+);/);
                        for (var p = 0; p < packages.length; p++) {
                            try {
                                var package = packages[p];

                                var sourceFile = path.join(platformSourcesRoot, package.replace(/\./g, '/'), filename)
                                if (!fs.existsSync(sourceFile)) 
                                    throw 'Can\'t find file in installed platform directory: "' + sourceFile + '".';

                                var sourceFileContents = fs.readFileSync(sourceFile, 'utf8');
                                if (!sourceFileContents) 
                                    throw 'Can\'t read file contents.';

                                var newContents = sourceFileContents
                                    .replace(/(import ([^;]+).R;)/g, '')
                                    .replace(/(package ([^;]+);)/g, '$1 import ' + appPackage + '.R;');

                                fs.writeFileSync(sourceFile, newContents, 'utf8');
                                break;
                            }
                            catch (ex) {
                                console.log('Could not add import to "' +  filename + '" using package "' + package + '". ' + ex);
                            }
                        }
                    }
                });

                deferrals.push(deferral.promise);
            });

        Q.all(deferrals)
            .then(function() {
                console.log('Done with the hook!');
                deferral.resolve();
            })
    });

    return deferral.promise;
}

plugin.xmlにafter_plugin_installフック (Android プラットフォーム用)として追加するだけです。

<hook type="after_plugin_install" src="scripts/android/addResourcesClassImport.js" />

それが誰かを助けることを願っています!

于 2017-06-08T15:07:40.473 に答える