Недавно я добавил защиту Android от копирования LVL в свое приложение, и результаты были, мягко говоря, ошибочными.
Каждый тестовый ответ, который я установил вручную в консоли разработчика, работает так, как предполагалось. Однако, когда я устанавливаю «Отвечать нормально», здесь начинаются проблемы. В среду я впервые загрузил приложение, и вскоре после того, как оно появилось на рынке, оно, как и ожидалось, сообщило, что оно ЛИЦЕНЗИРОВАНО.
Однако вчера днем без какого-либо предупреждения мое приложение внезапно сообщает мне, что я НЕ_ЛИЦЕНЗИРОВАН. До этого момента я не вносил никаких изменений ни в консоль разработчика, ни в код. Обнаружив это, я немедленно удалил публикацию, пока не нашел решение. Я уже пробовал очищать кеш приложения и кеш Google Play.
Так что я не знаю, что я сделал не так здесь. Я установил собственное приложение на свой телефон через APK из Eclipse вместо того, чтобы покупать собственное приложение на рынке. Чтобы протестировать LVL в реальном времени, нужно ли мне покупать собственное приложение или достаточно загрузить его на страницу разработчика? Мой LVL-код — практически точная копия страницы примера, которую я сделал в версии, чтобы попытаться заставить ее работать перед дальнейшей оптимизацией. Я разместил его здесь с вырезкой некоторой идентифицируемой информации.
public class Main extends Activity {
private static final byte[] SALT = { <salt> };
private static final String B64 = "<base 64 key>";
private dbHelper db = new dbHelper(this);
private int requestCode;
LicenseCheckerCallback mLCC;
LicenseChecker mC;
Handler mH;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
checkL();
}
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == 1) {
startActivity(new Intent(Main.this, MainProfiler.class)); //callback for profile setup
finish();
}
}
protected void checkL() {
String a = Settings.Secure.getString(getContentResolver(), Settings.Secure.ANDROID_ID);
mH = new Handler();
mLCC = new settingsResolved();
mC = new LicenseChecker(
this,
new ServerManagedPolicy(this, new AESObfuscator(SALT, getPackageName(), a)),
B64);
mC.checkAccess(mLCC);
}
protected class settingsResolved implements LicenseCheckerCallback {
@Override
public void allow(int reason) {
//the application is licensed properly
if (isFinishing()) {
// Don't update UI if Activity is finishing.
return;
}
//authorize access
startFromCallback();
}
@Override
public void dontAllow(int reason) {
//the application is not licensed properly
Log.e("Main", "LVL Failed!");
if (isFinishing()) {
// Don't update UI if Activity is finishing.
return;
}
failFromCallback(reason);
}
@Override
public void applicationError(int errorCode) {
//an error occurred
Log.e("Main", "LVL Error!");
if (isFinishing()) {
// Don't update UI if Activity is finishing.
return;
}
errorFromCallback(errorCode);
}
}
private void startProcedure() {
if (db.getRunOnce()) { //this is the first run
Intent i = new Intent(Main.this, ProfileSetup.class);
i.putExtra("NewProfile", true);
startActivityForResult(i, requestCode);
} else { //this is not the first run
startActivity(new Intent(Main.this, MainProfiler.class));
finish();
}
}
private void failureState(int reason) {
AlertDialog.Builder adb = new AlertDialog.Builder(this);
adb.setTitle("LVL Error");
adb.setCancelable(false);
adb.setMessage(<license refused message>));
adb.setPositiveButton("Exit", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
finish();
}
});
if (reason != Policy.NOT_LICENSED) {// not NOT_LICENSED, meaning the error is not due to a licensing issue
adb.setNegativeButton("Check Again", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
checkL();
}
});
} else {
adb.setNegativeButton("Google Play", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Intent i = new Intent(Intent.ACTION_VIEW);
i.setData(Uri.parse("market://details?id=<package name>"));
startActivity(i);
finish();
}
});
}
adb.create().show();
}
private void applicationError(int errorCode) {
AlertDialog.Builder adb = new AlertDialog.Builder(this);
adb.setTitle("LVL Error");
adb.setCancelable(false);
adb.setMessage(<application error message>);
adb.setPositiveButton("Exit", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
finish();
}
});
adb.create().show();
}
private void startFromCallback() {
mH.post(new Runnable() {
public void run() {
Log.i("LVL", "License Pass!");
startProcedure();
}
});
}
private void failFromCallback(final int reason) {
mH.post(new Runnable() {
public void run() {
failureState(reason);
}
});
}
private void errorFromCallback(final int errorCode) {
mH.post(new Runnable() {
public void run() {
applicationError(errorCode);
}
});
}
@Override
protected void onDestroy() {
super.onDestroy();
if (mC != null) {
mC.onDestroy();
}
}
}