2013-06-12 11 views
5

chcę pokazać się okno dialogowe z ostrzeżeniem poprzez AlertDialogManager klasy do non-activity klasy DeviceAdminReceiverSample „s metody onDisabled, ale gdy zgłoszę alertDialog za pośrednictwem tej metody generuje błąd z następującym tekstemPokaż alert dialogowe z klasy zakaz działalności w Android

błąd

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 

wiem, że problem jest z context rzeczy, ale nie wiem, co tam umieścić tak, że działa, próbowałem this, getApplicationContext() ale wszystko próżne. Mój kod dla obu klas jest poniżej

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

stworzyć DialogActivity do tego. –

+0

Użyj obiektu działania zamiast obiektu kontekstowego. – Ajay

Odpowiedz

10

Problemem jest 'You can show AlertDialogs from Activity only'. To nie jest kwestia kontekstu.

Chociaż nie jest to dobry pomysł, aby wyświetlić okno dialogowe z odbiornika (lepiej jest korzystać z powiadomień), ale jeśli chcesz to zrobić, dzięki czemu można stworzyć Activity as dialog and show

1

wywołanie tej metody w klasie działalności

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

Tak, jest to poprawne – Ajay

+0

Dzięki, ta koncepcja bardzo mi pomogła, –

0

Zgodnie z sugestią AJAY, najlepszym sposobem jest praca z "Aktywnością" w parametrze zamiast używania "kontekstu".

W swojej klasie osobistej po prostu poproś o działanie w swoim konstruktorze jako parametr obowiązkowy => public void constructorOfTheClass (Activity activity) {...}.

Po wywołaniu konstruktora w swojej działalności, po prostu wskaż ten parametr, a będziesz mógł z nim pracować bezpośrednio w klasie.

Następnie możesz użyć tej informacji o "aktywności" w swojej metodzie AlertDialog w swojej klasie, ponieważ SUNIL zauważył, że został prawidłowo zapytany o pożądaną aktywność.

Mam nadzieję, że pomoże ... i będzie działać! ; O)

31

Wystarczy dodać ten przed alertDialog.show();

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

i korzystać z tego uprawnienia:

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

Dzięki, działa. Twoja odpowiedź powinna zostać poddana pod głosowanie. – VAdaihiep

+1

Bardzo dobre odkrycie. Dziękuję Ci. Dodanie do tego rozwiązania, zgodnie z dokumentacją 'Zezwala aplikacji na otwieranie okien przy użyciu typu TYPE_SYSTEM_ALERT, wyświetlanego na górze wszystkich innych aplikacji. Bardzo niewiele aplikacji powinno korzystać z tego pozwolenia; Okna te są przeznaczone do interakcji na poziomie systemu z użytkownikiem. Dlatego też musimy zachować ostrożność podczas korzystania z tego rozwiązania. –

+0

Miał ten sam problem, rozwiązany za pomocą tej metody. Dzięki – darthvading

3

Jeśli zawsze chcesz uzyskać bieżącej działalności z dowolnego miejsca w aplikacji Można zarejestrować ActivityLifecycleCallback w instancji aplikacji.

Oto niesprawdzona implementacja, która może Cię przybliżyć.

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

} 

Następnie aby skorzystać z tej całej aplikacji byś zrobił jakieś połączenie takiego ...

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

Zalety to zawsze można śledzić bieżącej działalności, jednak jej zbyt przesadą do po prostu obsługi Dialogów z działania.

+0

Działa z pojedynczym WebView i MutableContextWrapper. – norbDEV

0

Oto szybka metoda prawidłowego wykonania tego zadania, które wykonało zadanie dla mnie. Zasadniczo wystarczy utworzyć nowy wątek.


  1. Zadeklaruj zmienną publiczną i statyczną z typem, który pasuje do oryginalnej klasy aktywności.

    public static Activity1 activity;

Activity1 jest klasa, która znajduje się zmienna w.


  1. Po wywołaniu metody onCreate(); ustaw zmienną być równa w kontekście działania, znanego pod nazwą , to jest.

Przykład:

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


3. Od teraz mamy kontekst działalności, możemy używać go do tworzenia funkcji z okna alertu za pomocą metody runOnUiThread(); wewnątrz funkcji który wywoła okno dialogowe alertu. Użylibyśmy new Runnable() dla działającej czynności wymaganej dla runOnUiThread();, i aby okno dialogowe alertu było rzeczywiście otwarte, zastąpilibyśmy funkcję run elementu uruchamialnego i umieściliśmy tam kod dla okna dialogowego alertu.

przykład funkcja:

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

Nadzieja to pomaga :)

Powiązane problemy