簡體   English   中英

使用模擬器和HttpURLConnection的未知主機異常

[英]Unknown Host Exception using emulator and HttpURLConnection

我目前正處於在Android Studio上開發Android應用程序的最后階段。 構建了APK文件,以便在與Android Studio模擬器之一分開的設備上運行它們。 我選擇了Andy android模擬器。 我安裝了APK,但是當我嘗試登錄即連接到服務器時,出現未知主機異常,如下所示:

System.err: java.net.UnknownHostException: http://point_collector.netau.net/FetchData.php
System.err:     at libcore.net.http.HttpConnection$Address.<init>(HttpConnection.java:282)
System.err:     at libcore.net.http.HttpConnection.connect(HttpConnection.java:128)
System.err:     at libcore.net.http.HttpEngine.openSocketConnection(HttpEngine.java:316)
System.err:     at libcore.net.http.HttpEngine.connect(HttpEngine.java:311)
System.err:     at libcore.net.http.HttpEngine.sendSocketRequest(HttpEngine.java:290)
System.err:     at libcore.net.http.HttpEngine.sendRequest(HttpEngine.java:240)
System.err:     at libcore.net.http.HttpURLConnectionImpl.connect(HttpURLConnectionImpl.java:81)
System.err:     at libcore.net.http.HttpURLConnectionImpl.getOutputStream(HttpURLConnectionImpl.java:197)
System.err:     at com.jack.pointcollector.ServerRequests$GetDataAsyncTask.doInBackground(ServerRequests.java:169)
System.err:     at com.jack.pointcollector.ServerRequests$GetDataAsyncTask.doInBackground(ServerRequests.java:132)
com.jack.pointcollector W/System.err:     at android.os.AsyncTask$2.call(AsyncTask.java:287)
com.jack.pointcollector W/System.err:     at java.util.concurrent.FutureTask.run(FutureTask.java:234)
System.err:     at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:230)
com.jack.pointcollector W/System.err:     at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1080)
System.err:     at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:573)
System.err:     at java.lang.Thread.run(Thread.java:856)

服務器請求代碼如下:

public class ServerRequests {

    //Variables for this class
    //Process Dialog informs the user what is happening while thier request is being carried out
    //Connection timeout will be the time in milliseconds of how long the connection will last
    //Server address is the location of the PHP files
    ProgressDialog progressDialog;
    public static final int CONNECTION_TIMEOUT = 1000 * 15;
    public static final String SERVER_ADDRESS = "http://point_collector.netau.net/";


    public ServerRequests(Context context) {
        //process dialog requires the context of the class e.g. Register.this or Login.this
        progressDialog = new ProgressDialog(context);
        progressDialog.setCancelable(false);
        progressDialog.setTitle("Processing");
        progressDialog.setMessage("Please wait...");
    }
    public void storeUserData(User user, GetUserCallBack callBack) {
        //Process to write to the database to be performed in the background
        progressDialog.show();
        new StoreDataAsyncTask(user, callBack).execute();
    }
    public void fetchUserData(User user, GetUserCallBack callBack) {
        //Process to read from the database to be performed in the background
        progressDialog.show();
        new GetDataAsyncTask(user,callBack).execute();
    }


    public void storeChoreData(Chore chore, GetUserCallBack callBack){
        progressDialog.show();
        new StoreChoreAsyncTask(chore, callBack).execute();
    }

    public void storeRewardData(Reward reward, GetUserCallBack callBack){
        progressDialog.show();
        new StoreRewardAsyncTask(reward, callBack).execute();
    }

    //Creates a background thread to write to the data base
    public class StoreDataAsyncTask extends AsyncTask<Void, Void, Void> {
        //instance variables one for a user
        //GetUserCallBack is an interface which signals when the operation has been completed
        User user;
        GetUserCallBack userCallBack;

        public StoreDataAsyncTask(User user0, GetUserCallBack callBack0) {
            user = user0;
            userCallBack = callBack0;
        }
        @Override
        protected Void doInBackground(Void... params) {
            try {
                //The URL to be connected
                //Then we open the connection
                //Set the conditions the connection must follow
                URL url = new URL(SERVER_ADDRESS + "Register.php");
                HttpURLConnection conn = (HttpURLConnection) url.openConnection();
                conn.setReadTimeout(CONNECTION_TIMEOUT);
                conn.setConnectTimeout(CONNECTION_TIMEOUT);
                conn.setRequestMethod("POST");
                conn.setDoInput(true);
                conn.setDoOutput(true);

                //Identifies the objects to be passed for the PHP files
                Uri.Builder builder = new Uri.Builder()
                        .appendQueryParameter("username", user.username)
                        .appendQueryParameter("password", user.password)
                        .appendQueryParameter("email", user.email);
                //Determines whether the user is creating a parent or child account
                if(user.isParent) builder.appendQueryParameter("userType", "Parent");
                else builder.appendQueryParameter("userType", "Child");

                //Encodes the data for the PHP file
                String query = builder.build().getEncodedQuery();

                //Records entry
                Log.d("query", query);

                //Creates an output to send out the query
                //Then flushes the writer and closes all outputs
                OutputStream os = conn.getOutputStream();
                BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(os, "UTF-8"));
                writer.write(query);
                writer.flush();
                writer.close();
                os.close();
                //Gets the response code to ensure this was succesful.
                int code = conn.getResponseCode();
                Log.d("code", Integer.toString(code));
                conn.connect();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return null;
        }
        @Override
        protected void onPostExecute(Void aVoid) {
            //After the previous method executes we end the process dialog
            //and we return the user call back
            progressDialog.dismiss();
            userCallBack.complete(null);
            super.onPostExecute(aVoid);
        }
    }

    public class GetDataAsyncTask extends AsyncTask<Void, Void, User> {
        //instance variables one for a user
        //GetUserCallBack is an interface which signals when the operation has been completed
        User user;
        GetUserCallBack userCallBack;

        public GetDataAsyncTask(User user0, GetUserCallBack callBack0) {
            user = user0;
            userCallBack = callBack0;
        }
        @Override
        protected User doInBackground(Void... params) {
            //A HashMap to determine what we want to retrieve from the server
            //The URL is the location of the PHP file to validate a user
            HashMap<String, String> param = new HashMap<>();
            String requestURL = SERVER_ADDRESS+"FetchData.php";
            param.put("username", user.username);
            param.put("password", user.password);
            //Checks if a the user logging in is a parent or child
            if(user.isParent) param.put("userType", "Parent");
            else param.put("userType", "Child");

            URL url;
            User returnedUser = null;
            try {
                //Opens the connection to the PHP files
                //Sets the conditions of the connection
                url = new URL(requestURL);
                HttpURLConnection conn = (HttpURLConnection) url.openConnection();
                conn.setReadTimeout(CONNECTION_TIMEOUT);
                conn.setConnectTimeout(CONNECTION_TIMEOUT);
                conn.setRequestMethod("POST");
                conn.setDoInput(true);
                conn.setDoOutput(true);

                //Opens an output stream to send the data to be verified
                // and then closes the all output streams and flushes the output writer
                OutputStream os = conn.getOutputStream();
                BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(os, "UTF-8"));
                writer.write(getPostDataString(param));
                writer.flush();
                writer.close();
                os.close();
                //saves the response code to ensure connection was succesful
                int code = conn.getResponseCode();
                Log.d("code", Integer.toString(code));

                //Opens an input stream to retrieve verified data back from the server
                //Starts a String Builder to read the data off the input
                //Closes the BufferedReader once it has finished building the string
                InputStream responseStream = new BufferedInputStream(conn.getInputStream());
                BufferedReader responseStreamReader = new BufferedReader(new InputStreamReader(responseStream));
                String line;
                StringBuilder stringBuilder = new StringBuilder();
                while ((line = responseStreamReader.readLine()) != null) { stringBuilder.append(line);}
                responseStreamReader.close();

                String response = stringBuilder.toString();
                Log.d("response", response);
                if(response.contains("This is a parent")) {
                    user.isParent = true;
                }
                else user.isChild = true;



                //Creates a JSON object from the string
                JSONObject jsonResponse = new JSONObject(response);
                Log.d("length",Integer.toString(jsonResponse.length()));
                //Stores the verified user details if the response is not 0
                if(jsonResponse.length() > 0) {
                    if(user.isChild) {
                        int flag = jsonResponse.getInt("request_flag");
                        returnedUser = new User(user.username, user.password, flag);
                        Log.d("returned user", returnedUser.username);
                    }
                    else {
                        returnedUser = new User(user.username, user.password);
                        Log.d("returned user", returnedUser.username);

                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            return returnedUser;
        }
        private String getPostDataString(HashMap<String, String> params) throws UnsupportedEncodingException {
            //Correctly formats the data to be sent to the PHP file
            StringBuilder result = new StringBuilder();
            boolean first = true;
            for (Map.Entry<String, String> entry : params.entrySet()) {
                if (first) first = false;
                else result.append("&");
                result.append(URLEncoder.encode(entry.getKey(), "UTF-8"));
                result.append("=");
                result.append(URLEncoder.encode(entry.getValue(), "UTF-8"));
            }
            return result.toString();
        }
        @Override
        protected void onPostExecute(User returnedUser) {
            //After the previous method executes we end the process dialog
            //and we return the user call back and return the verified user
            progressDialog.dismiss();
            userCallBack.complete(returnedUser);
            super.onPostExecute(returnedUser);
        }
    }

    public class StoreChoreAsyncTask extends AsyncTask<Void, Void, Void> {
        //instance variables one for a chore
        //GetUserCallBack is an interface which signals when the operation has been completed
        Chore chore;
        GetUserCallBack userCallBack;

        public StoreChoreAsyncTask(Chore chore0, GetUserCallBack callBack0) {
            chore = chore0;
            userCallBack = callBack0;
        }
        @Override
        protected Void doInBackground(Void... params) {
            try {
                //The URL to be connected
                //Then we open the connection
                //Set the conditions the connection must follow
                URL url = new URL(SERVER_ADDRESS + "Chore.php");
                HttpURLConnection conn = (HttpURLConnection) url.openConnection();
                conn.setReadTimeout(CONNECTION_TIMEOUT);
                conn.setConnectTimeout(CONNECTION_TIMEOUT);
                conn.setRequestMethod("POST");
                conn.setDoInput(true);
                conn.setDoOutput(true);

                //Identifies the objects to be passed for the PHP files
                Uri.Builder builder = new Uri.Builder()
                        .appendQueryParameter("chore", chore.chore)
                        .appendQueryParameter("points", chore.points +"")
                        .appendQueryParameter("parent_name", chore.pname);


                //Encodes the data for the PHP file
                String query = builder.build().getEncodedQuery();

                //Records entry
                Log.d("query", query);

                //Creates an output to send out the query
                //Then flushes the writer and closes all outputs
                OutputStream os = conn.getOutputStream();
                BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(os, "UTF-8"));
                writer.write(query);
                writer.flush();
                writer.close();
                os.close();
                //Gets the response code to ensure this was succesful.
                int code = conn.getResponseCode();
                Log.d("code", Integer.toString(code));
                conn.connect();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return null;
        }
        @Override
        protected void onPostExecute(Void aVoid) {
            //After the previous method executes we end the process dialog
            //and we return the user call back
            progressDialog.dismiss();
            userCallBack.complete(null);
            super.onPostExecute(aVoid);
        }
    }

    public class StoreRewardAsyncTask extends AsyncTask<Void, Void, Void> {
        //instance variables one for a reward
        //GetUserCallBack is an interface which signals when the operation has been completed
        Reward reward;
        GetUserCallBack userCallBack;

        public StoreRewardAsyncTask(Reward reward0, GetUserCallBack callBack0) {
            reward = reward0;
            userCallBack = callBack0;
        }
        @Override
        protected Void doInBackground(Void... params) {
            try {
                //The URL to be connected
                //Then we open the connection
                //Set the conditions the connection must follow
                URL url = new URL(SERVER_ADDRESS + "Reward.php");
                HttpURLConnection conn = (HttpURLConnection) url.openConnection();
                conn.setReadTimeout(CONNECTION_TIMEOUT);
                conn.setConnectTimeout(CONNECTION_TIMEOUT);
                conn.setRequestMethod("POST");
                conn.setDoInput(true);
                conn.setDoOutput(true);

                //Identifies the objects to be passed for the PHP files
                Uri.Builder builder = new Uri.Builder()
                        .appendQueryParameter("reward", reward.reward)
                        .appendQueryParameter("child", reward.child)
                        .appendQueryParameter("points", reward.points +"")
                        .appendQueryParameter("parent", reward.pname);


                //Encodes the data for the PHP file
                String query = builder.build().getEncodedQuery();

                //Records entry
                Log.d("query", query);

                //Creates an output to send out the query
                //Then flushes the writer and closes all outputs
                OutputStream os = conn.getOutputStream();
                BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(os, "UTF-8"));
                writer.write(query);
                writer.flush();
                writer.close();
                os.close();
                //Gets the response code to ensure this was succesful.
                int code = conn.getResponseCode();
                Log.d("code", Integer.toString(code));
                conn.connect();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return null;
        }
        @Override
        protected void onPostExecute(Void aVoid) {
            //After the previous method executes we end the process dialog
            //and we return the user call back
            progressDialog.dismiss();
            userCallBack.complete(null);
            super.onPostExecute(aVoid);
        }
    }
}

我的Android清單文件中有正確的INTERNET權限,因為權限全部出現在android的應用程序設置中。 我進行了一些研究,發現URL可能下划線了嗎? 有人可以提供幫助嗎?

謝謝

https://code.google.com/p/android/issues/detail?id=37577

基本上,URL中的_是主機名中的無效字符(盡管不是文件名中的字符)。 某些瀏覽器支持它,但是會引起問題。 Android的默認http實現則沒有。 您要么需要更改url(首選),要么需要使用支持它的HTTP庫。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM