2013-06-12 10 views
5

voglio mostrare una finestra di avviso via AlertDialogManager classe per una classe s DeviceAdminReceiverSample' metodo onDisablednon-activity, ma ogni volta che io chiamo alertDialog attraverso quel metodo si genera l'errore con il seguente testoMostra finestra di avviso da una classe non-attività in Android

errore

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 

so che il problema è con context cosa, ma non so cosa mettere lì in modo che il lavoro, ho provato this, getApplicationContext() ma tutto vano. Il mio codice per entrambe le categorie è inferiore

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

creare un DialogActivity per questo. –

+0

Utilizzare l'oggetto attività anziché l'oggetto contesto. – Ajay

risposta

10

Il problema è 'You can show AlertDialogs from Activity only'. Questo non è un problema di contesto.

Anche se questa non è una buona idea per mostrare dialogo dal ricevitore (migliore è quello di utilizzare la notifica), ma se si vuole fare in modo da poter creare un Activity as dialog and show

1

chiamata di questo metodo in classe di attività

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

Sì, è corretto – Ajay

+0

Grazie, questo concetto mi è di grande aiuto, –

0

Come suggerito AJAY, il modo migliore è quello di lavorare con il 'Activity' nel parametro invece di utilizzare il 'contesto'.

Nella classe personale, è sufficiente chiedere l'attività nel proprio costruttore come parametro obbligatorio => public void constructorOfTheClass (Activity activity) {...}.

Quando si chiama il costruttore nella propria attività, basta indicare questo parametro e si sarà in grado di lavorare direttamente all'interno della classe.

Quindi è possibile utilizzare queste informazioni "attività" nel proprio metodo AlertDialog all'interno della classe, poiché SUNIL ha rilevato che deve essere visualizzato correttamente nell'attività desiderata.

Spero che aiuti ... e si assicuri che funzionerà! ; O)

31

Basta aggiungere questa prima alertDialog.show();

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

e utilizzare questa autorizzazione:

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

Grazie, funziona. La tua risposta dovrebbe essere votata. – VAdaihiep

+1

Molto bello da trovare. Grazie. Aggiungendo a questa soluzione, come da documentazione 'Consente a un'applicazione di aprire Windows usando il tipo TYPE_SYSTEM_ALERT, mostrato sopra a tutte le altre applicazioni. Pochissime applicazioni dovrebbero usare questa autorizzazione; queste finestre sono intese per l'interazione a livello di sistema con l'utente. Quindi, dobbiamo anche fare attenzione durante l'utilizzo di questa soluzione. –

+0

Aveva lo stesso problema, risolto in questo modo. Grazie – darthvading

3

Se si vuole sempre ottenere l'attività corrente da qualsiasi punto della applicazione è possibile registrare un ActivityLifecycleCallback sull'istanza dell'applicazione.

Ecco un'implementazione non testata che potrebbe avvicinarti.

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(); 
    } 

} 

quindi di utilizzare questo per tutta la vostra applicazione si dovrebbe fare un po 'chiamata in questo modo ...

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

I vantaggi sono che si può sempre tenere traccia della vostra attività in corso, tuttavia è un po' troppo eccessivo per la semplice gestione dei dialoghi dall'interno dell'attività.

+0

Funziona con un singleton WebView e un MutableContextWrapper. – norbDEV

0

Ecco un metodo rapido per eseguire correttamente questa attività che ha svolto il lavoro per me. Fondamentalmente, quello che dovresti fare è creare un nuovo thread.


  1. dichiarare una variabile pubblica e statico con un tipo che corrisponde alla classe attività originaria.

    public static Activity1 activity;

Activity1 è la classe che la variabile risiede.


  1. Dopo aver chiamato il metodo onCreate();, impostare la variabile per essere uguale al contesto dell'attività, altrimenti noto come questo.

Esempio:

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


3. Da ora abbiamo il contesto dell'attività, si può usare per creare una funzione con una finestra di avviso utilizzando il metodo runOnUiThread(); all'interno della funzione che chiamerà la finestra di avviso. Useremo un new Runnable() per l'azione eseguibile richiesta per runOnUiThread(); e per fare in modo che la finestra di avviso sia effettivamente aperta, sostituiremo la funzione di esecuzione di un elemento eseguibile e inseriremo il codice per la finestra di avviso.

funzione Esempio:

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

Spero che questo aiuti :)

Problemi correlati