android:protectionLevel="dangerous" />
<uses-permission android:name="android.permission.ACCESS_SUPERUSER" />
+ <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<application
android:name=".SuApplication"
<receiver
android:name=".SuReceiver"
android:permission="android.permission.REPORT_SUPERUSER" />
+
+ <receiver android:name=".SuCheckerReceiver" >
+ <intent-filter>
+ <action android:name="android.intent.action.BOOT_COMPLETED" />
+ <!-- <action android:name="internal.superuser.BOOT_TEST" /> -->
+ </intent-filter>
+ </receiver>
</application>
</manifest>
\ No newline at end of file
<string name="checking_superuser">Checking Superuser...</string>
<string name="install_error">There was an error installing Superuser. Please send a log of the error to the developer.</string>
<string name="install_success">Installation of Superuser was successful.</string>
+ <string name="su_binary_outdated">The su binary is out of date.</string>
</resources>
package com.koushikdutta.superuser;
import java.io.File;
-import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.os.Bundle;
-import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.MenuItem.OnMenuItemClickListener;
-import com.koushikdutta.superuser.util.Settings;
import com.koushikdutta.superuser.util.StreamUtility;
+import com.koushikdutta.superuser.util.SuHelper;
import com.koushikdutta.widgets.BetterListActivity;
public class MainActivity extends BetterListActivity {
p.getOutputStream().close();
if (p.waitFor() != 0)
throw new Exception("non zero result");
- checkSu();
+ SuHelper.checkSu(MainActivity.this);
}
catch (Exception ex) {
_error = true;
});
builder.create().show();
}
-
- void checkSu() throws Exception {
- Process p = Runtime.getRuntime().exec("su -v");
- String result = Settings.readToEnd(p.getInputStream());
- Log.i("Superuser", "Result: " + result);
- if (0 != p.waitFor())
- throw new Exception("non zero result");
- if (result == null)
- throw new Exception("no data");
- if (!result.contains(getPackageName()))
- throw new Exception("unknown su");
- // TODO: upgrades herp derp
- }
@Override
protected void onCreate(Bundle savedInstanceState) {
public void run() {
boolean error = false;
try {
- checkSu();
+ SuHelper.checkSu(MainActivity.this);
}
catch (Exception e) {
e.printStackTrace();
--- /dev/null
+package com.koushikdutta.superuser;
+
+import android.app.NotificationManager;
+import android.app.PendingIntent;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Handler;
+import android.support.v4.app.NotificationCompat;
+import android.util.Log;
+
+import com.koushikdutta.superuser.util.Settings;
+import com.koushikdutta.superuser.util.SuHelper;
+
+public class SuCheckerReceiver extends BroadcastReceiver {
+ public void doNotification(Context context) {
+ NotificationCompat.Builder builder = new NotificationCompat.Builder(context);
+ builder.setTicker(context.getString(R.string.install_superuser));
+ builder.setContentTitle(context.getString(R.string.install_superuser));
+ builder.setSmallIcon(R.drawable.ic_stat_notification);
+ builder.setWhen(0);
+ builder.setContentText(context.getString(R.string.su_binary_outdated));
+ builder.setAutoCancel(true);
+ PendingIntent launch = PendingIntent.getActivity(context, 0, new Intent(context, MainActivity.class), 0);
+ Intent delIntent = new Intent(context, SuCheckerReceiver.class);
+ delIntent.setAction(ACTION_DELETED);
+ PendingIntent delete = PendingIntent.getBroadcast(context, 0, delIntent, 0);
+ builder.setDeleteIntent(delete);
+ builder.setContentIntent(launch);
+ NotificationManager nm = (NotificationManager)context.getSystemService(Context.NOTIFICATION_SERVICE);
+ nm.notify(10000, builder.build());
+ }
+
+ private static final String ACTION_DELETED = "internal.superuser.ACTION_CHECK_DELETED";
+
+ @Override
+ public void onReceive(final Context context, Intent intent) {
+ if (intent == null)
+ return;
+
+
+ if (Intent.ACTION_BOOT_COMPLETED.equals(intent.getAction()) || "internal.superuser.BOOT_TEST".equals(intent.getAction())) {
+ // if the user deleted the notification in the past, don't bother them again for a while
+ int counter = Settings.getCheckSuQuietCounter(context);
+ if (counter > 0) {
+ Log.i("Superuser", "Not bothering user... su counter set.");
+ counter--;
+ Settings.setCheckSuQuietCounter(context, counter);
+ return;
+ }
+
+ final Handler handler = new Handler();
+ new Thread() {
+ public void run() {
+ try {
+ SuHelper.checkSu(context);
+ }
+ catch (Exception ex) {
+ handler.post(new Runnable() {
+ @Override
+ public void run() {
+ doNotification(context);
+ }
+ });
+ }
+ };
+ }.start();
+ }
+ else if (ACTION_DELETED.equals(intent.getAction())) {
+ // notification deleted? bother the user in 3 reboots.
+ Log.i("Superuser", "Will not bother the user in the future... su counter set.");
+ Settings.setCheckSuQuietCounter(context, 3);
+ }
+ }
+}
catch (Exception ex) {
}
}
+
+ private static final String CHECK_SU_QUIET = "check_su_quiet";
+ public static final int getCheckSuQuietCounter(Context context) {
+ return getInt(context, CHECK_SU_QUIET, 0);
+ }
+
+ public static final void setCheckSuQuietCounter(Context context, int counter) {
+ setInt(context, CHECK_SU_QUIET, counter);
+ }
}
--- /dev/null
+package com.koushikdutta.superuser.util;
+
+import android.content.Context;
+import android.util.Log;
+
+public class SuHelper {
+
+ public static void checkSu(Context context) throws Exception {
+ Process p = Runtime.getRuntime().exec("su -v");
+ String result = Settings.readToEnd(p.getInputStream());
+ Log.i("Superuser", "Result: " + result);
+ if (0 != p.waitFor())
+ throw new Exception("non zero result");
+ if (result == null)
+ throw new Exception("no data");
+ if (!result.contains(context.getPackageName()))
+ throw new Exception("unknown su");
+ // TODO: upgrades herp derp
+ }
+
+}