2

我正在尝试一个示例应用程序来在 Android 中配置 Google License Service LVL

按照此处找到的说明进行操作

我刚刚尝试使用包含的代码配置基本应用程序

public class MainActivity extends Activity {
    private static final String BASE64_PUBLIC_KEY = "mykeywithoutspaces";

    // Generate your own 20 random bytes, and put them here.
    private static final byte[] SALT = new byte[] {
        -00, 65, 30, -128, -58, -57, 00, -64, 51, 32, -95, -45, 77, -117, -36, -15, -11, 32, -64,
        89
    };

    private TextView mStatusText;
    private Button mCheckLicenseButton;

    private LicenseCheckerCallback mLicenseCheckerCallback;
    private LicenseChecker mChecker;
    // A handler on the UI thread.
    private Handler mHandler;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
        setContentView(R.layout.main);

        mStatusText = (TextView) findViewById(R.id.status_text);
        mCheckLicenseButton = (Button) findViewById(R.id.check_license_button);
        mCheckLicenseButton.setOnClickListener(new View.OnClickListener() {
            public void onClick(View view) {
                doCheck();
            }
        });

        mHandler = new Handler();

        // Try to use more data here. ANDROID_ID is a single point of attack.
        String deviceId = Secure.getString(getContentResolver(), Secure.ANDROID_ID);

        // Library calls this when it's done.
        mLicenseCheckerCallback = new MyLicenseCheckerCallback();
        // Construct the LicenseChecker with a policy.
        mChecker = new LicenseChecker(
            this, new ServerManagedPolicy(this,
                new AESObfuscator(SALT, getPackageName(), deviceId)),
            BASE64_PUBLIC_KEY);
        doCheck();
    }

    protected Dialog onCreateDialog(int id) {
        final boolean bRetry = id == 1;
        return new AlertDialog.Builder(this)
            .setTitle(R.string.unlicensed_dialog_title)
            .setMessage(bRetry ? R.string.unlicensed_dialog_retry_body : R.string.unlicensed_dialog_body)
            .setPositiveButton(bRetry ? R.string.retry_button : R.string.buy_button, new DialogInterface.OnClickListener() {
                boolean mRetry = bRetry;
                public void onClick(DialogInterface dialog, int which) {
                    if ( mRetry ) {
                        doCheck();
                    } else {
                        Intent marketIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(
                                "http://market.android.com/details?id=" + getPackageName()));
                            startActivity(marketIntent);                        
                    }
                }
            })
            .setNegativeButton(R.string.quit_button, new DialogInterface.OnClickListener() {
                public void onClick(DialogInterface dialog, int which) {
                    finish();
                }
            }).create();
    }

    private void doCheck() {
        mCheckLicenseButton.setEnabled(false);
        setProgressBarIndeterminateVisibility(true);
        mStatusText.setText(R.string.checking_license);
        mChecker.checkAccess(mLicenseCheckerCallback);
    }

    private void displayResult(final String result) {
        mHandler.post(new Runnable() {
            public void run() {
                mStatusText.setText(result);
                setProgressBarIndeterminateVisibility(false);
                mCheckLicenseButton.setEnabled(true);
            }
        });
    }

    private void displayDialog(final boolean showRetry) {
        mHandler.post(new Runnable() {
            public void run() {
                setProgressBarIndeterminateVisibility(false);
                showDialog(showRetry ? 1 : 0);
                mCheckLicenseButton.setEnabled(true);
            }
        });
    }    

    private class MyLicenseCheckerCallback implements LicenseCheckerCallback {
        public void allow(int policyReason) {
            if (isFinishing()) {
                // Don't update UI if Activity is finishing.
                return;
            }
            // Should allow user access.
            displayResult(getString(R.string.allow));
        }

        public void dontAllow(int policyReason) {
            if (isFinishing()) {
                // Don't update UI if Activity is finishing.
                return;
            }
            displayResult(getString(R.string.dont_allow));
            // Should not allow access. In most cases, the app should assume
            // the user has access unless it encounters this. If it does,
            // the app should inform the user of their unlicensed ways
            // and then either shut down the app or limit the user to a
            // restricted set of features.
            // In this example, we show a dialog that takes the user to Market.
            // If the reason for the lack of license is that the service is
            // unavailable or there is another problem, we display a
            // retry button on the dialog and a different message.
            displayDialog(policyReason == Policy.RETRY);
        }

        public void applicationError(int errorCode) {
            if (isFinishing()) {
                // Don't update UI if Activity is finishing.
                return;
            }
            String result = String.format(getString(R.string.application_error), errorCode);
            displayResult(result);
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        mChecker.onDestroy();
    }

}

但不幸的是,应用程序在开始时崩溃并出现错误

10-03 01:10:20.309: E/AndroidRuntime(2145): FATAL EXCEPTION: main
10-03 01:10:20.309: E/AndroidRuntime(2145): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.android.market.licensing/com.example.android.market.licensing.MainActivity}: java.lang.IllegalArgumentException: java.security.spec.InvalidKeySpecException: java.io.IOException: corrupted stream - out of bounds length found
10-03 01:10:20.309: E/AndroidRuntime(2145):     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1651)
10-03 01:10:20.309: E/AndroidRuntime(2145):     at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1667)
10-03 01:10:20.309: E/AndroidRuntime(2145):     at android.app.ActivityThread.access$1500(ActivityThread.java:117)
10-03 01:10:20.309: E/AndroidRuntime(2145):     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:935)
10-03 01:10:20.309: E/AndroidRuntime(2145):     at android.os.Handler.dispatchMessage(Handler.java:99)
10-03 01:10:20.309: E/AndroidRuntime(2145):     at android.os.Looper.loop(Looper.java:130)
10-03 01:10:20.309: E/AndroidRuntime(2145):     at android.app.ActivityThread.main(ActivityThread.java:3687)
10-03 01:10:20.309: E/AndroidRuntime(2145):     at java.lang.reflect.Method.invokeNative(Native Method)
10-03 01:10:20.309: E/AndroidRuntime(2145):     at java.lang.reflect.Method.invoke(Method.java:507)
10-03 01:10:20.309: E/AndroidRuntime(2145):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:867)
10-03 01:10:20.309: E/AndroidRuntime(2145):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:625)
10-03 01:10:20.309: E/AndroidRuntime(2145):     at dalvik.system.NativeStart.main(Native Method)
10-03 01:10:20.309: E/AndroidRuntime(2145): Caused by: java.lang.IllegalArgumentException: java.security.spec.InvalidKeySpecException: java.io.IOException: corrupted stream - out of bounds length found
10-03 01:10:20.309: E/AndroidRuntime(2145):     at com.google.android.vending.licensing.LicenseChecker.generatePublicKey(LicenseChecker.java:121)
10-03 01:10:20.309: E/AndroidRuntime(2145):     at com.google.android.vending.licensing.LicenseChecker.<init>(LicenseChecker.java:92)
10-03 01:10:20.309: E/AndroidRuntime(2145):     at com.example.android.market.licensing.MainActivity.onCreate(MainActivity.java:100)
10-03 01:10:20.309: E/AndroidRuntime(2145):     at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047)
10-03 01:10:20.309: E/AndroidRuntime(2145):     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1615)
10-03 01:10:20.309: E/AndroidRuntime(2145):     ... 11 more
10-03 01:10:20.309: E/AndroidRuntime(2145): Caused by: java.security.spec.InvalidKeySpecException: java.io.IOException: corrupted stream - out of bounds length found
10-03 01:10:20.309: E/AndroidRuntime(2145):     at org.bouncycastle.jce.provider.JDKKeyFactory.engineGeneratePublic(JDKKeyFactory.java:92)
10-03 01:10:20.309: E/AndroidRuntime(2145):     at org.bouncycastle.jce.provider.JDKKeyFactory$RSA.engineGeneratePublic(JDKKeyFactory.java:396)
10-03 01:10:20.309: E/AndroidRuntime(2145):     at java.security.KeyFactory.generatePublic(KeyFactory.java:177)
10-03 01:10:20.309: E/AndroidRuntime(2145):     at com.google.android.vending.licensing.LicenseChecker.generatePublicKey(LicenseChecker.java:112)

怎么了?

在行

private static final String BASE64_PUBLIC_KEY = "mykeywithoutspaces";

我已经设置了我的真实公钥

4

1 回答 1

7

我在 Google 帐户上编辑了一些个人资料信息后,Google Developers 控制台上的密钥发生了变化。

我已经更新了密钥,现在一切正常。

于 2012-10-03T01:01:41.610 回答