如何防止Root Android手机安装我的应用程序?

时间:2014-12-18 05:13:33

标签: android mobile anti-cheat

此背景下的目的是防止在LeaderBoard中报告错误的高分(我的应用程序是游戏)。 Flappy Birds发生了这种情况 - 请参阅此链接 - http://www.androidpit.com/forum/589832/flappy-bird-high-score-cheat-set-your-own-high-score

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

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

5 个答案:

答案 0 :(得分:15)

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

  • 检查您的设备是否植根于您的活动onResume
  • 如果它有根,只要告诉他“此设备已植根。您无法使用此应用。”,并退出应用程序。

示例:

@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是一个Utility类,如果设备是否为root,则返回。

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中,因为用户(有黑客攻击)可以安装应用程序,导航到其他一些活动,然后导入根设备。

答案 1 :(得分:4)

无需像普通用户行为那样阻止使用root用户的用户。那么,如果您在游戏中没有高分,应用内购买等的在线连接,您会担心会有什么样的危险或损害?

玩家想欺骗她的方式到最后一级或本地(!)排行榜的顶部?损坏在哪里?

通过阻止您的游戏在root设备上运行,您只需取消应用程序的合法用户即可获得。

编辑:

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

答案 2 :(得分:2)

private static boolean canExecuteCommand(String command) {
        boolean executedSuccesfully;
        try {
            Runtime.getRuntime().exec(command);
            executedSuccesfully = true;
        } catch (Exception e) {
            executedSuccesfully = false;
        }

        return executedSuccesfully;
    }

答案 3 :(得分:0)

我们在Playstore控制台中提供了一个 SafetyNet排除选项,我们可以使用该选项来阻止应用程序出现在Playstore上以便在有根设备上下载。

我们提供了 Google Play服务 Safety Net Attestation API ,通过它我们可以评估设备并确定其是否被扎根/被篡改。

对于想要处理植根设备的用户,请仔细阅读我的回答:https://stackoverflow.com/a/58304556/3908895

答案 4 :(得分:0)

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

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
        ....
        ....
    }
}

希望这个答案会帮助您。