temz 2023-02-06 20:49 采纳率: 100%
浏览 111
已结题

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

权限也加了

 <uses-permission android:name="android.permission.SYSTEM_OVERLAY_WINDOW"/>
 <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
 <uses-permission android:name="android.permission.INTERNET"/>
  • 写回答

11条回答 默认 最新

  • 爱吃鱼豆腐 2023-02-07 15:35
    关注

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

    解决方法如下:

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

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

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

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(10条)

报告相同问题?

问题事件

  • 系统已结题 2月21日
  • 已采纳回答 2月13日
  • 创建了问题 2月6日

悬赏问题

  • ¥20 wireshark抓不到vlan
  • ¥20 关于#stm32#的问题:需要指导自动酸碱滴定仪的原理图程序代码及仿真
  • ¥20 设计一款异域新娘的视频相亲软件需要哪些技术支持
  • ¥15 stata安慰剂检验作图但是真实值不出现在图上
  • ¥15 c程序不知道为什么得不到结果
  • ¥40 复杂的限制性的商函数处理
  • ¥15 程序不包含适用于入口点的静态Main方法
  • ¥15 素材场景中光线烘焙后灯光失效
  • ¥15 请教一下各位,为什么我这个没有实现模拟点击
  • ¥15 执行 virtuoso 命令后,界面没有,cadence 启动不起来