Ksoap2 не работает в Android 3.0, получая исключение NetworkOnMainThreadException

Ksoap2 не работает в Android 3.0. Logcat показывает исключение NetworkOnMainThreadException:

02-24 20:18:34.536: ERROR/AndroidRuntime(428): java.lang.RuntimeException: Unable to start activity ComponentInfo{com. Bill/com. Bill.Diag}: android.os.NetworkOnMainThreadException
02-24 20:18:34.536: ERROR/AndroidRuntime(428):     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1701)
02-24 20:18:34.536: ERROR/AndroidRuntime(428):     at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1717)
02-24 20:18:34.536: ERROR/AndroidRuntime(428):     at android.app.ActivityThread.access$1500(ActivityThread.java:123)
02-24 20:18:34.536: ERROR/AndroidRuntime(428):     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:984)
02-24 20:18:34.536: ERROR/AndroidRuntime(428):     at android.os.Handler.dispatchMessage(Handler.java:99)
02-24 20:18:34.536: ERROR/AndroidRuntime(428):     at android.os.Looper.loop(Looper.java:126)
02-24 20:18:34.536: ERROR/AndroidRuntime(428):     at android.app.ActivityThread.main(ActivityThread.java:3900)
02-24 20:18:34.536: ERROR/AndroidRuntime(428):     at java.lang.reflect.Method.invokeNative(Native Method)
02-24 20:18:34.536: ERROR/AndroidRuntime(428):     at java.lang.reflect.Method.invoke(Method.java:491)
02-24 20:18:34.536: ERROR/AndroidRuntime(428):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:841)
02-24 20:18:34.536: ERROR/AndroidRuntime(428):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:599)
02-24 20:18:34.536: ERROR/AndroidRuntime(428):     at dalvik.system.NativeStart.main(Native Method)
02-24 20:18:34.536: ERROR/AndroidRuntime(428): Caused by: android.os.NetworkOnMainThreadException
02-24 20:18:34.536: ERROR/AndroidRuntime(428):     at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1069)
02-24 20:18:34.536: ERROR/AndroidRuntime(428):     at dalvik.system.BlockGuard$WrappedNetworkSystem.connect(BlockGuard.java:368)
02-24 20:18:34.536: ERROR/AndroidRuntime(428):     at org.apache.harmony.luni.net.PlainSocketImpl.connect(PlainSocketImpl.java:208)
02-24 20:18:34.536: ERROR/AndroidRuntime(428):     at org.apache.harmony.luni.net.PlainSocketImpl.connect(PlainSocketImpl.java:431)
02-24 20:18:34.536: ERROR/AndroidRuntime(428):     at java.net.Socket.connect(Socket.java:901)
02-24 20:18:34.536: ERROR/AndroidRuntime(428):     at org.apache.harmony.luni.internal.net.www.protocol.http.HttpConnection.<init>(HttpConnection.java:75)
02-24 20:18:34.536: ERROR/AndroidRuntime(428):     at org.apache.harmony.luni.internal.net.www.protocol.http.HttpConnection.<init>(HttpConnection.java:48)
02-24 20:18:34.536: ERROR/AndroidRuntime(428):     at org.apache.harmony.luni.internal.net.www.protocol.http.HttpConnection$Address.connect(HttpConnection.java:304)
02-24 20:18:34.536: ERROR/AndroidRuntime(428):     at org.apache.harmony.luni.internal.net.www.protocol.http.HttpConnectionPool.get(HttpConnectionPool.java:89)
02-24 20:18:34.536: ERROR/AndroidRuntime(428):     at org.apache.harmony.luni.internal.net.www.protocol.http.HttpURLConnectionImpl.getHttpConnection(HttpURLConnectionImpl.java:292)
02-24 20:18:34.536: ERROR/AndroidRuntime(428):     at org.apache.harmony.luni.internal.net.www.protocol.http.HttpURLConnectionImpl.makeConnection(HttpURLConnectionImpl.java:274)
02-24 20:18:34.536: ERROR/AndroidRuntime(428):     at org.apache.harmony.luni.internal.net.www.protocol.http.HttpURLConnectionImpl.connect(HttpURLConnectionImpl.java:217)
02-24 20:18:34.536: ERROR/AndroidRuntime(428):     at org.ksoap2.transport.ServiceConnectionSE.connect(ServiceConnectionSE.java:46)
02-24 20:18:34.536: ERROR/AndroidRuntime(428):     at org.ksoap2.transport.HttpTransportSE.call(HttpTransportSE.java:68)
02-24 20:18:34.536: ERROR/AndroidRuntime(428):     at com.IsBill.Connection.Connect(Connection.java:53)
02-24 20:18:34.536: ERROR/AndroidRuntime(428):     at com.IsBill.Diagnos.FirstProv(Diagnos.java:385)
02-24 20:18:34.536: ERROR/AndroidRuntime(428):     at com.IsBill.Diagnos.onCreate(Diagnos.java:53)
02-24 20:18:34.536: ERROR/AndroidRuntime(428):     at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1048)
02-24 20:18:34.536: ERROR/AndroidRuntime(428):     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1665)
02-24 20:18:34.536: ERROR/AndroidRuntime(428):     ... 11 more

person user632576    schedule 24.02.2011    source источник
comment
Прочитайте здесь о NetworkOnMainThreadException.   -  person bigstones    schedule 24.02.2011
comment
Вы можете обернуть вызов ksoap в AsyncTask. Подробнее читайте здесь.   -  person Brad Eisenhauer    schedule 02.11.2011
comment
Ваш вывод о том, что ksoap не работает, неверен. ЛЮБОЙ сетевой трафик в потоке пользовательского интерфейса будет демонстрировать такое же поведение.   -  person Manfred Moser    schedule 21.12.2011


Ответы (3)


StrictMode включен в HoneyComb, отключите его, чтобы избежать NetworkOnMainThreadException

    StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
    StrictMode.setThreadPolicy(policy);

ОБНОВЛЕНИЕ:

другим способом обнаружения является существование strictMode с использованием класса StrictModeWrapper.

 private static boolean strictModeAvailable;

    // use the StrictModeWrapper to see if we are running on Android 2.3 or higher and StrictMode is available
    static {
        try {
            StrictModeWrapper.checkAvailable();
            strictModeAvailable = true;
        } catch (Throwable throwable) {
            strictModeAvailable = false;
        }
    }

Класс StrictModeWrapper

import android.os.StrictMode;

/**
 * StrictModeWrapper is a wrapper class for the android class android.os.StrictMode provided with Android 2.3 onwards.
 * It allows usage of StrictMode class on devices/emulators with Android 2.3 or higher, while providing an availability
 * check so that the code can stay in situ for lower platform versions. See the application class for usage.
 *
 * @author Manfred Moser <[email protected]>
 *
 * @see "http://android-developers.blogspot.com/2009/04/backward-compatibility-for-android.html"
 * @see "http://android-developers.blogspot.com/2010/12/new-gingerbread-api-strictmode.html"
 */
public class StrictModeWrapper {

    /* class initialization fails when this throws an exception */
   static {
       try {
           Class.forName("android.os.StrictMode", true, Thread.currentThread().getContextClassLoader());
       } catch (Exception ex) {
           throw new RuntimeException(ex);
       }
   }

    /**
     * Check if the class android.os.StrictMode is available at runtime.
     */
   public static void checkAvailable() {}


    /**
     * Call StrictMode.enableDefaults().
     */
    public static void enableDefaults() {
       StrictMode.enableDefaults();
    }

    // all the implementation below is not tested but it should work ... feel free to check and send me fixes..
    public static  void setThreadPolicy(android.os.StrictMode.ThreadPolicy policy) {
        StrictMode.setThreadPolicy(policy);
    }


    public static  android.os.StrictMode.ThreadPolicy getThreadPolicy() {
        return StrictMode.getThreadPolicy();
    }

    public static  android.os.StrictMode.ThreadPolicy allowThreadDiskWrites() {
        return StrictMode.allowThreadDiskWrites();
    }

    public static  android.os.StrictMode.ThreadPolicy allowThreadDiskReads() {
        return StrictMode.allowThreadDiskReads();
    }

    public static  void setVmPolicy(android.os.StrictMode.VmPolicy policy) {
        StrictMode.setVmPolicy(policy);
    }

    public static android.os.StrictMode.VmPolicy getVmPolicy() {
        return StrictMode.getVmPolicy();
    }

    public static final class ThreadPolicyWrapper
    {
        public static final class BuilderWrapper
        {
            StrictMode.ThreadPolicy.Builder builderInstance;

            public  BuilderWrapper() {
                    builderInstance = new StrictMode.ThreadPolicy.Builder();
            }

            public  BuilderWrapper(android.os.StrictMode.ThreadPolicy policy) {
                    builderInstance = new StrictMode.ThreadPolicy.Builder(policy);
            }

            public android.os.StrictMode.ThreadPolicy.Builder detectAll() {
                return builderInstance.detectAll();
            }

            public android.os.StrictMode.ThreadPolicy.Builder permitAll() {
                return builderInstance.permitAll();
            }

            public android.os.StrictMode.ThreadPolicy.Builder detectNetwork() {
                return builderInstance.detectNetwork();
            }

            public android.os.StrictMode.ThreadPolicy.Builder permitNetwork() {
                return builderInstance.permitNetwork();
            }

            public android.os.StrictMode.ThreadPolicy.Builder detectDiskReads() {
                return builderInstance.detectDiskReads();
            }

            public android.os.StrictMode.ThreadPolicy.Builder permitDiskReads() {
                return builderInstance.permitDiskReads();
            }

            public android.os.StrictMode.ThreadPolicy.Builder detectDiskWrites() {
                return builderInstance.detectDiskWrites();
            }

            public android.os.StrictMode.ThreadPolicy.Builder permitDiskWrites() {
                return builderInstance.permitDiskWrites();
            }

            public android.os.StrictMode.ThreadPolicy.Builder penaltyDialog() {
                return builderInstance.penaltyDialog();
            }

            public android.os.StrictMode.ThreadPolicy.Builder penaltyDeath() {
                return builderInstance.penaltyDeath();
            }

            public android.os.StrictMode.ThreadPolicy.Builder penaltyLog() {
                return builderInstance.penaltyLog();
            }

            public android.os.StrictMode.ThreadPolicy.Builder penaltyDropBox() {
                return builderInstance.penaltyDropBox();
            }

            public android.os.StrictMode.ThreadPolicy build() {
                return builderInstance.build();
            }
        }
    }

    public static final class VmPolicyWrapper {
        public static final class BuilderWrapper {
            private StrictMode.VmPolicy.Builder builderInstance;

            public BuilderWrapper() {
                builderInstance = new StrictMode.VmPolicy.Builder();
            }

            public android.os.StrictMode.VmPolicy.Builder detectAll() {
                return builderInstance.detectAll();
            }

            public android.os.StrictMode.VmPolicy.Builder detectLeakedSqlLiteObjects() {
                return builderInstance.detectLeakedSqlLiteObjects();
            }

            public android.os.StrictMode.VmPolicy.Builder penaltyDeath() {
                return builderInstance.penaltyDeath();
            }

            public android.os.StrictMode.VmPolicy.Builder penaltyLog() {
                return builderInstance.penaltyLog();
            }

            public android.os.StrictMode.VmPolicy.Builder penaltyDropBox() {
                return builderInstance.penaltyDropBox();
            }

            public android.os.StrictMode.VmPolicy build() {
                return builderInstance.build();
            }
        }
    }
    // add more wrapping as desired..
}
person Jorgesys    schedule 02.11.2011
comment
Правильно.. и ИКС. Это будет зависеть от того, разрешает ли производитель оборудования эту настройку. По умолчанию они, вероятно, не будут, так как это так в восходящем потоке. В любом случае... это в лучшем случае обходной путь. Просто сделайте асинтаск. - person Manfred Moser; 21.12.2011

Вам нужно выполнять любую сетевую операцию в отдельном потоке, а не в потоке пользовательского интерфейса. Самый простой способ сделать это — использовать AsyncTask.

person Manfred Moser    schedule 20.12.2011

Для этого сетевая операция должна обрабатываться в новом потоке
. Вы должны вызвать запрос ksoap в классе задач AsyncTask в вашей Asynctask.

public class Get extends AsyncTask<Void, Void, String> {
@Override
protected String doInBackground(Void... arg) {

   //your KSOAP request code
}

}

person Himesh goswami    schedule 10.05.2013