Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/374.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何在影响当前活动的Runnable中提供回调函数_Java_Android - Fatal编程技术网

Java 如何在影响当前活动的Runnable中提供回调函数

Java 如何在影响当前活动的Runnable中提供回调函数,java,android,Java,Android,我有以下课程: package com.example.vodafone_fu_h300s.logic; import com.example.vodafone_fu_h300s.logic.exceptions.CsrfTokenNotFound; import com.example.vodafone_fu_h300s.logic.exceptions.SettingsFailedException; import com.example.vodafone_fu_h300s.logic.

我有以下课程:

package com.example.vodafone_fu_h300s.logic;

import com.example.vodafone_fu_h300s.logic.exceptions.CsrfTokenNotFound;
import com.example.vodafone_fu_h300s.logic.exceptions.SettingsFailedException;

import com.example.vodafone_fu_h300s.logic.lambdas.ExceptionHandler;
import com.example.vodafone_fu_h300s.logic.lambdas.LoginHandler;
import com.example.vodafone_fu_h300s.logic.lambdas.RetrieveSettingsHandler;
import com.example.vodafone_fu_h300s.logic.lambdas.SettingsRetrievalFailedHandler;

import org.json.JSONArray;
import org.json.JSONObject;

import java.io.IOException;

import java.math.BigInteger;
import java.nio.charset.StandardCharsets;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import okhttp3.Call;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import okhttp3.FormBody.Builder;

import java.security.MessageDigest;

public class Η300sCredentialsRetriever {

    private String url;

    private OkHttpClient httpClient;

    private String username;
    private String password;

    private LoginHandler loginHandler;
    private ExceptionHandler exceptionHandler;
    private RetrieveSettingsHandler settingsHandler;
    private SettingsRetrievalFailedHandler failedHandler;

    private String session_id;

    public Η300sCredentialsRetriever()
    {
        this.exceptionHandler = (Exception e)->{};
        this.loginHandler     = (boolean loginStatus)->{};
        this.settingsHandler  = (H300sVoipSettings settings)->{};
        this.failedHandler    = ()->{};

        this.setHttpClient(new OkHttpClient());
    }

    public void setSettingsHandler(RetrieveSettingsHandler handler){
        this.settingsHandler = handler;
    }

    public void setFailedHandler(SettingsRetrievalFailedHandler handler){
        this.failedHandler = handler;
    }

    public void setExceptionHandler(ExceptionHandler handler){
        this.exceptionHandler= handler;
    }

    public void setLoginHandler(LoginHandler handler){
        this.loginHandler=handler;
    }

    public void setUrl(String url){
        url = "http://"+url.replaceAll("http(s?)://","");
        this.url = url;
    }

    public String getUrl(){
        return this.url;
    }

    public void setHttpClient(OkHttpClient client)
    {
        this.httpClient = client;
    }

    public void setUsername(String username){
        this.username = username.trim();
    }

    public void setPassword(String password){
        this.password = password.trim();
    }

    public String getSessionId()
    {
        return this.session_id;
    }

    public String retrieveCSRFTokenFromHtml(String htmlPageUrl) throws IOException {

        if(htmlPageUrl==null || htmlPageUrl.trim().equals("")){
           return "";
        }

        Pattern csrfRegex = Pattern.compile("var csrf_token\\s*=\\s*'.+'");
        Matcher match     = csrfRegex.matcher(htmlPageUrl);

        if(match.find()){
            String matched = match.group();
            matched=matched.replaceAll("var|csrf_token|'|\\s|=","");
            return matched;
        }
        return "";
    }

    public String retrieveUrlContents(String url, String csrfToken, String referer) throws Exception
    {
        url = this.url.replaceAll("/$","")+"/"+url.replaceAll("^/","");
        csrfToken=(csrfToken == null)?"":csrfToken;

        if(!csrfToken.equals("")){
            long unixtime = System.currentTimeMillis() / 1000L;
            // AJAX Calls also require to offer the _ with a unix timestamp alongside csrf token
            url+="?_="+unixtime+"&csrf_token="+csrfToken;
        }
        Request.Builder request = new Request.Builder()
                .url(url)
                .header("User-Agent","Mozila/5.0 (X11;Ubuntu; Linux x86_64; rv:87.0) Gecko/20100101 Firefox/87.0")
                .header("Accept","text/html,application/xhtml+html;application/xml;q=0.9,image/webp,*/*;q=0.8")
                .header("Upgrade-Insecure-Requests","1")
                .header("Sec-GPC","1");

        String session_id = this.getSessionId();
        session_id = session_id==null?"":session_id;

        if(!session_id.equals("")){
            request.header("Cookie","login_uid="+Math.random()+"; session_id="+session_id);
        }

        referer = (referer==null)?"":referer;

        if(!referer.trim().equals("")){
            request.header("Referer",referer);
        }

        Response response = this.httpClient.newCall(request.build()).execute();

        int code = response.code();
        if( code != 200){
            throw new Exception("The url "+url+" returned code "+code);
        }
        String responseBody = response.body().string();
        return responseBody;
    }

    public String retrieveUrlContents(String url, String csrfToken) throws Exception
    {
        return retrieveUrlContents(url,csrfToken,"");
    }

    public String retrieveUrlContents(String url) throws Exception {
       return retrieveUrlContents(url,"");
    }

    public String retrieveCsrfTokenFromUrl(String url,String referer) throws CsrfTokenNotFound {
        try {
            String html = retrieveUrlContents(url,"",referer);
            return retrieveCSRFTokenFromHtml(html);
        } catch (Exception e) {
            exceptionHandler.handle(e);
            throw new CsrfTokenNotFound(url);
        }
    }

    public boolean login() {

        if(
                username == null || username.equals("") ||
                password == null || password.equals("")){
            return false;
        }

        try {
            this.session_id = null;
            String token = this.retrieveCsrfTokenFromUrl("/login.html",null);

            if(token == null){
                return false;
            }

            if(token.trim().equals("")){
                return false;
            }

            String challengeJson = this.retrieveUrlContents("/data/login.json");

            if(challengeJson == null){
                return false;
            }

            if(challengeJson.trim().equals("")){
                return false;
            }

            JSONObject json = (JSONObject) (new JSONArray(challengeJson)).get(0);

            String challenge = json.getString("challenge");

            if(challenge == null){
                return false;
            }

            if(challenge.trim().equals("")){
                return false;
            }

            MessageDigest md = MessageDigest.getInstance("SHA-256");
            String stringToDigest = password+challenge;
            byte []hash = md.digest(stringToDigest.getBytes(StandardCharsets.UTF_8));

            BigInteger number = new BigInteger(1, hash);
            StringBuilder hexString = new StringBuilder(number.toString(16));

            String loginPwd = hexString.toString();


            RequestBody requestBody = new Builder()
                    .add("LoginName", username)
                    .add("LoginPWD", loginPwd)
                    .add("challenge",challenge)
                    .build();

            long unixTime = System.currentTimeMillis() / 1000L;
            Request request = new Request.Builder()
                    .url(this.url+"/data/login.json?_="+unixTime+"&csrfToken="+token)
                    .post(requestBody)
                    .header("Cookie","login_uid="+Math.random())
                    .header("Referer","http://192.158.2.1/login.html")
                    .header("X-Requested-With","XMLHttpRequest")
                    .header("Content-Type","application/x-www-form-urnencoded; charset=UTF-8")
                    .header("User-Agent","Mozila/5.0 (X11;Ubuntu; Linux x86_64; rv:87.0) Gecko/20100101 Firefox/87.0")
                    .header("Origin","http://192.168.2.1")
                    .build();

            Call call = this.httpClient.newCall(request);
            Response response = call.execute();

            String responseString = response.body().string();
            String cookies = response.header("Set-Cookie");
            if(cookies == null || cookies.trim().equals("")){
                return false;
            }
            cookies=cookies.replaceAll("path=/|session_id=|;","");
            this.session_id=cookies;
            return responseString.equals("1");
        } catch (Exception e){
            exceptionHandler.handle(e);
            return false;
        }
    }

    public H300sVoipSettings retrieveVOIPSettings()  throws Exception {
        H300sVoipSettings settings;

        String csrfToken = retrieveCsrfTokenFromUrl("/overview.html",this.url+"/login.html");

        if(csrfToken == null || csrfToken.trim().equals("")){
            throw new SettingsFailedException();
        }

        String contents = retrieveUrlContents("/data/phone_voip.json",csrfToken,this.url+"/phone.html");

        if(contents == null || contents.trim().equals("")){
            throw new SettingsFailedException();
        }

        try{
            settings = H300sVoipSettings.createFromJson(contents);
        } catch (Exception e){
            this.exceptionHandler.handle(e);
            throw new SettingsFailedException();
        }


        return settings;
    }

    public void retrieveVoipCredentials()
    {
        try {
            boolean loginStatus = login();
            loginHandler.loginCallback(loginStatus);
            if (loginStatus) {
                H300sVoipSettings settings = retrieveVOIPSettings();
                settingsHandler.retrieveSettings(settings);
            }
        } catch (SettingsFailedException f){
            failedHandler.handler();
            exceptionHandler.handle(f);
        } catch (Exception e){
            exceptionHandler.handle(e);
        }
    }


}

它的主要目的是执行一系列HttpCalls,并检索H300s Sercomm路由器的voip凭据

该类通过以下活动运行:

package com.example.vodafone_fu_h300s.screens;

import androidx.appcompat.app.AppCompatActivity;

import android.content.Intent;
import android.os.Bundle;
import android.text.Editable;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.text.TextWatcher;

import com.example.vodafone_fu_h300s.R;
import com.example.vodafone_fu_h300s.logic.H300sVoipSettings;
import com.example.vodafone_fu_h300s.logic.Η300sCredentialsRetriever;

import kotlin.reflect.KFunction;

public class ConnectIntoRouterActivity extends AppCompatActivity implements View.OnClickListener, TextWatcher {

    private CredentialsRetriever retriever;

    private EditText url;
    private EditText admin;
    private EditText password;
    private Button submit;


    private class CredentialsRetriever extends Η300sCredentialsRetriever implements Runnable  {

        private ConnectIntoRouterActivity activity;

        public CredentialsRetriever(ConnectIntoRouterActivity activity)
        {
            super();
            this.activity = activity;
            this.setExceptionHandler((Exception e) -> {
                Log.e("Η300s",ConnectIntoRouterActivity.class+e.getMessage());
            });

            this.setLoginHandler((boolean loginStatus)->{
                if(!loginStatus){
                    Log.e("Η300s",ConnectIntoRouterActivity.class+" Login Failed");
                    this.activity.getSubmit().setEnabled(true);
                }
            });

            this.setSettingsHandler((H300sVoipSettings settings)->{
                this.activity.getSubmit().setEnabled(true);
                Intent displaySettings = new Intent(this.activity, DisplaySettingsActivity.class);
                displaySettings.putExtra("settings",settings);
                startActivity(displaySettings);
            });
        }

        public void run() {
            this.retrieveVoipCredentials();
        }

    }

    public Button getSubmit()
    {
        return this.submit;
    }

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

        Intent activityIntent = getIntent();

        String menu_url = activityIntent.getStringExtra("router_url");

        Button submit = (Button)findViewById(R.id.connect_btn);
        submit.setOnClickListener(this);
        this.submit = submit;

        this.retriever = new CredentialsRetriever(this);

        this.url = (EditText)findViewById(R.id.menu_url);
        url.setText(menu_url);
        url.addTextChangedListener(this);

        this.admin = (EditText)findViewById(R.id.username);
        admin.setText("admin");
        admin.addTextChangedListener(this);

        this.password = (EditText)findViewById(R.id.password);
        password.addTextChangedListener(this);

    }

    private void onUpdateForm() {
        String menu_url = this.url.getText().toString();
        String admin = this.admin.getText().toString();
        String password = this.password.getText().toString();

        if(menu_url.equals("")||admin.equals("")||password.equals("")){
            Button submit = (Button)findViewById(R.id.connect_btn);
            submit.setEnabled(false);
            return;
        }

        Button submit = (Button)findViewById(R.id.connect_btn);
        submit.setEnabled(true);
        this.retriever.setUrl(menu_url);
        this.retriever.setUsername(admin);
        this.retriever.setPassword(password);
    }

    @Override
    public void beforeTextChanged(CharSequence s, int start, int count, int after) {}

    @Override
    public void onTextChanged(CharSequence s, int start, int before, int count) {}

    @Override
    public void afterTextChanged(Editable s) {
        onUpdateForm();
    }

    @Override
    public void onClick(View v){

        Button submit = (Button)findViewById(R.id.connect_btn);
        submit.setEnabled(false);

        Thread thread = new Thread(this.retriever);
        thread.start();
    }
}
但一旦我按下活动呈现的以下表单上的提交:

我得到以下错误:

我还尝试了以下方法:

package com.example.vodafone_fu_h300s.screens;

import androidx.appcompat.app.AppCompatActivity;

import android.content.Intent;
import android.os.Bundle;
import android.text.Editable;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.text.TextWatcher;

import com.example.vodafone_fu_h300s.R;
import com.example.vodafone_fu_h300s.logic.H300sVoipSettings;
import com.example.vodafone_fu_h300s.logic.Η300sCredentialsRetriever;

import kotlin.reflect.KFunction;

public class ConnectIntoRouterActivity extends AppCompatActivity implements View.OnClickListener, TextWatcher {

    private CredentialsRetriever retriever;

    private EditText url;
    private EditText admin;
    private EditText password;
    private Button submit;


    private class CredentialsRetriever extends Η300sCredentialsRetriever implements Runnable  {

        private ConnectIntoRouterActivity activity;

        public CredentialsRetriever(ConnectIntoRouterActivity activity)
        {
            super();
            this.activity = activity;
            this.setExceptionHandler((Exception e) -> {
                Log.e("Η300s",ConnectIntoRouterActivity.class+e.getMessage());
            });

            this.setLoginHandler((boolean loginStatus)->{
                if(!loginStatus){
                    Log.e("Η300s",ConnectIntoRouterActivity.class+" Login Failed");
                    this.activity.getSubmit().setEnabled(true);
                }
            });

            this.setSettingsHandler((H300sVoipSettings settings)->{
                this.activity.getSubmit().setEnabled(true);
                Intent displaySettings = new Intent(this.activity, DisplaySettingsActivity.class);
                displaySettings.putExtra("settings",settings);
                startActivity(displaySettings);
            });
        }

        public void run() {
            this.retrieveVoipCredentials();
        }

    }

    public Button getSubmit()
    {
        return this.submit;
    }

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

        Intent activityIntent = getIntent();

        String menu_url = activityIntent.getStringExtra("router_url");

        Button submit = (Button)findViewById(R.id.connect_btn);
        submit.setOnClickListener(this);
        this.submit = submit;

        this.retriever = new CredentialsRetriever(this);

        this.url = (EditText)findViewById(R.id.menu_url);
        url.setText(menu_url);
        url.addTextChangedListener(this);

        this.admin = (EditText)findViewById(R.id.username);
        admin.setText("admin");
        admin.addTextChangedListener(this);

        this.password = (EditText)findViewById(R.id.password);
        password.addTextChangedListener(this);

    }

    private void onUpdateForm() {
        String menu_url = this.url.getText().toString();
        String admin = this.admin.getText().toString();
        String password = this.password.getText().toString();

        if(menu_url.equals("")||admin.equals("")||password.equals("")){
            Button submit = (Button)findViewById(R.id.connect_btn);
            submit.setEnabled(false);
            return;
        }

        Button submit = (Button)findViewById(R.id.connect_btn);
        submit.setEnabled(true);
        this.retriever.setUrl(menu_url);
        this.retriever.setUsername(admin);
        this.retriever.setPassword(password);
    }

    @Override
    public void beforeTextChanged(CharSequence s, int start, int count, int after) {}

    @Override
    public void onTextChanged(CharSequence s, int start, int before, int count) {}

    @Override
    public void afterTextChanged(Editable s) {
        onUpdateForm();
    }

    @Override
    public void onClick(View v){

        Button submit = (Button)findViewById(R.id.connect_btn);
        submit.setEnabled(false);

        runOnUiThread(this.retriever);
    }
}
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.vodafone_fu_h300s">

    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.INTERNET" />

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/Theme.VfuH300s"
        android:usesCleartextTraffic="true">
        <activity android:name=".screens.DisplaySettingsActivity"></activity>
        <activity android:name=".screens.ConnectIntoRouterActivity" />
        <activity android:name=".screens.InstructionsActivity" />
        <activity android:name=".screens.ErrorActivity" />
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>
但我得到了以下错误:

E/Η300s:class com.example.vodafone_fu_h300s.screens.connectionToRouterActivity创建视图层次结构的原始线程只能接触其视图

那么,如何运行线程并为任何事件提供回调,例如在事件发生错误的情况下,例如成功检索完整凭据

我的应用程序清单如下所示:

package com.example.vodafone_fu_h300s.screens;

import androidx.appcompat.app.AppCompatActivity;

import android.content.Intent;
import android.os.Bundle;
import android.text.Editable;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.text.TextWatcher;

import com.example.vodafone_fu_h300s.R;
import com.example.vodafone_fu_h300s.logic.H300sVoipSettings;
import com.example.vodafone_fu_h300s.logic.Η300sCredentialsRetriever;

import kotlin.reflect.KFunction;

public class ConnectIntoRouterActivity extends AppCompatActivity implements View.OnClickListener, TextWatcher {

    private CredentialsRetriever retriever;

    private EditText url;
    private EditText admin;
    private EditText password;
    private Button submit;


    private class CredentialsRetriever extends Η300sCredentialsRetriever implements Runnable  {

        private ConnectIntoRouterActivity activity;

        public CredentialsRetriever(ConnectIntoRouterActivity activity)
        {
            super();
            this.activity = activity;
            this.setExceptionHandler((Exception e) -> {
                Log.e("Η300s",ConnectIntoRouterActivity.class+e.getMessage());
            });

            this.setLoginHandler((boolean loginStatus)->{
                if(!loginStatus){
                    Log.e("Η300s",ConnectIntoRouterActivity.class+" Login Failed");
                    this.activity.getSubmit().setEnabled(true);
                }
            });

            this.setSettingsHandler((H300sVoipSettings settings)->{
                this.activity.getSubmit().setEnabled(true);
                Intent displaySettings = new Intent(this.activity, DisplaySettingsActivity.class);
                displaySettings.putExtra("settings",settings);
                startActivity(displaySettings);
            });
        }

        public void run() {
            this.retrieveVoipCredentials();
        }

    }

    public Button getSubmit()
    {
        return this.submit;
    }

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

        Intent activityIntent = getIntent();

        String menu_url = activityIntent.getStringExtra("router_url");

        Button submit = (Button)findViewById(R.id.connect_btn);
        submit.setOnClickListener(this);
        this.submit = submit;

        this.retriever = new CredentialsRetriever(this);

        this.url = (EditText)findViewById(R.id.menu_url);
        url.setText(menu_url);
        url.addTextChangedListener(this);

        this.admin = (EditText)findViewById(R.id.username);
        admin.setText("admin");
        admin.addTextChangedListener(this);

        this.password = (EditText)findViewById(R.id.password);
        password.addTextChangedListener(this);

    }

    private void onUpdateForm() {
        String menu_url = this.url.getText().toString();
        String admin = this.admin.getText().toString();
        String password = this.password.getText().toString();

        if(menu_url.equals("")||admin.equals("")||password.equals("")){
            Button submit = (Button)findViewById(R.id.connect_btn);
            submit.setEnabled(false);
            return;
        }

        Button submit = (Button)findViewById(R.id.connect_btn);
        submit.setEnabled(true);
        this.retriever.setUrl(menu_url);
        this.retriever.setUsername(admin);
        this.retriever.setPassword(password);
    }

    @Override
    public void beforeTextChanged(CharSequence s, int start, int count, int after) {}

    @Override
    public void onTextChanged(CharSequence s, int start, int before, int count) {}

    @Override
    public void afterTextChanged(Editable s) {
        onUpdateForm();
    }

    @Override
    public void onClick(View v){

        Button submit = (Button)findViewById(R.id.connect_btn);
        submit.setEnabled(false);

        runOnUiThread(this.retriever);
    }
}
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.vodafone_fu_h300s">

    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.INTERNET" />

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/Theme.VfuH300s"
        android:usesCleartextTraffic="true">
        <activity android:name=".screens.DisplaySettingsActivity"></activity>
        <activity android:name=".screens.ConnectIntoRouterActivity" />
        <activity android:name=".screens.InstructionsActivity" />
        <activity android:name=".screens.ErrorActivity" />
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>