157d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton/*
22ef360deaff9f17aa72d5749ceee283cc80897afBen Dodson * Copyright (C) 2011 The Android Open Source Project
357d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton *
457d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton * Licensed under the Apache License, Version 2.0 (the "License");
557d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton * you may not use this file except in compliance with the License.
657d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton * You may obtain a copy of the License at
757d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton *
857d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton *      http://www.apache.org/licenses/LICENSE-2.0
957d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton *
1057d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton * Unless required by applicable law or agreed to in writing, software
1157d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton * distributed under the License is distributed on an "AS IS" BASIS,
1257d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1357d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton * See the License for the specific language governing permissions and
1457d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton * limitations under the License.
1557d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton */
1657d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
17ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamiltonpackage com.android.nfc.ndefpush;
1857d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
194a61d3b45e81c0070538f94747a70a49c78f12faJeff Hamiltonimport com.android.nfc.DeviceHost.LlcpSocket;
204a61d3b45e81c0070538f94747a70a49c78f12faJeff Hamiltonimport com.android.nfc.LlcpException;
214a61d3b45e81c0070538f94747a70a49c78f12faJeff Hamiltonimport com.android.nfc.NfcService;
224a61d3b45e81c0070538f94747a70a49c78f12faJeff Hamilton
232ef360deaff9f17aa72d5749ceee283cc80897afBen Dodsonimport android.nfc.NdefMessage;
242ef360deaff9f17aa72d5749ceee283cc80897afBen Dodsonimport android.util.Log;
252ef360deaff9f17aa72d5749ceee283cc80897afBen Dodson
2657d376f1ee1a3939977b95759525585abb9601fbJeff Hamiltonimport java.io.IOException;
27ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamiltonimport java.util.Arrays;
2857d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
2957d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton/**
3057d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton * Simple client to push the local NDEF message to a server on the remote side of an
312ef360deaff9f17aa72d5749ceee283cc80897afBen Dodson * LLCP connection, using the Android Ndef Push Protocol.
3257d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton */
332ef360deaff9f17aa72d5749ceee283cc80897afBen Dodsonpublic class NdefPushClient {
34ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton    private static final String TAG = "NdefPushClient";
35bcccb386fe1dc20401b88ab0b0e493a8dbe7615cSylvain Fonteneau    private static final int MIU = 128;
3657d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton    private static final boolean DBG = true;
3757d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
38d2d5dddf17ac2008547172cd72faa034a89d569bJeff Hamilton    public boolean push(NdefMessage msg) {
392ef360deaff9f17aa72d5749ceee283cc80897afBen Dodson        NfcService service = NfcService.getInstance();
402ef360deaff9f17aa72d5749ceee283cc80897afBen Dodson
412ef360deaff9f17aa72d5749ceee283cc80897afBen Dodson        // We only handle a single immediate action for now
42d2d5dddf17ac2008547172cd72faa034a89d569bJeff Hamilton        NdefPushProtocol proto = new NdefPushProtocol(msg, NdefPushProtocol.ACTION_IMMEDIATE);
43d2d5dddf17ac2008547172cd72faa034a89d569bJeff Hamilton        byte[] buffer = proto.toByteArray();
442ef360deaff9f17aa72d5749ceee283cc80897afBen Dodson        int offset = 0;
452ef360deaff9f17aa72d5749ceee283cc80897afBen Dodson        int remoteMiu;
462ef360deaff9f17aa72d5749ceee283cc80897afBen Dodson        LlcpSocket sock = null;
472ef360deaff9f17aa72d5749ceee283cc80897afBen Dodson        try {
482ef360deaff9f17aa72d5749ceee283cc80897afBen Dodson            if (DBG) Log.d(TAG, "about to create socket");
492ef360deaff9f17aa72d5749ceee283cc80897afBen Dodson            // Connect to the my tag server on the remote side
502ef360deaff9f17aa72d5749ceee283cc80897afBen Dodson            sock = service.createLlcpSocket(0, MIU, 1, 1024);
512ef360deaff9f17aa72d5749ceee283cc80897afBen Dodson            if (sock == null) {
522ef360deaff9f17aa72d5749ceee283cc80897afBen Dodson                throw new IOException("Could not connect to socket.");
532094515fca0cfa0ac87e9cc260d3953d416afe3eJason parks            }
542ef360deaff9f17aa72d5749ceee283cc80897afBen Dodson            if (DBG) Log.d(TAG, "about to connect to service " + NdefPushServer.SERVICE_NAME);
554a61d3b45e81c0070538f94747a70a49c78f12faJeff Hamilton            sock.connectToService(NdefPushServer.SERVICE_NAME);
562ef360deaff9f17aa72d5749ceee283cc80897afBen Dodson
574a61d3b45e81c0070538f94747a70a49c78f12faJeff Hamilton            remoteMiu = sock.getRemoteMiu();
582ef360deaff9f17aa72d5749ceee283cc80897afBen Dodson            if (DBG) Log.d(TAG, "about to send a " + buffer.length + " byte message");
592ef360deaff9f17aa72d5749ceee283cc80897afBen Dodson            while (offset < buffer.length) {
602ef360deaff9f17aa72d5749ceee283cc80897afBen Dodson                int length = Math.min(buffer.length - offset, remoteMiu);
612ef360deaff9f17aa72d5749ceee283cc80897afBen Dodson                byte[] tmpBuffer = Arrays.copyOfRange(buffer, offset, offset+length);
622ef360deaff9f17aa72d5749ceee283cc80897afBen Dodson                if (DBG) Log.d(TAG, "about to send a " + length + " byte packet");
632ef360deaff9f17aa72d5749ceee283cc80897afBen Dodson                sock.send(tmpBuffer);
642ef360deaff9f17aa72d5749ceee283cc80897afBen Dodson                offset += length;
6557d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton            }
66d2d5dddf17ac2008547172cd72faa034a89d569bJeff Hamilton            return true;
672ef360deaff9f17aa72d5749ceee283cc80897afBen Dodson        } catch (IOException e) {
682ef360deaff9f17aa72d5749ceee283cc80897afBen Dodson            Log.e(TAG, "couldn't send tag");
692ef360deaff9f17aa72d5749ceee283cc80897afBen Dodson            if (DBG) Log.d(TAG, "exception:", e);
702ef360deaff9f17aa72d5749ceee283cc80897afBen Dodson        } catch (LlcpException e) {
712ef360deaff9f17aa72d5749ceee283cc80897afBen Dodson            // Most likely the other side doesn't support the my tag protocol
722ef360deaff9f17aa72d5749ceee283cc80897afBen Dodson            Log.e(TAG, "couldn't send tag");
732ef360deaff9f17aa72d5749ceee283cc80897afBen Dodson            if (DBG) Log.d(TAG, "exception:", e);
742ef360deaff9f17aa72d5749ceee283cc80897afBen Dodson        } finally {
752ef360deaff9f17aa72d5749ceee283cc80897afBen Dodson            if (sock != null) {
762094515fca0cfa0ac87e9cc260d3953d416afe3eJason parks                try {
772ef360deaff9f17aa72d5749ceee283cc80897afBen Dodson                    if (DBG) Log.d(TAG, "about to close");
782ef360deaff9f17aa72d5749ceee283cc80897afBen Dodson                    sock.close();
792ef360deaff9f17aa72d5749ceee283cc80897afBen Dodson                } catch (IOException e) {
802094515fca0cfa0ac87e9cc260d3953d416afe3eJason parks                    // Ignore
812094515fca0cfa0ac87e9cc260d3953d416afe3eJason parks                }
822094515fca0cfa0ac87e9cc260d3953d416afe3eJason parks            }
8357d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton        }
84d2d5dddf17ac2008547172cd72faa034a89d569bJeff Hamilton        return false;
8557d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton    }
8657d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton}
87