Need help getting Android TextWatcher to work with incoming composite barcode data

I am writing an application that uses an externally connected USB barcode / RFID scanner. The data that is scanned is β€œcomposite” data. Here is an example:

=+03000=W12560712345600=%2800&>0090452359

This is from scanning complex data. The separator in the data is the equal sign (=) or ampersand (&). The first bit =+03000says that there are three pieces of data in the scan:

=W12560712345600

=%2800

&>0090452359

This data may contain any number of pieces of data from one to N.

In my Android app, I have a form with three elements EditText. What I need to do with this composite scanned data is to split it with delimiters and insert each piece of data into the correct field EditText.

, stdin TextWatcher EditText , .

, , . :

activity_main.xml

<LinearLayout>
    <TextView />
    <EditText android:id="@+id/datafield01" />
    <EditText android:id="@+id/datafield02" />
    <EditText android:id="@+id/datafield03" />
    <Button />
</LinearLayout>

MainActivity.java

public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState){
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        EditText dataField01 = (EditText)findViewById(R.id.datafield01);
        EditText dataField02 = (EditText)findViewById(R.id.datafield02);
        EditText dataField02 = (EditText)findViewById(R.id.datafield03);

        dataField01.addTextChangedListener(editTextWatcher);
    }

    TextWatcher editTextWatcher = new TextWatcher(){
        @Override
        public void beforeTextChanged(CharSequence s, int start, int count, int after){
        }

        @Override
        public void onTextChanged(CharSequence s, int start, int before, int count){
        }

        @Override
        public void afterTextChanged(CharSequence s){
        }
    };
}

CharSequence StringBuffer - before, on afterTextChanged - EditText, .

MainActivity.java

public class MainActivity extends AppCompatActivity {
    private StringBuffer stringBuffer;
    @Override
    protected void onCreate(Bundle savedInstanceState){
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        stringBuffer = new StringBuffer();

        EditText dataField01 = (EditText)findViewById(R.id.datafield01);
        EditText dataField02 = (EditText)findViewById(R.id.datafield02);
        EditText dataField02 = (EditText)findViewById(R.id.datafield03);
        dataField01.addTextChangedListener(editTextWatcher);

        System.out.println(stringBuffer.toString());
    }

    TextWatcher editTextWatcher = new TextWatcher(){
        @Override
        public void beforeTextChanged(CharSequence s, int start, int count, int after){
        }

        @Override
        public void onTextChanged(CharSequence s, int start, int before, int count){
            stringBuffer.append(s);
        }

        @Override
        public void afterTextChanged(CharSequence s){
        }
    };
}

, System.out.println(stringbuffer);, .

, , N, .

, - , Google .

, , , ?

.

+6
3

, TextWatcher; , char ..

, , , -. .

, , , , .

, , , Android Filter . . ( , Google , , , .)

, -, , , . , , .

, IoC:

    interface ScanProcessor {

       void process(CharSequence input);
    }

Handler. (UI), .

    public static class InputDelayHandler extends Handler {

       private static final int INPUT_MESSAGE = 0x20170308;

       private static final int PROCESS_MESSAGE = 0x20170309;

       // You'll have to tweak this value to ensure all input is entered, 
       // while the app remains responsive to the scan
       private static final long DELAY_MS = 250;

       private CharSequence mInput;

       private ScanProcessor mScanProcessor;

       InputDelayHandler(ScanProcessor scanProcessor) {
           super();  // associate the handler with the Looper for the current thread
           mScanProcessor = scanProcessor;
       }

       void setInput(CharSequence input) {

           // removing this message is the key to how this works
           // since it delayed, we can cancel before input is complete.
           removeMessages(PROCESS_MESSAGE);
           removeMessages(INPUT_MESSAGE);
           Message inputMessage = obtainMessage(INPUT_MESSAGE);
           inputMessage.obj = input;
           sendMessage(inputMessage);
           Message startMessage = obtainMessage(PROCESS_MESSAGE);
           sendMessageDelayed(startMessage, DELAY_MS);
       }

       @Override
       public void handleMessage(Message msg) {

           switch (msg.what) {
           case INPUT_MESSAGE:
               // remember the last input
               mInput = (CharSequence) msg.obj;
               break;
           case PROCESS_MESSAGE:
               // callback
               if (/*mInput looks like valid scan data*/) {
                   mScanProcessor.process(mInput);
               }
               break;
           }
       }
   }

, EditText, .

        private InputDelayHandler mHandler;

TextWatcher , - :

        @Override
        public void onTextChanged(CharSequence s, int start, int before, int count) {

            mHandler.setInput(s);
        }

:

            mHandler = new InputDelayHandler(new ScanProcessor() {

                @Override void process(CharSequence input) {

                    // parse the input, set the EditText fields, etc.
                }
            });
0

-, TextWatcher 3 , , . afterTextChanged

private String[] mCompound;

public void afterTextChanged(CharSequence s) {
    //first check and make sure we only try to split up compound data
    //and don't loop forever each time we set data back to ourselves
    if (s.contains("=")) {

        //create an array of the compound data parts
        //by splitting every time we find = or &
        mCompound = s.split("(\\=)|(&)");
        //Your example =+03000=W12560712345600=%2800&>0090452359 is now
        //mCompound = { "+03000", "W12560712345600", "%2800", ">0090452359" }     

        //Clear/reset all our fields first
        dataField01.setText(null);
        dataField02.setText(null);
        dataField03.setText(null);

        //We check if >1 because we know mCompound[0] is always the count
        if (mCompound.length > 1) {
            //we wrap with string.valueof() because the data might just be a number
            dataField01.setText( String.valueOf(mCompound[1]) );
            if (mCompound.length > 2) {
                dataField02.setText( String.valueOf(mCompound[2]) );
                if (mCompound.length > 3) {
                    dataField02.setText( String.valueOf(mCompound[3]) );
                }
            }
        } 

    }
}
0

, :

  • rfid:

-, :

<uses-permission android:name="android.permission.NFC" />
<uses-sdk android:minSdkVersion="10"/>
<uses-feature android:name="android.hardware.nfc" android:required="true" />

, , "", :

<intent-filter>
    <action android:name="android.nfc.action.NDEF_DISCOVERED"/>
    <category android:name="android.intent.category.DEFAULT"/>
    <data android:mimeType="text/plain" />
</intent-filter>

NFC, , res xml:

<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
    <tech-list>
        <tech>android.nfc.tech.IsoDep</tech>
        <tech>android.nfc.tech.NfcA</tech>
        <tech>android.nfc.tech.NfcB</tech>
        <tech>android.nfc.tech.NfcF</tech>
        <tech>android.nfc.tech.NfcV</tech>
        <tech>android.nfc.tech.Ndef</tech>
        <tech>android.nfc.tech.NdefFormatable</tech>
        <tech>android.nfc.tech.MifareClassic</tech>
        <tech>android.nfc.tech.MifareUltralight</tech>
    </tech-list>
</resources>

, AndroidManifest.xml:

<activity>
...
<intent-filter>
    <action android:name="android.nfc.action.TECH_DISCOVERED"/>
</intent-filter>

<meta-data android:name="android.nfc.action.TECH_DISCOVERED"
    android:resource="@xml/nfc_tech_filter" />
...
</activity>
  1. According to the received data, you want to break the message into 3 parts, as you indicated, which are divided by the '=' or '&' sign:

    Parcelable [] rawMsgs = intent.getParcelableArrayExtra (NfcAdapter.EXTRA_NDEF_MESSAGES);

    NdefMessage msg = (NdefMessage) rawMsgs [0]; String st = new String (msg.getRecords () [0] .getPayload ()); st. String [] tokens = st.split ("= | &");

When finished, the token array should contain your messages.

https://developer.android.com/guide/topics/connectivity/nfc/nfc.html#tag-dispatch

0
source

Source: https://habr.com/ru/post/1015419/


All Articles