14

在此上下文中的目的是防止在排行榜中报告虚假的高分(我的应用是游戏)。这发生在 Flappy Birds - 请参阅此链接 - http://www.androidpit.com/forum/589832/flappy-bird-high-score-cheat-set-your-own-high-score

由于 root 用户可以用他的手机做任何他想做的事情,我想其他的解决方法都不会起作用,唯一的解决方案是阻止 root 用户安装应用程序。我对吗?有没有办法做到这一点?

PS:我的游戏并不总是需要互联网连接,因此当它发生在另一台服务器上时报告分数是不可行的。只有当互联网连接可用时,才会向排行榜报告高分。

4

5 回答 5

25

我有类似的要求。我无法实现该应用程序不应该安装在有根设备上,但我使用了一种解决方法:

  • 检查您的设备是否植根于您的活动的onResume.
  • 如果它已root,只需向他显示警报“此设备已root。您无法使用此应用程序。”,然后退出应用程序。

例子:

@Override
protected void onResume() {
    // TODO Auto-generated method stub
    super.onResume();
    if(new DeviceUtils().isDeviceRooted(getApplicationContext())){
        showAlertDialogAndExitApp("This device is rooted. You can't use this app.");
    }
}


public void showAlertDialogAndExitApp(String message) {

    AlertDialog alertDialog = new AlertDialog.Builder(MainActivity.this).create();
    alertDialog.setTitle("Alert");
    alertDialog.setMessage(message);
    alertDialog.setButton(AlertDialog.BUTTON_NEUTRAL, "OK",
            new DialogInterface.OnClickListener() {
                public void onClick(DialogInterface dialog, int which) {
                    dialog.dismiss();
                    Intent intent = new Intent(Intent.ACTION_MAIN);
                    intent.addCategory(Intent.CATEGORY_HOME);
                    intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                    startActivity(intent);
                    finish();
                }
            });

    alertDialog.show();
}

DeviceUtis.java是一个实用程序类,如果设备被植根,则返回。

public class DeviceUtils {

    public Boolean isDeviceRooted(Context context){
        boolean isRooted = isrooted1() || isrooted2();
        return isRooted;
    }

    private boolean isrooted1() {

        File file = new File("/system/app/Superuser.apk");
        if (file.exists()) {
            return true;
        }
        return false;
    }

    // try executing commands
    private boolean isrooted2() {
        return canExecuteCommand("/system/xbin/which su")
                || canExecuteCommand("/system/bin/which su")
                || canExecuteCommand("which su");
    }
}

我们使用了 5 种方法进行测试,我这里只展示了 2 种。你可以使用任何你认为好的方法。

希望这可以帮助。

PS:我已将此调用放在所有活动中onResume,因为用户(意图黑客)可以安装应用程序,导航到其他活动,然后是根设备。

于 2014-12-18T06:45:35.000 回答
6
private static boolean canExecuteCommand(String command) {
        boolean executedSuccesfully;
        try {
            Runtime.getRuntime().exec(command);
            executedSuccesfully = true;
        } catch (Exception e) {
            executedSuccesfully = false;
        }

        return executedSuccesfully;
    }
于 2018-04-25T05:57:32.720 回答
3

没有必要阻止具有根电话的用户,因为这是正常的用户行为。那么,如果您在游戏中没有在线连接以获取高分、应用内购买等,您会担心什么样的危险或损害?

玩家想以欺骗方式到达最后一关或本地(!)排行榜的顶部?伤害在哪里?

通过阻止您的游戏在有根设备上运行,您只会排斥应用程序的合法用户。

编辑:

使用云保存服务保存玩家的高分。如果离线,它将被加密并存储在设备上。下次在线时,您会读取高分并将其发送到播放服务。播放服务提供了您可能还需要的反盗版功能。

于 2014-12-18T08:03:38.397 回答
2

使用 Kotlin 扩展,您可以轻松检查设备是否已植根。下面是可以帮助你的代码

DeviceUtils.kt

object DeviceUtils {
    fun isDeviceRooted(context: Context?): Boolean {
        return isRooted1 || isRooted2
    }

    private val isRooted1: Boolean
        get() {
            val file = File("/system/app/Superuser.apk")
            return file.exists()
        }

    // try executing commands
    private val isRooted2: Boolean
        get() = (canExecuteCommand("/system/xbin/which su")
                || canExecuteCommand("/system/bin/which su")
                || canExecuteCommand("which su"))

    private fun canExecuteCommand(command: String): Boolean {
        return try {
            Runtime.getRuntime().exec(command)
            true
        } catch (e: Exception) {
            false
        }
    }
}

Extention.kt

fun Activity.checkDeviceRoot(): Boolean {
    return if (DeviceUtils.isDeviceRooted(this)) {
        AlertDialog.Builder(this)
                .setMessage("Your device is rooted. you can not use this app into rooted device.")
                .setCancelable(false)
                .setPositiveButton(R.string.alert_ok) { _, _ ->
                    exitProcess(0)
                }.show()
        true
    } else {
        false
    }
}

如何使用这个扩展:

class MyActivity : Activity{
    ...
    override 
    fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_splash)

        if(checkDeviceRoot())
            return
        ....
        ....
    }
}

希望这个答案能帮到你。

于 2019-12-13T05:35:52.073 回答
0

我们在安全网排除的 Playstore 控制台中有一个选项,我们可以使用它来防止应用程序出现在 Playstore 上以便在有根设备上下载。 Google play 服务

Safety Net Attestation API,我们可以通过它评估设备并确定它是否被 root/篡改。 谁想处理root设备,请看我的回答:https ://stackoverflow.com/a/58304556/3908895


于 2019-10-10T05:29:08.783 回答