2

Phonegap アプリの読み込みを開始するときに、非同期スレッドで Android の LVL ライセンス検証を開始する方法を知りたいです。検証の結果が「アクセスなし」の場合は、アプリを閉じてください。私は、通常の一度に 1 ステップずつセットアップするよりも、このロジックを好みます。LVL にはかなりの数秒かかりますが、ライセンスを持っていない悪意のあるユーザーがアプリを閉じる前に数秒間そのアプリを見ることができたとしても、それは問題ではありません。

問題は、私が Java にあまり詳しくないことです。

私のアプリ Google Play で公開されている PhoneGap (Cordova) 有料アプリを持っています。LVL 検証を使用して、アプリがユーザーによって支払われたかどうかを確認します。チェックに約5秒かかることを除いて、魅力のように機能します。多くの場合、スプラッシュ スクリーンでさえ数秒間表示されません。

したがって、ユーザーは 5 秒間黒い画面で立ち往生し、Java コードのロード中にスプラッシュ画面が表示され、最後に Java スクリプトが完了するまでデフォルトの淡色表示のホーム画面表示されます。そのため、この起動遅延を短縮することに非常に意欲的です。

非同期アプローチの使用を提案するコメントをいくつか読みました。URL のロードをすぐに開始し、ライセンス チェックを asyncTask として実行します。しかし、ライセンスが無効な場合に WebView を閉じるために WebView を asyncTask に渡す方法がわかりません。

初挑戦ライセンスチェック自体が非同期なので、スプラッシュスクリーンを設定してURLを読み込んでからライセンスチェックをしてみました。以下のコードを参照してください。チェックが「許可されていません」を返した場合、コールバックはアプリを閉じる必要があります。ただし、この設定を試してみると、Google Play で強制応答を「無効」または「不明」などに設定しても、LVL サーバーは常に「有効」を返します。

私は A か B のどちらかを探しています: A. LVL を正しく応答させる方法。B. 非同期ライセンス チェックを実装する別の方法。

以下のコードは、現在のコードを抽象化したものです。DroidGap は Web ビューです。基本的に、onCreate はライセンス チェックを開始し、ライセンス チェック コールバックはアプリの HTML をロードするか、Web ビューを閉じます。

public class App extends DroidGap {

    public void onCreate(Bundle icicle) {
        super.setIntegerProperty("splashscreen", R.drawable.splash);
        super.loadUrl("file:///android_asset/www/index.html");

        mCheckerCallback = new LicenseCheckerCallback();
        checkAccess(mCheckerCallback);
    }

private class MyCheckerCallback implements LicenseCheckerCallback() {
    public void Allow() {
         //Do nothing
    }
    public void DontAllow(){
         finish();
    }

}
4

1 に答える 1

1

スコットは私に解決策を見つけたかどうか尋ねました。私がどのように行ったかを思い出すには長すぎますが、以下の設定は私にとってはうまくいったようです. それが役立つことを願っています!

package com.phonegap.mappingtheforest.helloworld;

import org.apache.cordova.DroidGap;

//import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.provider.Settings.Secure;
import android.util.Log;
import android.widget.Toast;

import com.android.vending.licensing.AESObfuscator;
import com.android.vending.licensing.LicenseChecker;
import com.android.vending.licensing.LicenseCheckerCallback;
import com.android.vending.licensing.ServerManagedPolicy;
//import com.phonegap.afforditfull.R;


public class App extends DroidGap { 

    private LicenseChecker mChecker;
    private LicenseCheckerCallback mLicenseCheckerCallback;
    private static final String BASE64_PUBLIC_KEY = "MyBase64PublicKey";
 // Generate 20 random bytes, and put them here.
    private static final byte[] SALT = new byte[] {
     //[my bunch of integers]
     };
    private AESObfuscator mObsfuscator;
    private String android_id;

    /** Called when the activity is first created. */ 
    @Override 
    public void onCreate(Bundle icicle) { 
         super.onCreate(icicle); 
         //setContentView(R.layout.main);
         super.loadUrl("file:///android_asset/www/index.html",1);
         //super.setStringProperty("loadingDialog", "Starting Afford-It...");
         super.setIntegerProperty("splashscreen", R.drawable.splash);
         android_id = Secure.getString(this.getContentResolver(), Secure.ANDROID_ID);
         mObsfuscator = new AESObfuscator(SALT, getPackageName(), android_id);
         ServerManagedPolicy serverPolicy = new ServerManagedPolicy(this,mObsfuscator);

         mLicenseCheckerCallback = new MyLicenseCheckerCallback();
         mChecker = new LicenseChecker(
             this, serverPolicy,
             BASE64_PUBLIC_KEY  // Your public licensing key.
             );
         mChecker.checkAccess(mLicenseCheckerCallback);  
    }

private class MyLicenseCheckerCallback implements LicenseCheckerCallback {
        public void allow() {
            if (isFinishing()) {
                // Don't update UI if Activity is finishing.
                return;
            }
            // Should allow user access.
            Log.w("LicenseChecker", "Allow");
            Intent i = new Intent(App.this, DroidGap.class);
            startActivity(i);
            finish();
        }

        public void dontAllow() {
            if (isFinishing()) {
                // Don't update UI if Activity is finishing.
                return;
            }
            Log.w("LicenseChecker", "Don't Allow");
            // Should not allow access. An app can handle as needed,
            // typically by informing the user that the app is not licensed
            // and then shutting down the app or limiting the user to a
            // restricted set of features.
            // In this example, we show a dialog that takes the user to Market.
            showDialog(0);

        }

        @Override
        public void applicationError(ApplicationErrorCode errorCode) {
            if (isFinishing()) {
                // Don't update UI if Activity is finishing.
                return;
            }
            toast("Error: " + errorCode.name());

        }
    }
    @Override
    protected Dialog onCreateDialog(int id) {
        // We have only one dialog.
        return new AlertDialog.Builder(this)
                .setTitle("Application Not Licensed")
                .setCancelable(false)
                .setMessage(
                        "This application is not licensed. Please purchase it from Android Market")
                .setPositiveButton("Buy App",
                        new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialog,
                                    int which) {
                                Intent marketIntent = new Intent(
                                        Intent.ACTION_VIEW,
                                        Uri.parse("market://details?id=com.phonegap.mappingtheforest.afforditpaid" + getPackageName()));
                                startActivity(marketIntent);
                                finish();
                            }
                        })
                .setNegativeButton("Exit",
                        new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialog,
                                    int which) {
                                finish();
                            }
                        }).create();
    }   

    public void toast(String string) {
        Toast.makeText(this, string, Toast.LENGTH_SHORT).show();
    }

    @Override
    public void onDestroy() {
    super.onDestroy();
    mChecker.onDestroy();
  }
}
于 2014-10-09T08:19:22.020 に答える