2

Android と iOS の両方で正常に動作する Cordova プラグインがあります。ただし、Cordova for Windows Phone では複数の未解決のコールバックがサポートされていないように見えるため、Windows Phone 8 に移植すると失敗します。

問題はこれです:

DispatchCommandResult が、KeepCallback が true に設定された PluginResult で呼び出されると、別のメソッドからの別の DispatchCommand が、そのコールバックと前のコールバック (KeepCallback が true に設定されたもの) の両方を呼び出します。

さらに悪いことに、2 番目の DispatchCommandResult に、KeepCallback が false (デフォルト) に設定された PluginResult がある場合、KeepCallback が true に設定されている以降のコールバックがキャンセルされます。

以下のコードを検討してください。これは、Cordova Echo サンプルの変更です。

echo メソッドは (DispatchCommandResult を介して) 最初に呼び出されたときと同じ文字列で JavaScript の「成功」コールバックを呼び出します (2 回の JSON 変換の後)。

繰り返しメソッドは、別のスレッドで 5 秒ごとに JavaScript の「成功」コールバックを繰り返し呼び出すことを除いて、echo と同じことを行います。

repeat が呼び出され、echo が呼び出された後のある時点で、echo メソッドの DispatchCommandResult により、echo の成功と繰り返しの成功のコールバックの両方が呼び出され、KeepCallback が true に設定されていないため、それ以上の繰り返しの成功のコールバックが防止されます。

Android では、Cordova が提供する callbackId により、この問題は問題になりません。ただし、Windows Phone の場合、callbackId にはアクセスできません。

C# コード

namespace Cordova.Extension.Commands
{
    public class Echo : BaseCommand
    {
        public void echo(string options)
        {
            string optVal = JsonHelper.Deserialize<string[]>(options)[0];
            DispatchCommandResult(new PluginResult(PluginResult.Status.OK, optVal));
        }
        public void repeat(string options)
        {
            string optVal = JsonHelper.Deserialize<string[]>(options)[0];
            ThreadStart worker = () =>
            {
                try
                {
                    while (true)
                    {
                        Thread.Sleep(5000);
                        PluginResult r = new PluginResult(PluginResult.Status.OK, optVal);
                        r.KeepCallback = true;
                        DispatchCommandResult(r);
                    }
                }
                catch (Exception ex)
                {
                    this.DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, ex.Message));
                }
            };
            new Thread(worker).Start();
        }
    }
}

JavaScript コード

function echo() {
    function success(message) {
        console.log("echo success: " + message);
    }
    function error(e) {
        console.log("echo error: " + e);
    }
    cordova.exec(success, error, "Echo", "echo", ["Hello"]);
}

function repeat() {
    function success(message) {
        console.log("repeat success: " + message);
    }
    function error(e) {
        console.log("repeat error: " + e);
    }
    cordova.exec(success, error, "Echo", "repeat", ["Hello again"]);
}

echo();
.
.
.
repeat();
.
.
.
echo();

サンプル出力

Log:"echo success: Hello"
Log:"repeat success: Hello again"
Log:"repeat success: Hello again"
Log:"repeat success: Hello again"
Log:"repeat success: Hello again"
Log:"repeat success: Hello"
Log:"echo success: Hello"

他の誰かがこの問題を抱えていますか? もしそうなら、回避策はありますか?私は何か間違ったことをしていますか?

4

1 に答える 1

1

私はコルドバ2.5で同じ問題を抱えていましたが、これが私が見つけたものです。

(まだリリースされていない) 2.8 バージョンの cordova ではBaseCommand.cs、cordovalib ファイルの . CurrentCommandCallbackId呼び出したいコールバックを追跡するために使用できる を確認できます。

次に、KeepCallback を false に設定すると、必要なコールバックにコマンドをディスパッチできます。

PhoneGap の現在のリリースは 2.7.0 であるため、これを使用するには、cordova の 2.8 バージョンをPlugins複製し、cordovaおよびフォルダーのコンテンツをコピーする必要cordivalibがありtemplates/standaloneます。

完了したら、この新しい機能を次のように使用できます。

private void DispatchMessage(PluginResult.Status status, string message, bool keepCallback, string callBackID)
{
    PluginResult res = new PluginResult(status, message);
    res.KeepCallback = keepCallback;
    DispatchCommandResult(res, callBackID);
}

ただし、Phonegap 2.8 がリリースされたら、Cordova の公式バージョンでアプリを更新する方が安全です。

于 2013-05-30T12:12:10.167 に答える