android service弹出dialog,showdialog就出错,如何解决?

写了一个应用mainactivity启动服务,在service中启动socket服务,socket捕获异常在service中弹出dialog,但就是不行。
每次都弹出这个错误,但改主题也没用还是弹出这个错误,哪位给看一下
FATAL EXCEPTION: Thread-4
Process: com.example.msslapp, PID: 22716
java.lang.IllegalStateException: You need to use a Theme.AppCompat theme (or descendant) with this activity.

android 使用 service弹出dialog
mainactivity是

public class MainActivity extends AppCompatActivity {

    private  final int SERVER_PORT = 26666;//端口号
    private  final String SERVER_IP = "192.168.1.101";//连接IP

    TcpConnectThread tcpthread;
    TextView tv1;
    EditText et1,et2,et3,et4;
    Button btn1,btn2,btn3;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        tv1 =(TextView) findViewById(R.id.tv1);
        et1 =(EditText) findViewById(R.id.et1);
        btn1=(Button)   findViewById(R.id.btn1);

        et2 =(EditText) findViewById(R.id.et2);
        et3 =(EditText) findViewById(R.id.et3);
        et4 =(EditText) findViewById(R.id.et4);
        btn2=(Button)   findViewById(R.id.btn2);
        btn3=(Button)   findViewById(R.id.btn3);


        Intent regIntent = new Intent(this, SocketService.class);
        regIntent.putExtra("IP", SERVER_IP);
        regIntent.putExtra("PORT",SERVER_PORT);
        startService(regIntent);


       // tcpthread = new TcpConnectThread(SERVER_IP,SERVER_PORT,getApplicationContext());
       // tcpthread.start();

        //发送消息模式为test的消息
        btn1.setOnClickListener(new Button.OnClickListener(){
            @Override
            public void onClick(View arg0) {
                String str=et1.getText().toString();
                TCPsend ts=new TCPsend(tcpthread.Client_ssl,"test",str);
                new Thread(ts).start();
            }
        });

        //发送消息模式为key的消息
        btn2.setOnClickListener(new Button.OnClickListener(){
            @Override
            public void onClick(View arg0) {
                String key=  et2.getText().toString();
                String data= et3.getText().toString();
                String context =et4.getText().toString();
                TCPsend ts=new TCPsend(SocketService.Client_ssl,key,data,context);
                new Thread(ts).start();
            }
        });

        btn3.setOnClickListener(new Button.OnClickListener(){
            @Override
            public void onClick(View arg0) {
                EventBus.getDefault().post(new MyEvent("123456"));

            }
        });

        /*
        if(EventBus.getDefault().isRegistered(this)){
            System.out.println("已经注册");
        }
        else if(!EventBus.getDefault().isRegistered(this)){
            System.out.println("注册失败");
        }*/
        EventBus.getDefault().register(this);
    }

    @Override
    public void onDestroy() {
      //  TCPsend ts=new TCPsend(tcpthread.Client_ssl,"type","Quit");
      //  new Thread(ts).start();
        super.onDestroy();
        MainActivity.this.stopService(new
                Intent(MainActivity.this,
                SocketService.class));

        EventBus.getDefault().unregister(this); //取消注册
    }

    //接收eventbus消息
    @Subscribe(threadMode = ThreadMode.MAIN)
    public void EventbusMain(MyEvent te) {
        tv1.setText(te.getdata());
    }
}

service为

public class SocketService extends Service {

    private static final String CLIENT_KET_PASSWORD = "changeit";//私钥密码
    private static final String CLIENT_TRUST_PASSWORD = "changeit";//信任证书密码
    private static final String CLIENT_AGREEMENT = "SSL";//使用协议
    private static final String CLIENT_KEY_MANAGER = "X509";//密钥管理器
    private static final String CLIENT_TRUST_MANAGER = "X509";//
    private static final String CLIENT_KEY_KEYSTORE = "BKS";//密库,这里用的是BouncyCastle密库
    private static final String CLIENT_TRUST_KEYSTORE = "BKS";//

    /*连接线程*/
    private Thread connectThread;
    private Timer timer = new Timer();
    //private OutputStream outputStream;

    private SocketBinder sockerBinder = new SocketBinder();
    private String ip;
    private int port;
    private TimerTask task;

    static SSLSocket Client_ssl;
    /*默认重连*/
    private boolean isReConnect = true;
    private Handler handler;



    @Override
    public IBinder onBind(Intent intent) {
        return sockerBinder;
    }
    public class SocketBinder extends Binder {

        /*返回SocketService 在需要的地方可以通过ServiceConnection获取到SocketService  */
        public SocketService getService() {
            return SocketService.this;
        }
    }

    @Override
    public void onCreate() {

        handler = new Handler(Looper.getMainLooper());
        super.onCreate();
    }


    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {

        /*拿到传递过来的ip和端口号*/
        ip = intent.getStringExtra("IP");
        port =intent.getIntExtra("PORT",0) ;

        /*初始化socket*/
        initSocket();

        return super.onStartCommand(intent, flags, startId);
    }


    /*初始化socket*/
    private void initSocket() {
        if (Client_ssl == null && connectThread == null) {
            connectThread = new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        final SSLContext sslContext = SSLContext.getInstance(CLIENT_AGREEMENT);
                        //取得KeyManagerFactory和TrustManagerFactory的X509密钥管理器实例
                        KeyManagerFactory keyManager = KeyManagerFactory.getInstance(CLIENT_KEY_MANAGER);
                        TrustManagerFactory trustManager = TrustManagerFactory.getInstance(CLIENT_TRUST_MANAGER);
                        //取得BKS密库实例
                        KeyStore kks = KeyStore.getInstance(CLIENT_KEY_KEYSTORE);
                        KeyStore tks = KeyStore.getInstance(CLIENT_TRUST_KEYSTORE);
                        //加客户端载证书和私钥,通过读取资源文件的方式读取密钥和信任证书
                        kks.load(getBaseContext().getAssets().open("client.bks"), CLIENT_KET_PASSWORD.toCharArray());
                        tks.load(getBaseContext().getAssets().open("client.bks"), CLIENT_TRUST_PASSWORD.toCharArray());
                        //初始化密钥管理器
                        keyManager.init(kks, CLIENT_KET_PASSWORD.toCharArray());
                        trustManager.init(tks);
                        //初始化SSLContext
                        sslContext.init(keyManager.getKeyManagers(), trustManager.getTrustManagers(), null);
                        Client_ssl = (SSLSocket) sslContext.getSocketFactory().createSocket(ip, port);
                        System.out.println("正在连接");

                        /*连接成功的话  发送心跳包*/
                        if (Client_ssl.isConnected()) {

                            /*因为Toast是要运行在主线程的  这里是子线程  所以需要到主线程哪里去显示toast*/
                            toastMsg("socket已连接");
                             TcpConnectThread tcpthread = new TcpConnectThread(Client_ssl,getApplicationContext());
                             tcpthread.start();

                            /*发送心跳数据*/
                            sendBeatData();
                        }

                    } catch (IOException e) {
                        e.printStackTrace();
                        if (e instanceof SocketTimeoutException) {
                            toastMsg("连接超时");
                            releaseSocket();

                        } else if (e instanceof NoRouteToHostException) {
                            toastMsg("该地址不存在,请检查");
                            stopSelf();

                        } else if (e instanceof ConnectException) {
                            toastMsg("连接异常或被拒绝,请检查");
                            releaseSocket();
                            //stopSelf();

                        }
                    } catch (UnrecoverableKeyException e) {
                        e.printStackTrace();
                    } catch (CertificateException e) {
                        e.printStackTrace();
                    } catch (NoSuchAlgorithmException e) {
                        e.printStackTrace();
                    } catch (KeyStoreException e) {
                        e.printStackTrace();
                    } catch (KeyManagementException e) {
                        e.printStackTrace();
                    }
                }
            });
            /*启动连接线程*/
            connectThread.start();
        }
    }

    /*定时发送数据*/
    private void sendBeatData() {
        if (timer == null) {
            timer = new Timer();
        }

        if (task == null) {
            task = new TimerTask() {
                @Override
                public void run() {
                    try {
                        Message msg=new Message();
                        msg.putmsgmap("type","Beat");
                        MyObjectOutputStream moos;
                        moos =new MyObjectOutputStream(Client_ssl.getOutputStream());

                        moos.writeObject(msg);
                        moos.flush();
                    } catch (Exception e) {
                        /*发送失败说明socket断开了或者出现了其他错误*/
                        //toastMsg("连接断开,正在重连");
                        /*重连*/
                        releaseSocket();
                        e.printStackTrace();
                    }
                }
            };
        }

        timer.schedule(task, 0, 2000);
    }

    /*释放资源*/
    private void releaseSocket() {

        if (task != null) {
            task.cancel();
            task = null;
        }
        if (timer != null) {
            timer.purge();
            timer.cancel();
            timer = null;
        }

        if (Client_ssl != null) {
            try {
                Client_ssl.close();

            } catch (IOException e) {
            }
            Client_ssl = null;
        }

        if (connectThread != null) {
            connectThread = null;
        }

        /*重新初始化socket*/
        if (isReConnect) {
            showDialog();
            //initSocket();
        }

    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        Log.i("SocketService", "onDestroy");
        isReConnect = false;
        releaseSocket();
    }

    /*因为Toast是要运行在主线程的   所以需要到主线程哪里去显示toast*/
    private void toastMsg(final String msg) {

        handler.post(new Runnable() {
            @Override
            public void run() {
                Toast.makeText(getApplicationContext(), msg, Toast.LENGTH_SHORT).show();
            }
        });
    }

    private void showDialog() {
        AlertDialog.Builder builder = new AlertDialog.Builder(this);
        builder.setMessage("连接已经断开,是否重新连接");
        builder.setPositiveButton("确定", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialogInterface, int i) {
                initSocket();
            }
        });

        builder.setNegativeButton("取消", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialogInterface, int i) {
                isReConnect = false;
            }
        });


        AlertDialog alertDialog = builder.create();
        //alertDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            alertDialog.getWindow().setType((WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY));
        }else {
            alertDialog.getWindow().setType((WindowManager.LayoutParams.TYPE_SYSTEM_ALERT));
        }
        alertDialog.setCanceledOnTouchOutside(true);
        alertDialog.show();

        new Thread(){
            public void run() {

                handler.post(new Runnable() {
                    @Override
                    public void run() {
                        alertDialog.show();
                    }
                });
            };
        }.start();
    }
}

在服务中调用方法

private void showDialog() {
        AlertDialog.Builder builder = new AlertDialog.Builder(this);
        builder.setMessage("连接已经断开,是否重新连接");
        builder.setPositiveButton("确定", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialogInterface, int i) {
                initSocket();
            }
        });

        builder.setNegativeButton("取消", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialogInterface, int i) {
                isReConnect = false;
            }
        });


        AlertDialog alertDialog = builder.create();
        //alertDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            alertDialog.getWindow().setType((WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY));
        }else {
            alertDialog.getWindow().setType((WindowManager.LayoutParams.TYPE_SYSTEM_ALERT));
        }
        alertDialog.setCanceledOnTouchOutside(true);
        alertDialog.show();

        new Thread(){
            public void run() {

                handler.post(new Runnable() {
                    @Override
                    public void run() {
                        alertDialog.show();
                    }
                });
            };
        }.start();
    }

权限也加了

 name="android.permission.SYSTEM_OVERLAY_WINDOW"/>
 name="android.permission.SYSTEM_ALERT_WINDOW" />
 name="android.permission.INTERNET"/>

在Android中,Service不能直接弹出对话框,因为它不具有用户界面。如果您试图使用showDialog方法,则会出现错误。

解决方法如下:

  1. 启动一个Activity:您可以启动一个Activity,并在其中显示对话框。

  2. 使用Notification:您可以使用Notification,以在通知栏中显示消息。

  3. 使用BroadcastReceiver:您可以使用BroadcastReceiver,以在接收到广播时显示对话框。

望采纳。。

android 中,service 是不能直接使用 dialog,因为初始化 dialog 的参数 context 需要用到 Activity,你现在用的 context 是 service,所以会报错闪退。

解决方案:
方案一:使用 WindowManager 去添加 Layout 做一个悬浮窗版的 dialog。

方案二:在 service 里面启动一个 DialogActivity

方案三:在 service 里面启动一个全透明的 Activity,然后在这个全透明的 activity 里面弹出 Dialog。

望采纳,如果您需要代码,可先采纳,然后联系我,我可给你把这三个方案的代码写给你。

斟酌后再考虑,望采纳哦😅

只能从活动或片段调用该方法。Android 中的服务在后台运行,无法访问 UI,因此您无法直接显示来自服务的对话框。showDialog

若要显示来自服务的对话框,需要创建一个通知来启动显示该对话框的活动。下面是一个示例:

创建显示对话框的活动。可以通过调用 in 方法来执行此操作。AlertDialog.BuilderonCreate

在您的服务中,创建一个通知,用于启动在步骤 1 中创建的活动。用于创建在单击通知时启动活动的 Intent。PendingIntent


```java
Intent intent = new Intent(this, DialogActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, 0);

NotificationCompat.Builder builder = new NotificationCompat.Builder(this, "channel_id")
        .setSmallIcon(R.drawable.ic_notification)
        .setContentTitle("Service Notification")
        .setContentText("Click to show dialog")
        .setPriority(NotificationCompat.PRIORITY_DEFAULT)
        .setContentIntent(pendingIntent)
        .setAutoCancel(true);

NotificationManagerCompat notificationManager = NotificationManagerCompat.from(this);
notificationManager.notify(0, builder.build());


3.确保请求文件中的权限。FOREGROUND_SERVICEAndroidManifest.xml

```java
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />


这个错误如果单独用activity或许可以解决,目前android创建的默认这个不行,不兼容,所以会报这个错误,可以采用异步调用的方式,也可以直接再创一个activity兼容这个dialog,最后设置成透明背景就是一样的。

不知道你这个问题是否已经解决, 如果还没有解决的话:

如果你已经解决了该问题, 非常希望你能够分享一下解决方案, 写成博客, 将相关链接放在评论区, 以帮助更多的人 ^-^

service不可以弹出dialog,如果想要弹出,可以有以下方案
1)透明activity,里面有dialog进行展示,dialog的取消、确定与activity的生命周期关联
2)用phonewindow或者window
3)一个像素的activity,然后可以进行任意的操作

service里有个handler,放handler里去执行,如果你的toast可以正常显示,dialog也可以呀。

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

可以让对话框始终显示在其他应用程序的window之上,也就是说这个dialog始终处于最上层,对用户始终可见,

也就是说用户按了home之后dialog还在。这样做需要加上权限"android.permission.SYSTEM_ALERT_WINDOW",但是某些手机对底层进行了修改(小米,魅族,乐视之类),系统会默认会拒绝该权限。
解决:
通过将type设定为TYPE_TOAST, 就可以绕过检查。

通过将type设定为TYPE_TOAST, 就可以绕过检查。

如果需要后台进行建议换个方案吧,不如搞个悬浮窗来解决不行的话就回到软件打开个activity在进行不然的话用不了showdialog方法的

该回答引用ChatGPT
请参考下面的解决方案,如果有帮助,还请点击 “采纳” 感谢支持!

解决方案如下:
在清单文件中,为MainActivity活动指定一个AppCompat主题,如下所示:

<activity
  android:name=".MainActivity"
  android:theme="@style/AppTheme">
  ...
</activity>

2、创建一个style.xml文件并创建一个AppCompat主题:

<resources>
  <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
    <!-- Customize your theme here. -->
    ...
  </style>
</resources>


3、在Service中使用Context.getSystemService(Context.ALERT_SERVICE)获取WindowManager,并使用它创建一个Dialog:

WindowManager wm = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
AlertDialog.Builder builder = new AlertDialog.Builder(new ContextThemeWrapper(this, R.style.AppTheme));
builder.setTitle("Title")
  .setMessage("Message")
  .setPositiveButton("OK", new DialogInterface.OnClickListener() {
    public void onClick(DialogInterface dialog, int id) {
      // handle the click event
    }
  });
AlertDialog dialog = builder.create();
dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY);
dialog.show();