質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Android

Androidは、Google社が開発したスマートフォンやタブレットなど携帯端末向けのプラットフォームです。 カーネル・ミドルウェア・ユーザーインターフェイス・ウェブブラウザ・電話帳などのアプリケーションやソフトウェアをひとつにまとめて構成。 カーネル・ライブラリ・ランタイムはほとんどがC言語/C++、アプリケーションなどはJavaSEのサブセットとAndroid環境で書かれています。

Android Studio

Android Studioは、 Google社によって開発された、 Androidのネイティブアプリケーション開発に特化した統合開発ツールです。

Q&A

解決済

3回答

11135閲覧

androidのdialogの表示方法について

RNagamatsu

総合スコア13

Android

Androidは、Google社が開発したスマートフォンやタブレットなど携帯端末向けのプラットフォームです。 カーネル・ミドルウェア・ユーザーインターフェイス・ウェブブラウザ・電話帳などのアプリケーションやソフトウェアをひとつにまとめて構成。 カーネル・ライブラリ・ランタイムはほとんどがC言語/C++、アプリケーションなどはJavaSEのサブセットとAndroid環境で書かれています。

Android Studio

Android Studioは、 Google社によって開発された、 Androidのネイティブアプリケーション開発に特化した統合開発ツールです。

0グッド

0クリップ

投稿2017/05/10 14:15

編集2017/05/11 00:16

着信が入った時にダイアログを表示するアプリを作っていまして、素人ながらもいろいろなサイトを参考にしながらそれなりに形にはなっているのですが、ダイアログの表示でもう1か月以上滞っていて、ヒントだけでも頂けると助かります。

着信の状態を捕捉するクラス(PhoneReceiver.class)を下の様に作っていまして、着信が入ると

Java

1 AlertDialog.Builder builder = new AlertDialog.Builder(context); 2 builder.setMessage(R.string.dialog_message) 3 .setTitle(R.string.dialog_title) 4 .setPositiveButton(R.string.dialog_button, null) 5 .setView(layout); 6 builder.show();

という形でAlertDialogを表示させようとしましたが、アプリが強制終了します。
PhoneReceiverクラスがActivityクラスじゃないということが理由なのだろうと思いつつも、具体的な解決策を出せないでいます。
androidの公式サイトを見れば、DialogFragmentを推奨されていたので、同様にPhoneReceiverクラスがActivityでもFragmentクラスでもないために表示されないものと思います。

仕方がないので、他のサイトを参考にして下のようにToastをカスタマイズして、表示時間の延長、ボタンの追加等をしたのですが、納得ができないでいます。
popupWindowも試してみたのですが、これもうまくいきませんでした。

ですので、元のとおり、AlertDialogを表示する方法、ヒント等ありましたら、教えていただきたく質問いたします。
PhoneReceiverのコードは下に記載しています。
それとも根本的にやり方を変えた方がよいのでしょうか。

※捕捉1
あるサイトでこのような解決方法を見つけたのですが、

Java

1 public void showWarningAlert(Context context) { //Added argument 2 AlertDialog alertDialog = new AlertDialog.Builder(context).create(); //Use context 3 alertDialog.setTitle("Warning"); 4 alertDialog.setMessage("You are currently in a battle"); 5 alertDialog.setButton(AlertDialog.BUTTON_NEUTRAL, "OK", 6 new DialogInterface.OnClickListener() { 7 public void onClick(DialogInterface dialog, int which) { 8 dialog.dismiss(); 9 } 10 }); 11 alertDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT); 12 alertDialog.show(); 13 }

結局アプリは強制終了する状態です。alertDialog.show()のところでエラーが出ています。

※捕捉2
Logcatの内容です。PhoneReceiverに青文字がついています。

Java

105-11 09:13:42.101 26582-26582/com.example.ma2ri.newstage E/AndroidRuntime: FATAL EXCEPTION: main 2 Process: com.example.ma2ri.newstage, PID: 26582 3 java.lang.IllegalStateException: You need to use a Theme.AppCompat theme (or descendant) with this activity. 4 at android.support.v7.app.AppCompatDelegateImplV7.createSubDecor(AppCompatDelegateImplV7.java:343) 5 at android.support.v7.app.AppCompatDelegateImplV7.ensureSubDecor(AppCompatDelegateImplV7.java:312) 6 at android.support.v7.app.AppCompatDelegateImplV7.setContentView(AppCompatDelegateImplV7.java:277) 7 at android.support.v7.app.AppCompatDialog.setContentView(AppCompatDialog.java:80) 8 at android.support.v7.app.AlertController.installContent(AlertController.java:214) 9 at android.support.v7.app.AlertDialog.onCreate(AlertDialog.java:256) 10 at android.app.Dialog.dispatchOnCreate(Dialog.java:578) 11 at android.app.Dialog.show(Dialog.java:314) 12 at com.example.ma2ri.newstage.PhoneReceiver.showWarningAlert(PhoneReceiver.java:173) 13 at com.example.ma2ri.newstage.PhoneReceiver.onCallStateChanged(PhoneReceiver.java:60) 14 at android.telephony.PhoneStateListener$1.handleMessage(PhoneStateListener.java:323) 15 at android.os.Handler.dispatchMessage(Handler.java:102) 16 at android.os.Looper.loop(Looper.java:158) 17 at android.app.ActivityThread.main(ActivityThread.java:7237) 18 at java.lang.reflect.Method.invoke(Native Method) 19 at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1230) 20 at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1120)

Java

1 class PhoneReceiver extends PhoneStateListener { 2 private int totalCount = 0; 3 private Context context; 4 Intent intent; 5 TextView textView; 6 ToastCustom toastCustom; 7 View view; 8 PhoneReceiver(Context context) { 9 this.context = context; 10 } 11 12 public void onCallStateChanged(int state, String incomingNumber) { 13 super.onCallStateChanged(state, incomingNumber); 14 15 switch (state) { 16 case TelephonyManager.CALL_STATE_RINGING: 17 18 Cursor addressTable = context.getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null, null, null, null); 19 if (addressTable != null) { 20 while (addressTable.moveToNext()) { 21 String phoneNumber = addressTable.getString(addressTable.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER)); 22 for (int i = 0; i < addressTable.getCount(); i++) { 23 int count = BooleanSum(PhoneNumberUtils.compare(phoneNumber, incomingNumber)); 24 totalCount += count; 25 } 26 } 27 addressTable.close(); 28 } 29 if (totalCount >= 1) { 30 31 /* 32 final LayoutInflater inflater = (LayoutInflater)context.getSystemService(LAYOUT_INFLATER_SERVICE); 33 final View layout = inflater.inflate(R.layout.toast_layout, null); 34 final TextView textView = (TextView) layout.findViewById(R.id.text); 35 textView.setText(R.string.alert); 36 37 final Toast toast = new Toast(context.getApplicationContext()); 38 toast.setGravity(Gravity.CENTER_VERTICAL, 0, 0); 39 toast.setDuration(Toast.LENGTH_LONG); 40 toast.setView(layout); 41 toast.show(); 42 */ 43 44 CustomToast.makeText(context).show(); 45 46 } 47 break; 48 49 case TelephonyManager.CALL_STATE_OFFHOOK: 50 Toast.makeText(context, R.string.off_hook + incomingNumber, Toast.LENGTH_LONG).show(); 51 break; 52 } 53 } 54 55 private int BooleanSum(Boolean exchanger) { 56 if (exchanger) return 1; 57 else { 58 return 0; 59 } 60 }

_

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

swordone

2017/05/10 14:58

まず、コードをマークダウンしてください。質問編集画面でコード部分を反転選択して<code>を押すとコードが読みやすくなります。第2に、強制終了時のログを掲載してください。
RNagamatsu

2017/05/11 00:52

返信が遅くなり、申し訳ありません。コードを編集し、ログも掲載しました。
guest

回答3

0

ベストアンサー

DialogFragmentやAlertDialogはActivity上で表示させる必要があります。
そのため、PhoneReceiverがService内や単体のBroadcastReceiverであれば、Activityを表示させてそこからDialogを表示させる流れになるかと思います。

Activity側ですが、
半透明なActivityを用意しそこからDialogを表示させる。
Activity自体の表示をDialogにして表示する。
といった方法があります。

いずれの方法もStyle(Theme)で設定する事ができます(下部に記載)。
半透明なActivity方法であれば、Theme.Translucentといった半透明用のThemeが用意されていますので簡単です。ただAppCompatのThemeで透明にしたい場合はThemeが用意されていないためStyleを自作する必要があります。
*確認してないのでわかりませんが、最近のライブラリバージョンでは用意されてるやもしれません。

なお、この半透明なActivityでの方法の場合は回転時の対応に注意してください。
onCreateやonStart等のタイミングで単純にDialogFragmentをshowしていると回転の度にDialogが重複されていくかと思います。FragmentManager等で確認してすでに表示されているのであれば表示しないようにする必要があります。あとはDialogを閉じるタイミングでfinishしActivityも閉じるだけです。

最後にいくつかThemeも記載しておきます。
参考になれば幸いです。

AppCompatな半透明用Theme。

XML

1<!-- parentを利用するTheme.AppCompatに変更する事でDark等に変更可--> 2<style name="Theme.AppCompat.Translucent" parent="Base.Theme.AppCompat.Light.DarkActionBar"> 3 <item name="colorPrimary">@color/colorPrimary</item> 4 <item name="colorAccent">@color/colorAccent</item> 5 6 <!-- 完全に半透明にする場合は通知バー部分の色も透明にする--> 7 <item name="colorPrimaryDark">@android:color/transparent</item> 8</style>

ActivityをAppCompatなDialog表示にする。

XML

1<!-- Lightにする場合はparentをTheme.AppCompat.Light.Dialog.Alertにする--> 2<style name="Theme.AppCompat.DialogActivity" parent="Theme.AppCompat.Dialog.Alert"> 3 <item name="colorPrimary">@color/colorPrimary</item> 4 <item name="colorPrimaryDark">@color/colorPrimaryDark</item> 5 <item name="colorAccent">@color/colorAccent</item> 6</style>

投稿2017/05/12 14:49

uniko

総合スコア448

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

RNagamatsu

2017/05/12 15:19

丁寧な説明ありがとうございます。 すぐにチャレンジしたいのですが、まだ職場ですので明日頑張ってみます。
RNagamatsu

2017/05/13 05:57

まだ、エラーが出てアクティビティを立ち上げることはできないのですが、やり方は教えていただきましたので、頑張ってみます。ありがとうございました。
uniko

2017/05/13 06:32

エラーの内容が分からないのでなんとも言えませんが、別の回答にコメントされているような、 You need to use a Theme.AppCompat theme (or descendant) with this activity. といったエラーであれば該当ActivityがThemeがTheme.AppCompat を継承したものでないと言われているようです。AppCompatActivityであればTheme.AppCompatを継承したものを適応する必要があります。 参考まで。
guest

0

Reciverクラスで例えば以下のようにAcitivtyを取得し、そのActivity内でダイアログ表示処理を行うと上手くいくかもしれません。

Java

1MainActivity ma = (MainActivity) this.getContext(); 2ma.testest();

MainActivityクラスのtestest()

Java

1public void testest(){ 2DialogFragment dialog = new test_Dialog(); 3dialog.show(getFragmentManager(), "test_dialog"); 4}

拙いコードですが参考になれば幸いです。

投稿2017/05/11 03:22

編集2017/05/11 03:24
birdbird

総合スコア20

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

RNagamatsu

2017/05/11 03:54

回答ありがとうございます。 MainActivityクラスでtestest()を記述することはできたのですが、ReceiverクラスでgetContext()の部分だけ赤字になって失敗してしまいます。 もう少し試してみます。
birdbird

2017/05/12 12:24

お力になれずすみません。 がんばってください!
guest

0

Reciverクラスから適当なActivityを起動し、Activityの中でAlertDialogを表示するとできそうですね。

投稿2017/05/11 01:44

yona

総合スコア18155

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

RNagamatsu

2017/05/11 03:43

 ありがとうございます。そのような考え方は思いつきませんでした。  MyDialogというクラスを新たにつくって、その中でAlertDialogを表示するようにして、ReceiverクラスからMyDialogを起動させるようにしたのですが・・・        パターン① Intent i = new Intent(context.getApplicationContext(), MyDialog.class); context.startActivity(i);        パターン② Intent i = new Intent(); i.setClassName("com.example.ma2ri.newstage", "com.example.ma2ri.newstage.MyDialog"); context.startActivity(i);        パターン③ Intent i = new Intent(context, MyDialog.class); context.startActivity(i);        パターン④ Intent i = new Intent(activityContext, MyDialog.class); activityContext.startActivity(i); と試したのですが、いずれも最後の行で java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String android.content.Context.getPackageName()' on a null object reference at com.example.ma2ri.newstage.PhoneReceiver.onCallStateChanged(PhoneReceiver.java:77) このようなエラーが出てしまいます。  よろしかったら、もう少しだけヒントを頂けると幸いです。
yona

2017/05/11 03:55

その部分だけでは判断できません。 前後数行を記載してください。
RNagamatsu

2017/05/11 04:11

失礼しました。Receiverクラスのswitch文の中に、 Intent i = new Intent(context.getApplicationContext(), MyDialog.class); context.startActivity(i); と、下のように記述しました。読みづらいかと思いますが、体裁を整えられないようなのですみません。 class PhoneReceiver extends PhoneStateListener { private Context context; Intent intent; PhoneReceiver(Context context) { this.context = context; } public void onCallStateChanged(int state, String incomingNumber) { super.onCallStateChanged(state, incomingNumber); switch (state) { case TelephonyManager.CALL_STATE_RINGING: if (totalCount >= 1) { Intent i = new Intent(context.getApplicationContext(), MyDialog.class); context.startActivity(i); } break; case TelephonyManager.CALL_STATE_OFFHOOK: //省略 break; } } private int BooleanSum(Boolean exchanger) { //省略 } エラーはこのようになっています。 android.util.AndroidRuntimeException: Calling startActivity() from outside of an Activity context requires the FLAG_ACTIVITY_NEW_TASK flag. Is this really what you want? at android.app.ContextImpl.startActivity(ContextImpl.java:734) at android.app.ContextImpl.startActivity(ContextImpl.java:721) at android.content.ContextWrapper.startActivity(ContextWrapper.java:345) at android.content.ContextWrapper.startActivity(ContextWrapper.java:345) at com.example.ma2ri.newstage.PhoneReceiver.onCallStateChanged(PhoneReceiver.java:67) at android.telephony.PhoneStateListener$1.handleMessage(PhoneStateListener.java:323) at android.os.Handler.dispatchMessage(Handler.java:102) at android.os.Looper.loop(Looper.java:158) at android.app.ActivityThread.main(ActivityThread.java:7237) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1230) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1120)
RNagamatsu

2017/05/11 07:38 編集

何度もすみません。 Intent i = new Intent(context.getApplicationContext(), MyDialog.class); i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); context.getApplicationContext().startActivity(i); このようにすると一度だけMyDialogクラスを呼び出せましたが、その後はずっとエラーです。 java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.ma2ri.newstage/com.example.ma2ri.newstage.MyDialog}: java.lang.IllegalStateException: You need to use a Theme.AppCompat theme (or descendant) with this activity. at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3254) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3350) at android.app.ActivityThread.access$1100(ActivityThread.java:222) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1795) at android.os.Handler.dispatchMessage(Handler.java:102) at android.os.Looper.loop(Looper.java:158) at android.app.ActivityThread.main(ActivityThread.java:7237) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1230) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1120) Caused by: java.lang.IllegalStateException: You need to use a Theme.AppCompat theme (or descendant) with this activity. at android.support.v7.app.AppCompatDelegateImplV7.createSubDecor(AppCompatDelegateImplV7.java:343) at android.support.v7.app.AppCompatDelegateImplV7.ensureSubDecor(AppCompatDelegateImplV7.java:312) at android.support.v7.app.AppCompatDelegateImplV7.onPostCreate(AppCompatDelegateImplV7.java:167) at android.support.v7.app.AppCompatActivity.onPostCreate(AppCompatActivity.java:98) at android.app.Instrumentation.callActivityOnPostCreate(Instrumentation.java:1216) at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3236) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3350)  at android.app.ActivityThread.access$1100(ActivityThread.java:222)  at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1795)  at android.os.Handler.dispatchMessage(Handler.java:102)  at android.os.Looper.loop(Looper.java:158)  at android.app.ActivityThread.main(ActivityThread.java:7237)  at java.lang.reflect.Method.invoke(Native Method)  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1230)  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1120)  MyDialogのDialog自体も調子が悪いようです。 public class MyDialog extends AppCompatActivity { private Context context; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); AlertDialog.Builder alert = new AlertDialog.Builder(MyDialog.this); alert.setTitle("title") .setMessage("message") .setPositiveButton("OK", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { MyDialog.this.finish(); } }); alert.create().show(); } }
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問