23252


ListViewで写真一覧を作っており、写真はOkHttpというライブラリを用いてネットから取得するようにしています。

例えば、全50枚あるリストを勢い良くスクロールしている途中(序盤や中盤など)でタイトルに書いた例外が発生することがあります。  
(ListViewが表示されてすぐスクロール開始したなら発生しない？)  
キャンセル処理を行った時とその例外発生した時のImageViewのhashCode・読み込みURLを比較してみたところ、キャンセル処理を行ったかどうかにかかわらず発生するようです。  
その例外は何が要因で発生するものなのでしょうか？

ちなみにOSはAndroid 4.4.2を使用しています。  
その時の例外は以下の通りです。

[code]

    javax.net.ssl.SSLException: SSL handshake aborted: ssl=0x648aa828: I/O error during system call, Bad file number
        at com.android.org.conscrypt.NativeCrypto.SSL_do_handshake(Native Method)                                   
        at com.android.org.conscrypt.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:405)                   
        at okhttp3.internal.io.RealConnection.connectTls(RealConnection.java:195)                                   
        at okhttp3.internal.io.RealConnection.connectSocket(RealConnection.java:148)                                
        at okhttp3.internal.io.RealConnection.connect(RealConnection.java:111)                                      
        at okhttp3.internal.http.StreamAllocation.findConnection(StreamAllocation.java:188)                         
        at okhttp3.internal.http.StreamAllocation.findHealthyConnection(StreamAllocation.java:127)                  
        at okhttp3.internal.http.StreamAllocation.newStream(StreamAllocation.java:97)                               
        at okhttp3.internal.http.HttpEngine.connect(HttpEngine.java:289)                                            
        at okhttp3.internal.http.HttpEngine.sendRequest(HttpEngine.java:241)                                        
        at okhttp3.RealCall.getResponse(RealCall.java:240)                                                          
        at okhttp3.RealCall$ApplicationInterceptorChain.proceed(RealCall.java:198)                                  
        at okhttp3.RealCall.getResponseWithInterceptorChain(RealCall.java:160)                                      
        at okhttp3.RealCall.access$100(RealCall.java:30)                                                            
        at okhttp3.RealCall$AsyncCall.execute(RealCall.java:127)                                                    
        at okhttp3.internal.NamedRunnable.run(NamedRunnable.java:32)                                                
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
[/code]

読み込みコードは以下の通りです。

[code]

        /**
         * URLから写真をロードしてセット.  
    
         * 写真はViewに対して任意に設定したサイズでロードされる。
         *
         * @param photoUrl 写真取得に使用するURL
         */
        protected void loadPhoto(final String photoUrl) {
            if (getTag() != null) {
                ((Call) getTag()).cancel();
            }
            setImageResource(R.drawable.loading_animation);
            ((AnimationDrawable) getDrawable()).start();
            Request request = new Request.Builder()
                    .url(photoUrl)
                    .get()
                    .build();
    
            OkHttpClient client = new OkHttpClient();
            Call call = client.newCall(request);
            setTag(call);
            call.enqueue(new Callback() {
                /**
                 * リクエストキャンセル・接続の問題・タイムアウトのために実行できなった場合
                 *
                 * @param call
                 * @param e エラー内容
                 */
                @Override
                public void onFailure(Call call, IOException e) {
                    setTag(null); //通信終了
                    e.printStackTrace();
                    if (e instanceof SocketException) {
                        //キャンセル要求による反応は何もしない
                        return;
                    }
                    //それ以外は接続切れ扱い
                    Handler handler = new Handler(Looper.getMainLooper());
                    handler.post(new Runnable() {
                        @Override
                        public void run() {
                            setImageResource(R.drawable.error);
    
                        }
                    });
                    EventBus.getDefault().post(UserEvent.connectionError(""));
                }
    
                /**
                 * 応答が正常に返された場合
                 * エラーステータスも含む
                 *
                 * @param call
                 * @param response リクエストの結果
                 */
                @Override
                public void onResponse(Call call, Response response) {
                    setTag(null);
                    if (!response.isSuccessful()) {
                        EventBus.getDefault().post(UserEvent.connectionError(String.valueOf(response.code())));
                        return;
                    }
                    InputStream inputStream = response.body().byteStream();
                    final Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
                    Handler handler = new Handler(Looper.getMainLooper());
                    handler.post(new Runnable() {
                        @Override
                        public void run() {
                            setImageBitmap(bitmap);
                        }
                    });
                    response.body().close();
                }
            });
        }
[/code]


CC BY-SA 3.0
2016-03-18T08:05:44.083
23251
2016-03-18T08:26:10.267
9710
question
android
SSLException: SSL handshake abortedが発生する要因を知りたい


SSLの通信が途中で切断されているように見受けられます。

勢い良くスクロールしている途中に発生するということなので、短時間で多数のアクセスになり、取得先のサーバから切断された可能性があります。(おそらくTCPレベルで切断されているので、tcpdump
などで確かめてみると良いかもしれません。)


CC BY-SA 3.0
2016-03-18T08:26:10.267
23252
2016-03-18T08:26:10.267
76
23251
answer