【问题标题】:Android java Messaging problem in MainActivityMainActivity中的Android java消息传递问题
【发布时间】:2022-01-03 14:38:33
【问题描述】:

我正在构建一个多用户消息传递应用程序。我已经完成了服务器设置,但是我在用户(应用程序)部分遇到了问题。

client.java,创建异常的部分代码

public class Client {
public String photo;
public String clientPhoto;
public String clientId;
public PublicKey publicKey;
public PrivateKey privateKey;

public volatile Socket ClientSocket;
public InputStream in;
private  ClientDatabase db;
private Encryption E;



private String ipv4 ;
private int port;



/**
 *   Consturactor need server ipv4 address and port to conndect it
 */
public Client(String ipv4,int port) throws IOException {
    this.ipv4 = ipv4;
    this.port = port;



}


/**
 *  Start recieving message form server
 *
 * */
public void startClient()  {
    
    try {
        ClientSocket= new Socket(ipv4,5551);
        ClientThread clientThread = new ClientThread(ClientSocket.getInputStream(),db,privateKey);
        clientThread.start();
    } catch (IOException e) {
        e.printStackTrace();
    }


}





public ClientDatabase createDatabaseOnesTime(@Nullable  Context context){
    db = new ClientDatabase(context);
    return db;
}

/**
 *   This function create key pair (public and private) every client needs to
 *   create their own key pair and they will store private key and publich publickey
 *
 *   When I client want to send message to our client it should ecrypt message with our public key
 *   So ve can read data with our private key
 *
 *   this funcion will start just ones time at installation of app
 *
 **/
@RequiresApi(api = Build.VERSION_CODES.O)
public void createPublicPrivateKey() throws NoSuchAlgorithmException, SQLException {
    E = new Encryption();
    E.generateKeyPair();
    this.privateKey = E.getPrivate();
    this.publicKey = E.getPublic();
    this.db.addRootAuthTokens(this.E.encodeBase64FromPublicKey(publicKey),this.E.encodeBase64FromPrivateKey(privateKey));

}

还有 MainActivity.java

public class MainActivity extends AppCompatActivity {

private EditText edtPhoneNumber ;
private Button btnSignUp;
public static ClientDatabase database ;
public static  Client client ;



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


    edtPhoneNumber = findViewById(R.id.edtPhoneNum);
    btnSignUp = findViewById(R.id.btnSubmit);


    client = null; // Client
    try {
        client = new Client("18.193.114.51", 5551);
    } catch (IOException e) {
        e.printStackTrace();
    }
    client.startClient();


    database = client.createDatabaseOnesTime(MainActivity.this);  // database

ClientThread 类

class ClientThread extends Thread{

 private InputStream in;
 private ClientDatabase db;
 private Encryption E;
 private PrivateKey privateKey;

 byte[] data;
 String message;

 public ClientThread(InputStream in, ClientDatabase db,PrivateKey privateKey){
     this.privateKey = privateKey;
     this.db = db;
     this.in = in;

 }


@RequiresApi(api = Build.VERSION_CODES.O)
@Override
public void run(){
    /**
     * Read everytime message and send message to message processor
     *
     *
     **/




    while (true){
        try {
            if (in.available()!= 0){
                in.read(data);
                message = new String(data);
                messageProccessor(message);
            }



        } catch (IOException e) {
            e.printStackTrace();
        } catch (NoSuchPaddingException e) {
            e.printStackTrace();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        } catch (IllegalBlockSizeException e) {
            e.printStackTrace();
        } catch (BadPaddingException e) {
            e.printStackTrace();
        } catch (InvalidKeyException e) {
            e.printStackTrace();
        }



    }

}

我在 Client 类中使用 ClientThread 类接收所有传入消息并处理这些消息。通过使用客户端类中的一些函数,我使用了用户可能进行的活动。 问题是: 连接到 Socket 服务器时主要活动失败

E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.ceng201_project, PID: 5412
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.ceng201_project/com.example.ceng201_project.MainActivity}: android.os.NetworkOnMainThreadException
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2817)
    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2892)
    at android.app.ActivityThread.-wrap11(Unknown Source:0)
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1593)
    at android.os.Handler.dispatchMessage(Handler.java:105)
    at android.os.Looper.loop(Looper.java:164)
    at android.app.ActivityThread.main(ActivityThread.java:6541)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)
 Caused by: android.os.NetworkOnMainThreadException
    at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1448)
    at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:355)
    at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:200)
    at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:182)
    at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:356)
    at java.net.Socket.connect(Socket.java:616)
    at java.net.Socket.connect(Socket.java:565)
    at java.net.Socket.<init>(Socket.java:445)
    at java.net.Socket.<init>(Socket.java:217)
    at com.example.ceng201_project.Client.startClient(Client.java:66)
    at com.example.ceng201_project.MainActivity.onCreate(MainActivity.java:40)
    at android.app.Activity.performCreate(Activity.java:6975)
    at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1213)
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2770)
    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2892) 
    at android.app.ActivityThread.-wrap11(Unknown Source:0) 
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1593) 
    at android.os.Handler.dispatchMessage(Handler.java:105) 
    at android.os.Looper.loop(Looper.java:164) 
    at android.app.ActivityThread.main(ActivityThread.java:6541) 
    at java.lang.reflect.Method.invoke(Native Method) 
    at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240) 
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767) 

当我尝试在 ClientThread 类中建立 Socket 连接时,我无法从 Thread 类中获取连接的 Socket 对象,也无法运行其他应该工作的方法。例如,我无法向服务器发送消息。

我该如何解决这个问题? 提前致谢

【问题讨论】:

    标签: java android multithreading sockets


    【解决方案1】:

    当您使用网络时,您必须在主线程之外进行处理。

    以前有 Asynctask 用于处理后台线程,但 Asynctask 在 API 级别 30 中已弃用。

    你可以在java中使用kotlin coroutineconcurrent

    【讨论】:

    • 'class Invoker implements Executor { @Override public void execute(Runnable r) { r.run();} }' 我将它添加到 Client.java 并将 startClient 更新为此' public void startClient( ) { 调用者执行者 = 新调用者(); executor.execute(()->{ try { ClientSocket= new Socket(ipv4,5551); ClientThread clientThread = new ClientThread(ClientSocket.getInputStream(),db,privateKey); clientThread.start(); } catch (IOException e) { e.printStackTrace();}}); }'
    • 但是在 com.example.ceng201_project.Invoker.execute(Client.java:31) 在 com.example.ceng201_project.Client.startClient(Client.java: 73) 在 com.example.ceng201_project.MainActivity.onCreate(MainActivity.java:40)"
    • 正如我所说,您应该在后台线程中使用网络,而不是在主线程中,对线程和 kotlin 协程进行一些研究
    • 谢谢,但我的问题是我正在创建线程,我想在 main 中启动它,同样的问题。胎面开始主要但在后台工作。我可以从哪里开始我的话题?
    • @MIOx08 可以将更新后的代码添加到问题中吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-05-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多