2013-06-12 10 views
5

ich einen Alarm Dialog über AlertDialogManager Klasse zu einer non-activity Klasse DeviceAdminReceiverSample ‚s Methode onDisabled, zeigen wollen, aber wenn ich alertDialog über diese Methode aufrufen, erzeugt es Fehler mit Text nachanzeigen Dialog Alarm aus einer nicht-Aktivitätsklasse in android

Fehler

06-12 12:01:19.923: E/AndroidRuntime(468): FATAL EXCEPTION: main 
06-12 12:01:19.923: E/AndroidRuntime(468): java.lang.RuntimeException: Unable to start   
receiver com.android.remotewipedata.DeviceAdminReceiverSample: 
android.view.WindowManager$BadTokenException: Unable to add window -- token null is not 
for an application 

ich weiß, das Problem mit context Sache ist, aber ich weiß nicht, was dort zu setzen, so dass es funktioniert, habe ich versucht, this, getApplicationContext(), aber alles vergebens. Mein Code für beide Klassen unter

AlertDialogManager

public class AlertDialogManager { 

public void showAlertDialog(Context context, String title, String message, 
     Boolean status) { 
    final AlertDialog alertDialog = new AlertDialog.Builder(context).create(); 
    alertDialog.setTitle(title); 
    alertDialog.setMessage(message); 

    if (status != null) 
     alertDialog.setButton("OK", new DialogInterface.OnClickListener() { 
      public void onClick(DialogInterface dialog, int which) { 
       alertDialog.dismiss(); 
      } 
     }); 
    alertDialog.show(); 
} 

}

DeviceAdminReceiverSample

public class DeviceAdminReceiverSample extends DeviceAdminReceiver { 
static final String TAG = "DeviceAdminReceiver"; 
AlertDialogManager alert = new AlertDialogManager(); 

/** Called when this application is no longer the device administrator. */ 
@Override 
public void onDisabled(Context context, Intent intent) { 
    super.onDisabled(context, intent); 
    Toast.makeText(context, R.string.device_admin_disabled, 
      Toast.LENGTH_LONG).show(); 
    // intent.putExtra("dialogMessage", "Device admin has been disabled"); 
    // intent.setClass(context, DialogActivity.class); 
    // intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 
    // context.startActivity(intent); 
    alert.showAlertDialog(context, "Alert", 
      "Device admin has been disabled", true); 
} 
+0

eine DialogActivity dafür erstellen. –

+0

Verwenden Sie das Aktivitätsobjekt anstelle des Kontextobjekts. – Ajay

Antwort

10

Das Problem ist 'You can show AlertDialogs from Activity only'. Dies ist kein Problem des Kontextes.

Obwohl dies keine gute Idee, um zu zeigen, Dialog vom Empfänger (besser ist Benachrichtigung zu verwenden), aber wenn Sie wollen, so können Sie eine Activity as dialog and show

1

Aufruf dieser Methode in Aktivitätsklasse erstellen

public static void showAlert(Activity activity, String message) { 

     TextView title = new TextView(activity); 
     title.setText("Title"); 
     title.setPadding(10, 10, 10, 10); 
     title.setGravity(Gravity.CENTER); 
     title.setTextColor(Color.WHITE); 
     title.setTextSize(20); 

     AlertDialog.Builder builder = new AlertDialog.Builder(activity); 
     // builder.setTitle("Title"); 
     builder.setCustomTitle(title); 
     // builder.setIcon(R.drawable.alert_36); 

     builder.setMessage(message); 

     builder.setCancelable(false); 
     builder.setNegativeButton("OK", new DialogInterface.OnClickListener() { 
      public void onClick(DialogInterface dialog, int id) { 
       dialog.cancel(); 

      } 

     }); 

     AlertDialog alert = builder.create(); 
     alert.show(); 
    } 
+0

Ja, es ist richtig – Ajay

+0

Dank ist dieses Konzept mir sehr helfen, –

0

Als AJAY vorgeschlagen, der beste Weg ist mit der ‚Aktivität‘ im Parameter zu arbeiten, anstatt den ‚Kontext‘ zu verwenden.

Fragen Sie in Ihrer persönlichen Klasse einfach nach der Aktivität in ihrem Konstruktor als obligatorischem Parameter => public void constructorOfTheClass (Aktivitätsaktivität) {...}.

Wenn Sie den Konstruktor in Ihrer Aktivität aufrufen, geben Sie einfach diesen Parameter und Sie werden in der Lage direkt mit ihm in der Klasse zu arbeiten.

Dann können Sie diese Aktivitätsinformationen in Ihrer AlertDialog-Methode innerhalb Ihrer Klasse verwenden, da SUNIL festgestellt hat, dass Sie in der gewünschten Aktivität korrekt aufgefordert werden.

Hoffe, es hilft ... und sicher sein, es funktioniert! ; O)

31

Nur diese hinzufügen, bevor Ihr alertDialog.show();

alertDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT); 

und verwenden diese Berechtigung:

<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" /> 
+0

Danke, es funktioniert. Ihre Antwort sollte stimmen. – VAdaihiep

+1

Sehr gutes Ergebnis. Vielen Dank. Hinzufügen zu dieser Lösung gemäß der Dokumentation 'Ermöglicht einer Anwendung das Öffnen von Fenstern mit dem Typ TYPE_SYSTEM_ALERT, der über allen anderen Anwendungen angezeigt wird. Sehr wenige Anwendungen sollten diese Berechtigung verwenden; Diese Fenster sind für die Interaktion auf Systemebene mit dem Benutzer gedacht. Daher müssen wir bei der Verwendung dieser Lösung auch vorsichtig sein. –

+0

Hatte das gleiche Problem, löste es auf diese Weise. Danke – darthvading

3

Wenn Sie immer die aktuelle Aktivität von überall in der App bekommen möchten, können Sie ein registrieren ActivityLifecycleCallback auf Ihrer Anwendungsinstanz.

Hier ist eine nicht getestete Implementierung, die Sie näher kommen könnten.

public class TestApp extends Application { 

    private WeakReference<Activity> mActivity = null; 

    @Override 
    public void onCreate() { 
     super.onCreate(); 
     registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacks() { 
      @Override 
      public void onActivityCreated(Activity activity, Bundle savedInstanceState) { 
       mActivity = new WeakReference<Activity>(activity); 
      } 

      @Override 
      public void onActivityDestroyed(Activity activity) { 
       mActivity.clear(); 
      } 

      /** Unused implementation **/ 
      @Override 
      public void onActivityStarted(Activity activity) {} 

      @Override 
      public void onActivityResumed(Activity activity) {} 
      @Override 
      public void onActivityPaused(Activity activity) {} 

      @Override 
      public void onActivityStopped(Activity activity) {} 

      @Override 
      public void onActivitySaveInstanceState(Activity activity, Bundle outState) {} 
     }); 
    } 

    public Activity getCurrentActivity() { 
     return mActivity.get(); 
    } 

} 

Dann ist diese in Ihrer App verwenden Sie so etwas Anruf tun würde ...

Activity activity = ((TestApp)getApplicationContext()).getCurrentActivity(); 

Die Vorteile sind Sie immer den Überblick über Ihre aktuelle Aktivität halten kann, aber es ist ein wenig zu viel des Guten um Dialoge nur innerhalb der Aktivität zu bearbeiten.

+0

Funktioniert mit einem Singleton WebView und einem MutableContextWrapper. – norbDEV

0

Hier ist eine schnelle Methode, um diese Aufgabe richtig durchführen, die den Job für mich getan hat. Im Grunde würden Sie nur einen neuen Thread erstellen.


  1. Deklarieren Sie eine öffentliche und statische Variable mit einem Typ, der die ursprünglichen Aktivitätsklasse entspricht.

    public static Activity1 activity;

Activity1 ist die Klasse, die Variable in residiert.


  1. Nach dem Aufruf der Methode onCreate();, setzen Sie die Variable gleich zu sein zum Kontext der Aktivität, sonst bekannt als dieser.

Beispiel:

@Override 
    protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    activity = this; 
} 


3. Da wir nun den Rahmen der Tätigkeit haben, können wir es verwenden, indem Sie mit der runOnUiThread(); Methode innerhalb der Funktion eine Funktion mit einem Alarm-Dialog zu schaffen Das wird den Alarmdialog aufrufen. Wir würden ein new Runnable() für die runnable Aktion für runOnUiThread(); erforderlich verwenden, und den Alarm-Dialog tatsächlich offen ist, würden wir die Durchlauffunktion eines runnable Elements außer Kraft setzen und dort den Code für den Alarm-Dialog setzen.

Beispiel Funktion:

public static void exampleDialog(){ 
Activity1.activity.runOnUiThread(new Runnable){ 
@Override 
    public void run(){ 
    //alert dialog code goes here. For the context, use the activity variable from Activity1. 
     } 
    } 
} 

this helps :)