java - जेली बीन पर सॉकेट इनपुट स्ट्रीम नहीं पढ़ सकता




android sockets (5)

BufferedReader और PrintWriter का उपयोग मेरे लिए सभी संस्करणों पर काम करता है और किसी भी संचार प्रोटोकॉल के माध्यम से आप जो भी चाहते हैं उसे भेजने और प्राप्त करने के लिए बेहद सुविधाजनक है। अपने पृष्ठभूमि धागे को शुरू करते समय उन्हें सदस्य चर के रूप में सहेजने का प्रयास करें:

mInput = new BufferedReader(new InputStreamReader(
            socket.getInputStream()));
mOutput = new PrintWriter(new BufferedWriter(
            new OutputStreamWriter(socket.getOutputStream())), true);

एसिंक्रोनस संचार के लिए आपका पृष्ठभूमि धागा ऐसा दिखाई दे सकता है:

@Override
public final void run() {
    while (!Thread.currentThread().isInterrupted()) {
        if (mInput == null) {
            break;
        }
        String message = null;
        try {
            message = mInput.readLine();
        } catch (IOException e) {
            // handle the exception as you like
            break;
        }
        if (Thread.currentThread().isInterrupted()) {
            // thread was interrupted while reading
            break;
        } else if (message != null) {
            // handle the message as you like
        }
    }
}

संदेश भेजने के लिए एक और पृष्ठभूमि धागा का प्रयोग करें:

@Override
public void run() {
    if (mOutput != null) {
        mOutput.println(<message to be );
        if (mOutput == null) {
            // the above thread was interrupted while writing
        } else if (!mOutput.checkError()) {
            // everything went fine
        } else {
            // handle the exception
        }
    }
}

साथ ही, आपको यह सुनिश्चित करने के लिए बाहर से स्ट्रीम को बंद करना होगा कि रीडलाइन हमेशा के लिए अवरुद्ध नहीं होती है:

try {
    mOutput.close();
    mInput.close();
    mOutput = null;
    mInput = null;
} catch (IOException e) {
    // log the exception
}

अब, चूंकि आप टीसीपी सॉकेट का उपयोग कर रहे हैं, ऐसा हो सकता है कि सॉकेट वास्तव में मर चुका है और रीडलाइन अभी भी अवरुद्ध है। आपको इसे पहचानना होगा और उपरोक्त की तरह स्ट्रीम को बंद करना होगा। इसके लिए, आपको एक और धागा (ओह ठीक) जोड़ना होगा जो समय-समय पर जीवित-संदेश भेजता है। यदि एक्स सेकंड के लिए रिमोट डिवाइस से कोई संदेश प्राप्त नहीं हुआ है, तो उसे स्ट्रीम बंद करना होगा।

यह पूरा दृष्टिकोण सुनिश्चित करता है कि सॉकेट बंद है और सभी धागे सभी परिस्थितियों में खत्म हो जाते हैं। निस्संदेह आप पाठक-थ्रेड को हटाकर और पाठक-थ्रेड के अंदर println () सहित, सिंक्रनाइज़ेशन को सिंक्रोनस कर सकते हैं। मुझे उम्मीद है कि आपकी मदद करता है (भले ही उत्तर 8 महीने देर हो जाए)।

मेरे पास एक टीसीपी सॉकेट कनेक्शन है जो एंड्रॉइड 2.3 पर अच्छा काम करता है लेकिन अब एंड्रॉइड 4.1 पर कुछ समस्याएं आ रही हैं। समस्या यह है कि InputStream.read () विधि हमेशा -1 (अवरुद्ध किए बिना) लौटाती है, जैसे कनेक्शन बंद है।

सॉकेट बनाना:

SocketFactory socketFactory = SocketFactory.getDefault();
Socket socket = socketFactory.createSocket("c.whatsapp.net", 5222);
socket.setSoTimeout(3*60*1000);
socket.setTcpNoDelay(true);

इनपुट और आउटपुट स्ट्रीम को पुनर्प्राप्त करना और कुछ प्रारंभिक डेटा लिखना:

InputStream inputStream = new BufferedInputStream(socket.getInputStream());
OutputStream outputStream = new BufferedOutputStream(socket.getOutputStream());

outputStream.write(87);
outputStream.write(65);
outputStream.write(1);
outputStream.write(2);
outputStream.flush();

फिर, यह स्थिति हमेशा अवरुद्ध किए बिना गुजरती है:

int c = inputStream.read();
if (c < 0) {
    Log.d(TAG, "End of stream");
}

यह कोड पृष्ठभूमि धागे में चल रहा है । और यह जिंजरब्रेड पर काम कर रहा था।

प्रत्यक्ष धाराओं के बजाय इनपुटस्ट्रीम रीडर और आउटपुटस्ट्रीमवाइटर का उपयोग करने का प्रयास किया - कोई प्रभाव नहीं।



दोस्त,

inputStream.readLine(); प्रयास करें inputStream.readLine(); (यानी) DataInputStream.readLine(); (बहिष्कृत विधि)

यह मेरे लिए काम किया ...


मुझे एक समान समस्या है और इस तरह के कामकाज के साथ इसे ठीक किया गया है

private static ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(1);

private static class WatchDog implements Runnable{
    private Thread thread = Thread.currentThread();

    public void run() {
        Log.d(LOG_TAG, "Interrupting read due to timeout");
        thread.interrupt();
    }
}

private void read(InputStream in, ByteBuffer bb, long waitTime) throws IOException {
    int startingPos = bb.position();
    long timeout = System.currentTimeMillis() + RESPONSE_TIMEOUT;


    ScheduledFuture<?> watchdogFuture = executor.schedule(new WatchDog(), RESPONSE_TIMEOUT, TimeUnit.MILLISECONDS);
    try {
        while(System.currentTimeMillis() < timeout && bb.hasRemaining()){ //workaround fixing timeout after 1ms
            try{
                int read = in.read(bb.array(), bb.position(), bb.remaining());
                if(read > 0){
                    bb.position(bb.position()+read);
                }
            } catch(SocketTimeoutException e){}
            if(bb.hasRemaining()){
                Thread.sleep(5);
            }
        }
        watchdogFuture.cancel(true);
    } catch (InterruptedException e) {}


    if(bb.hasRemaining()){
        throw new SocketTimeoutException("Unable to read requested bytes: " 
                + (bb.position()-startingPos) + "/" +  (bb.limit()-startingPos)
                + " after " + (System.currentTimeMillis() - timeout + RESPONSE_TIMEOUT) + "ms");
    }
}

मैंने पहले भी यही त्रुटि देखी है, हालांकि यह जवाब ऑफटॉपिक रूप से एक मौका दे सकता है और अगर यह काम करता है तो मुझे बताएं, कुछ कारणों से सॉकेट को जेलीबीन पर अजीब व्यवहार हो रहा है, भले ही वे कम एंड्रॉइड संस्करणों में पूरी तरह से ठीक काम कर रहे हों, जिस तरह से मैंने इस मुद्दे को तय किया था, लक्ष्य एसडीकेवर्सन को जेली बीन के साथ-साथ परियोजना के एंड्रॉइड गुणों के तहत प्रोजेक्ट बिल्ड लक्ष्य को स्थानांतरित करना था, कोड की एक पंक्ति को संशोधित नहीं किया था, और किसी कारण से यह चाल है .. ।

उम्मीद है की यह मदद करेगा।

सादर!





android-4.2-jelly-bean