我正在开发Android的Cordova插件,我很难克服从活动中访问项目资源 - 插件应该是项目独立的,但访问资源(例如R.java)证明是棘手的.
我的插件目前由两个非常简单的类组成:RedLaser.java和RedLaserScanner.java.
RedLaser.java
继承自CordovaPlugin,因此包含该execute方法,看起来类似于以下内容.
public class RedLaser extends CordovaPlugin {
private static final string SCAN_ACTION = "scan";
public boolean execute(String action, final JSONArray args, final CallbackContext callbackContext) throws JSONException {
if (action.equals(SCAN_ACTION)) {
this.cordova.getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
scan(args, callbackContext);
}
});
return true;
}
return false;
}
private void scan(JSONArray args, CallbackContext callbackContext) {
Intent intent = new Intent(this.cordova.getActivity().getApplicationContext(), RedLaserScanner.class);
this.cordova.startActivityForResult((CordovaPlugin) this, intent, 1);
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
// Do something with the result
}
}
Run Code Online (Sandbox Code Playgroud)
RedLaserScanner.java
RedLaserScanner包含Android Activity逻辑,并继承自BarcodeScanActivity(这是一个RedLaser SDK类,可能本身继承自Activity);
一个非常简单的结构如下:
public class RedLaserScanner extends BarcodeScanActivity {
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
setContentView(R.layout.preview_overlay_new_portrait);
}
}
Run Code Online (Sandbox Code Playgroud)
我遇到了麻烦,因为我需要访问项目的资源来访问R.layout.preview_overlay_new_portrait(它们分散在Eclipse项目中) - 但除非我导入com.myProject.myApp.R,否则我不能这样做- 这使得我的插件依赖于项目本身.
我做了一些调查,发现cordova.getActivity().getResources()它看起来很有用,但是我的RedLaserScanner无法访问它 - 因为它不会从CordovaPlugin继承.
有人可以帮我指点一下吗?
谢谢
我刚遇到同样的问题,结果很容易解决.RedLaserScanner扩展了一个活动,所以你可以像这样调用getResources():
setContentView(getResources("preview_overlay_new_portrait", "layout", getPackageName()));
Run Code Online (Sandbox Code Playgroud)
挂钩可用于替换源文件内容以删除错误的导入和/或添加正确的资源导入。
我创建了一个脚本,无需指定文件即可执行此操作。它尝试查找源文件(带有.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;
}
Run Code Online (Sandbox Code Playgroud)
只需在您的plugin.xml中添加after_plugin_install挂钩(适用于Android 平台)即可:
<hook type="after_plugin_install" src="scripts/android/addResourcesClassImport.js" />
Run Code Online (Sandbox Code Playgroud)
希望它能帮助别人!
| 归档时间: |
|
| 查看次数: |
5230 次 |
| 最近记录: |