0

我正在构建一个独立于学校的时间表应用程序。我现在处于我的应用程序的测试阶段,它在 android 版本 2.3.6 上运行良好

但是,当我尝试在虚拟设备上运行它时,它会像往常一样启动。

但是,在点击应该执行登录过程的按钮后,应用程序返回以下错误:

01-05 00:52:23.180: E/AndroidRuntime(858): FATAL EXCEPTION: main
01-05 00:52:23.180: E/AndroidRuntime(858): java.lang.IllegalStateException: Could not execute method of the activity
01-05 00:52:23.180: E/AndroidRuntime(858):  at android.view.View$1.onClick(View.java:3597)
01-05 00:52:23.180: E/AndroidRuntime(858):  at android.view.View.performClick(View.java:4202)
01-05 00:52:23.180: E/AndroidRuntime(858):  at android.view.View$PerformClick.run(View.java:17340)
01-05 00:52:23.180: E/AndroidRuntime(858):  at android.os.Handler.handleCallback(Handler.java:725)
01-05 00:52:23.180: E/AndroidRuntime(858):  at android.os.Handler.dispatchMessage(Handler.java:92)
01-05 00:52:23.180: E/AndroidRuntime(858):  at android.os.Looper.loop(Looper.java:137)
01-05 00:52:23.180: E/AndroidRuntime(858):  at android.app.ActivityThread.main(ActivityThread.java:5039)
01-05 00:52:23.180: E/AndroidRuntime(858):  at java.lang.reflect.Method.invokeNative(Native Method)
01-05 00:52:23.180: E/AndroidRuntime(858):  at java.lang.reflect.Method.invoke(Method.java:511)
01-05 00:52:23.180: E/AndroidRuntime(858):  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793)
01-05 00:52:23.180: E/AndroidRuntime(858):  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560)
01-05 00:52:23.180: E/AndroidRuntime(858):  at dalvik.system.NativeStart.main(Native Method)
01-05 00:52:23.180: E/AndroidRuntime(858): Caused by: java.lang.reflect.InvocationTargetException
01-05 00:52:23.180: E/AndroidRuntime(858):  at java.lang.reflect.Method.invokeNative(Native Method)
01-05 00:52:23.180: E/AndroidRuntime(858):  at java.lang.reflect.Method.invoke(Method.java:511)
01-05 00:52:23.180: E/AndroidRuntime(858):  at android.view.View$1.onClick(View.java:3592)
01-05 00:52:23.180: E/AndroidRuntime(858):  ... 11 more
01-05 00:52:23.180: E/AndroidRuntime(858): Caused by: android.os.NetworkOnMainThreadException
01-05 00:52:23.180: E/AndroidRuntime(858):  at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1117)
01-05 00:52:23.180: E/AndroidRuntime(858):  at java.net.InetAddress.lookupHostByName(InetAddress.java:385)
01-05 00:52:23.180: E/AndroidRuntime(858):  at java.net.InetAddress.getAllByNameImpl(InetAddress.java:236)
01-05 00:52:23.180: E/AndroidRuntime(858):  at java.net.InetAddress.getAllByName(InetAddress.java:214)
01-05 00:52:23.180: E/AndroidRuntime(858):  at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:137)
01-05 00:52:23.180: E/AndroidRuntime(858):  at org.apache.http.impl.conn.AbstractPoolEntry.open(AbstractPoolEntry.java:164)
01-05 00:52:23.180: E/AndroidRuntime(858):  at org.apache.http.impl.conn.AbstractPooledConnAdapter.open(AbstractPooledConnAdapter.java:119)
01-05 00:52:23.180: E/AndroidRuntime(858):  at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:360)
01-05 00:52:23.180: E/AndroidRuntime(858):  at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:555)
01-05 00:52:23.180: E/AndroidRuntime(858):  at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:487)
01-05 00:52:23.180: E/AndroidRuntime(858):  at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:465)
01-05 00:52:23.180: E/AndroidRuntime(858):  at com.mattle.timetable.JSONParser.getJSONFromUrl(JSONParser.java:42)
01-05 00:52:23.180: E/AndroidRuntime(858):  at com.mattle.timetable.LoginView.doLogin(LoginView.java:129)
01-05 00:52:23.180: E/AndroidRuntime(858):  ... 14 more

我使用此页面中的 jsonparser 类:http ://www.androidhive.info/2012/01/android-json-parsing-tutorial/

我的登录代码如下所示:

package com.mattle.timetable;

import static com.mattle.timetable.MainActivity.PREFS_NAME;

import java.io.BufferedReader;
import java.math.BigInteger;
import java.net.URI;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.List;

import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.json.JSONException;
import org.json.JSONObject;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.EditText;

import com.google.android.gcm.GCMRegistrar;
import com.markupartist.android.widget.ActionBar;

public class LoginView extends Activity {

private JSONParser jsonParser;

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

    ActionBar actionBar = (ActionBar) findViewById(R.id.actionbar);
    // You can also assign the title programmatically by passing a
    // CharSequence or resource id.
    actionBar.setTitle("Jouw Lesrooster");
}

@Override
public void onBackPressed() {

    Intent startMain = new Intent(Intent.ACTION_MAIN);
    startMain.addCategory(Intent.CATEGORY_HOME);
    startMain.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    startActivity(startMain);

}

 private String getStringResourceByName(String aString)
    {
      String packageName = "com.mattle.timetable";
      int resId = getResources().getIdentifier(aString, "string", packageName);
      return getString(resId);
    }

private boolean haveNetworkConnection() {
    boolean haveConnectedWifi = false;
    boolean haveConnectedMobile = false;

    ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
    NetworkInfo[] netInfo = cm.getAllNetworkInfo();
    for (NetworkInfo ni : netInfo) {
        if (ni.getTypeName().equalsIgnoreCase("WIFI"))
            if (ni.isConnected())
                haveConnectedWifi = true;
        if (ni.getTypeName().equalsIgnoreCase("MOBILE"))
            if (ni.isConnected())
                haveConnectedMobile = true;
    }
    return haveConnectedWifi || haveConnectedMobile;
}

public String sha1(String s) {
    MessageDigest digest = null;
            try {
                    digest = MessageDigest.getInstance("SHA-1");
            } catch (NoSuchAlgorithmException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
            }
    digest.reset();
    byte[] data = digest.digest(s.getBytes());
    return String.format("%0" + (data.length*2) + "X", new BigInteger(1, data));
}

public void doRegister(View view) {

    Intent gotoregister = new Intent(this, Register.class);
    startActivity(gotoregister);

}

public void doLogin(View view) throws Exception {

    BufferedReader in = null;

    try{

        if(haveNetworkConnection()) {

            EditText getusername = (EditText) findViewById(R.id.username);
            String username = getusername.getText().toString();

            EditText getpassword = (EditText) findViewById(R.id.password);
            String password = sha1(getpassword.getText().toString() + "SOMESALTHERENVM");

        HttpClient client = new DefaultHttpClient();
        URI website = new URI("SOMEURL");
        HttpPost request = new HttpPost();
        List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(2);
        nameValuePairs.add(new BasicNameValuePair("login_username", username));
        nameValuePairs.add(new BasicNameValuePair("login_password", password));

        jsonParser = new JSONParser();
        JSONObject json = jsonParser.getJSONFromUrl("http://jouwlesrooster.nl/api/doLogin/", nameValuePairs);

        try {

            if (json.getString("success") != null) {
                String res = json.getString("success");
                if(Integer.parseInt(res) == 1){
            //Log.d("MYTAG", "Print this in logcat...");
            //Log.d("MYTAG", username + " ddd " + password);

            getSharedPreferences("myLoginshit",MODE_PRIVATE)
            .edit()
            .putString("Username", username)
            .putString("Password", password)
            .commit();

            GCMRegistrar.checkDevice(this);
            GCMRegistrar.checkManifest(this);
            String regId = GCMRegistrar.getRegistrationId(this);
            if (regId.equals("")) {
              GCMRegistrar.register(this, "***");
              Log.i("test", "ddd");
             // Toast.makeText(getApplicationContext(), "", Toast.LENGTH_LONG).show();
            } else {
            //  Toast.makeText(getApplicationContext(), "Already registered", Toast.LENGTH_LONG).show();
             // Log.v(TAG, "Already registered");
            }

            Intent gotomenu = new Intent(this, Menu.class);
            startActivity(gotomenu);

            }
            }

        } finally {

        }

        } else {


        }

    }finally{
        if (in != null) {
            try{
                in.close();

            }catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}
}

我该如何解决这个恼人的错误?

谢谢马特尔

4

3 回答 3

1

问题在于doLogin()- 方法,它在 UI 线程上执行网络任务。

查看您的 StackTrace,您可以看到:

Caused by: android.os.NetworkOnMainThreadException

这是自Android“冰淇淋三明治”以来抛出的。要摆脱它,请将网络代码放入AsyncTask.

请参阅这个较旧的问题:如何修复 android.os.NetworkOnMainThreadException?

于 2013-01-05T01:32:34.503 回答
1

看起来您doLogin()从 UI 线程执行您的方法(可能onClick是按钮中的某些方法)。

您不应该这样做,因为网络访问可能很慢并且可能会冻结 UI。请改用 AsyncTask 类(请参阅http://developer.android.com/reference/android/os/AsyncTask.html

于 2013-01-05T01:35:33.017 回答
1
  • 让 UI 在 UI-Thread 上工作,Non-UI 在 Non-UI Thread 上工作总是更好的做法,但是从 HoneyComb 版本的 Android 开始,它成为了一项法律,不允许在 UI 线程中进行任何网络操作

  • 在您的情况下, doLogin() 是一个阻塞调用,您从 UI 线程调用它,它应该在非 UI 线程上。

  • 要摆脱这种情况,请使用AsyncTaskThread。
于 2013-01-05T05:24:45.470 回答