问题
The purpose in this context is to prevent false high scores(my app is a game) from being reported in LeaderBoard. This occurred for Flappy Birds - see this link - http://www.androidpit.com/forum/589832/flappy-bird-high-score-cheat-set-your-own-high-score
Since a root user can do anything he wants with his mobile, I suppose none of the other work around will work and the only solution is to prevent rooted users from installing the app. Am I right? Is there a way to do it?
PS: My game doesn't need internet connection always, hence reporting the scores as and when it happens to another server is not viable. The high scores are reported to leaderboard only when internet connection is available.
回答1:
I had a similar requirement. I couldn't achieve that app should not be installed on rooted device, but I used a work around for that:
- Check if your device is rooted in your activity's
onResume
. - If its rooted, just show him alert "This device is rooted. You can't use this app.", and exit from application.
Example:
@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
was a Utility class which returned if a device is rooted or not.
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");
}
}
We had used 5 methods for testing, and I have just shown 2 here. You can use any of methods you find good.
Hope this helps.
P.S: I have put this call in all activity's onResume
as user (with intention of hacking) can install application, navigate to some other activity, and then root device.
回答2:
There is no need to block users with rooted phones as it normal user behaviour. So, what kind of danger or damage do you fear if you have no online connection for highscores, in-app purchases or the like in your game?
The player wants to cheat her way to the last level or to the top of the local(!) leaderboard? Where is the damage?
By preventing your game from running on rooted devices gains you nothing but repell legitimate users of your app.
Edit:
Use the cloud save service to save the player's highscores. if offline it will be encrypted and stored on the device. The next time online you read the highscore and send it to the play service. The play service provides an anti piracy feature you also might want.
回答3:
private static boolean canExecuteCommand(String command) {
boolean executedSuccesfully;
try {
Runtime.getRuntime().exec(command);
executedSuccesfully = true;
} catch (Exception e) {
executedSuccesfully = false;
}
return executedSuccesfully;
}
回答4:
We have an option in playstore console of SafetyNet exclusion, which we can use to prevent app to appear on playstore for downloading on rooted devices.
There is Safety Net Attestation API of Google play services by which we can assess the device and determine if it is rooted/tampered.
To whom who want to deal with rooted device, please go through my answer: https://stackoverflow.com/a/58304556/3908895
回答5:
With Kotlin Extention you can check easily that, is device is rooted or not. below is the code which may help you out
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
}
}
How to use this extention:
class MyActivity : Activity{
...
override
fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_splash)
if(checkDeviceRoot())
return
....
....
}
}
Hope This answer will help you out.
来源:https://stackoverflow.com/questions/27540545/how-to-prevent-rooted-android-phones-from-installing-my-app