上記の Cesidio DiBenedetto の回避策をアプリに実装することができました。うまく機能していますが、 PhoneGap/Cordoveを使用したことがない人(私のように) にとっては、少し難しいかもしれません。そこで、実装中にまとめたちょっとしたハウツーを以下に示します。
Apache Cordovaは、Web テクノロジを使用するだけでマルチプラットフォームのモバイル アプリを構築できるプラットフォームです。主な機能は、ネイティブ API を JavaScript にエクスポートするため、Web サイトとネイティブ アプリケーションの間で通信する方法を提供することです。一般的な PhoneGap/Cordova アプリは、Cordova レイヤーと一緒に 1 つの APK にバンドルされている静的な Web サイトです。しかし、Cordova を使用してリモート Web サイトを表示することはできます。
回避策は次のとおりです。Webサイトの表示WebView
に使用する標準の代わりに。CordovaWebView
ユーザーが [参照] をクリックしてファイルを選択すると、標準の JavaScript (jQuery...) を使用してそのクリックをキャッチし、Cordova API を使用してネイティブ側で Cesidio DiBenedetto の filechooser プラグインをアクティブにし、素敵なファイル ブラウザーを開きます。ユーザーがファイルを選択すると、ファイルは JavaScript 側に送り返され、そこから Web サーバーにアップロードされます。
知っておくべき重要なことは、Web サイトに Cordova サポートを追加する必要があるということです。さて、実際のハウツーは...
まず、Cordova を既存のアプリに追加する必要があります。私はこのドキュメントに従いました。いくつかの手順がわかりにくかったので、詳しく説明します。
Cordova をダウンロードしてアプリの外に展開し、説明に従って cordova-3.4.0.jarをビルドします。local.propertiesファイルが見つからないため、おそらく初めて失敗します。エラー出力で作成方法を指示されます。Android アプリのビルドに使用する SDK を指定するだけです。
コンパイルされた jar ファイルをアプリのlibディレクトリにコピーし、jar をライブラリとして追加します。私のように Android Studio を使用している場合はcompile fileTree(dir: 'libs', include: ['*.jar', '*.aar'])
、build.gradledependencies
内にあることを確認してください。次に、Sync project with gradle filesボタンをクリックするだけで問題ありません。
/res/xml/main.xmlファイルを作成する必要はありません。CordovaWebView は、標準の WebView と同じように扱うことができるため、レイアウト ファイルに直接配置できます。
元のドキュメントの手順 5 ~ 7 に従ってActivity
、 が実行される場所を独自に作成しますCordobaWebView
。/framework/src/org/apache/cordova/CordovaActivity.java
ダウンロードした Cordova パッケージの を確認することをお勧めします。実装に必要なほとんどのメソッドを単純にコピーできます。6. ステップは、filechooser プラグインを使用できるようにするため、この目的にとって非常に重要です。
HTML および JavaScript ファイルはどこにもコピーしないでください。後で Web サイトに追加します。
config.xmlファイルをコピーすることを忘れないでください(変更する必要はありません)。
に Web サイトをロードするにはCordovaWebView
、その URL を cwv.loadUrl()
の代わりに に渡すだけですConfig.getStartUrl()
。
次に、FileChooser プラグインをアプリに追加する必要があります。cordova plugin add
標準の Cordova セットアップを使用していないため、readme の指示に従ってヒットすることはできず、手動で追加する必要があります。
リポジトリをダウンロードし、ソース ファイルをアプリにコピーします。resフォルダーのコンテンツがアプリの res フォルダーに移動することを確認してください。今のところ、JavaScript ファイルは無視してかまいません。
READ_EXTERNAL_STORAGE
アプリに権限を追加します。
次のコードを/res/xml/config.xmlに追加します。
<feature name="FileChooser">
<param name="android-package" value="com.cesidiodibenedetto.filechooser.FileChooser" />
</feature>
今こそ、Web サイトに Cordova サポートを追加するときです。思ったより簡単で、cordova.jsを Web サイトにリンクするだけですが、知っておくべきことが 2 つあります。
まず、各プラットフォーム (Android、iOS、WP) には独自のcordova.jsがあるため、必ず Android バージョンを使用してください (これは、/framework/assets/wwwでダウンロードした Cordova パッケージにあります)。
次に、Web サイトがCordovaWebView
と標準のブラウザー (デスクトップまたはモバイル) の両方からアクセスされる場合、通常は、ページが に表示されている場合にのみcordova.jsCordovaWebView
をロードすることをお勧めします。検出する方法はいくつか見つかりましCordovaWebView
たが、次の方法がうまくいきました。あなたのウェブサイトの完全なコードは次のとおりです。
function getAndroidVersion(ua) {
var ua = ua || navigator.userAgent;
var match = ua.match(/Android\s([0-9\.]*)/);
return match ? parseFloat(match[1]) : false;
};
if (window._cordovaNative && getAndroidVersion() >= 4.4) {
// We have to use this ugly way to get cordova working
document.write('<script src="/js/cordova.js" type="text/javascript"></script>');
}
Android のバージョンもチェックしていることに注意してください。この回避策は、キットカットにのみ必要です。
この時点で、Web サイトからFileChooserプラグインを手動で呼び出すことができるはずです。
var cordova = window.PhoneGap || window.Cordova || window.cordova;
cordova.exec(function(data) {}, function(data) {}, 'FileChooser', 'open', [{}]);
これにより、ファイル ブラウザーが開き、ファイルを選択できるようになります。これは、イベント deviceready が発生した後にのみ実行できることに注意してください。テストするには、jQuery を使用してこのコードをボタンにバインドします。
最後のステップは、これをすべてまとめて、アップロード フォームを機能させることです。これを実現するには、 READMEに記載されている Cesidio DiBenedetto の指示に従うだけです。ユーザーがFileChooserでファイルを選択すると、ファイルパスが JavaScript 側に返され、そこから別の Cordova プラグインFileTransferが実際のアップロードを実行するために使用されます。つまり、ファイルはネイティブ側ではなく、ネイティブ側にアップロードされますCordovaWebView
(私が正しく理解している場合)。
別の Cordova プラグインを自分のアプリケーションに追加する気にはなれませんでした。また、それが Cookie でどのように機能するかもわかりませんでした (認証されたユーザーのみがファイルのアップロードを許可されているため、要求と共に Cookie を送信する必要があります)。それは私のやり方です。FileChooserプラグインを変更して、パスではなくファイル全体を返すようにしました。したがって、ユーザーがファイルを選択すると、そのコンテンツを読み取り、 を使用してエンコードしbase64
、JSON としてクライアント側に渡し、そこでデコードして、JavaScript を使用してサーバーに送信します。それは機能しますが、base64 はかなり CPU を必要とするため、大きなファイルがアップロードされるとアプリが少しフリーズする可能性があるため、明らかな欠点があります。
それを行うには、まずこのメソッドをFileUtilsに追加します。
public static byte[] readFile(final Context context, final Uri uri) throws IOException {
File file = FileUtils.getFile(context, uri);
return org.apache.commons.io.FileUtils.readFileToByteArray(file);
}
Apache Commons ライブラリを使用することに注意してください。それを含めるか、外部ライブラリを必要としない他の方法でファイルを読み取ることを忘れないでください。
次に、FileChooser.onActivityResultメソッドを変更して、パスではなくファイルの内容を返します。
// Get the URI of the selected file
final Uri uri = data.getData();
Log.i(TAG, "Uri = " + uri.toString());
JSONObject obj = new JSONObject();
try {
obj.put("filepath", FileUtils.getPath(this.cordova.getActivity(), uri));
obj.put("name", FileUtils.getFile(this.cordova.getActivity(), uri).getName());
obj.put("type", FileUtils.getMimeType(this.cordova.getActivity(), uri));
// attach the actual file content as base64 encoded string
byte[] content = FileUtils.readFile(this.cordova.getActivity(), uri);
String base64Content = Base64.encodeToString(content, Base64.DEFAULT);
obj.put("content", base64Content);
this.callbackContext.success(obj);
} catch (Exception e) {
Log.e("FileChooser", "File select error", e);
this.callbackContext.error(e.getMessage());
}
最後に、これは Web サイトで使用するコードです (jQuery が必要です)。
var cordova = window.PhoneGap || window.Cordova || window.cordova;
if (cordova) {
$('form.fileupload input[type="file"]', context).on("click", function(e) {
cordova.exec(
function(data) {
var url = $('form.fileupload', context).attr("action");
// decode file from base64 (remove traling = first and whitespaces)
var content = atob(data.content.replace(/\s/g, "").replace(/=+$/, ""));
// convert string of bytes into actual byte array
var byteNumbers = new Array(content.length);
for (var i = 0; i < content.length; i++) {
byteNumbers[i] = content.charCodeAt(i);
}
var byteContent = new Uint8Array(byteNumbers);
var formData = new FormData();
var blob = new Blob([byteContent], {type: data.type});
formData.append('file', blob, data.name);
$.ajax({
url: url,
data: formData,
processData: false,
contentType: false,
type: 'POST',
success: function(data, statusText, xhr){
// do whatever you need
}
});
},
function(data) {
console.log(data);
alert("error");
},
'FileChooser', 'open', [{}]);
});
}
それだけです。これが機能するまでに数時間かかったので、誰かの助けになることを願って私の知識を共有しています.