I've been working on Android (v2.3) for a couple of weeks now, and I've stumbled upon some problems with the Unimag Card Swiper from IDTECH.
The unit comes with a scarce documentation and the demo app from the SDK implements the firmware update and a few classes for dialogs and such which really offuscate how to achieve basic functionality (added to the few and not so good comments in the code).
I have implemented the interface in a basic activity and tried to detect when the unit is connected or disconnected but it seems the listener catches both events (connection/disconnection) as "disconnect", let alone trying to read a card.
Has anyone worked with this unit on Android and has some clear examples?
By the way, here is my class:
package com.card.swipe;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import IDTech.MSR.uniMag.uniMagReader;
import IDTech.MSR.uniMag.uniMagReaderMsg;
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;
public class CardSwipeTestActivity extends Activity implements uniMagReaderMsg {
private uniMagReader myUniMagReader = null;
private TextView etCardData;
private String _strMSRData = null;
private byte[]_MSRData = null;
private String _strStatus = null;
private int _nGetChallengeResult = 0;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// InitializeUI();
InitializeReader();
String strManufacture = myUniMagReader.getInfoManufacture();
String strModel = myUniMagReader.getInfoModel();
String strSDKVerInfo = myUniMagReader.getSDKVersionInfo();
String strOSVerInfo = android.os.Build.VERSION.RELEASE;
etCardData = (TextView)findViewById(R.id.text_view);
etCardData.setText("Phone: "+strManufacture+"\n"+"Model: "+strModel+"\n"+"SDK Ver: "+strSDKVerInfo+"\nOS Version: "+strOSVerInfo);
}
#Override
protected void onPause() {
// TODO Auto-generated method stub
if(myUniMagReader!=null)
{
//you should stop swipe card and unregister when the application go to background
myUniMagReader.stopSwipeCard();
// myUniMagReader.unregisterListen();
// myUniMagReader.release();
}
super.onPause();
}
#Override
protected void onResume() {
// TODO Auto-generated method stub
// you should register to listen the headset event when the application resumed.
// if(myUniMagReader!=null)
// {
//// myUniMagReader.registerListen();
// if(_bCheckedSaveLogItem==true)
// myUniMagReader.setSaveLogEnable(true);
// else
// myUniMagReader.setSaveLogEnable(false);
// }
// if(itemStartSC!=null)
// itemStartSC.setEnabled(true);
// waitingCommandResult=false;
super.onResume();
}
#Override
protected void onDestroy() {
myUniMagReader.release();
super.onDestroy();
android.os.Process.killProcess(android.os.Process.myPid());
}
//********************************************************************************//
#Override
public boolean getUserGrant(int arg0, String arg1) {
// TODO Auto-generated method stub
return false;
}
#Override
public void onReceiveMsgAutoConfigProgress(int arg0) {
// TODO Auto-generated method stub
}
#Override
public void onReceiveMsgCardData(byte arg0, byte[] arg1) {
// TODO Auto-generated method stub
Log.d("SWIPE", "Card swiped!");
Toast.makeText(getApplicationContext(), "Card swiped!", Toast.LENGTH_SHORT).show();
}
#Override
public void onReceiveMsgCommandResult(int arg0, byte[] arg1) {
// TODO Auto-generated method stub
}
#Override
public void onReceiveMsgConnected() {
Log.d("CONNECTION","Swiper Connected");
Toast.makeText(getApplicationContext(), "Swiper Connected!", Toast.LENGTH_SHORT).show();
}
#Override
public void onReceiveMsgDisconnected() {
Log.d("CONNECTION","Swiper Disconnected");
Toast.makeText(getApplicationContext(), "Swiper Disconnected!", Toast.LENGTH_SHORT).show();
}
#Override
public void onReceiveMsgFailureInfo(int arg0, String arg1) {
// TODO Auto-generated method stub
Log.d("CONNECTION","Swiper Failure");
}
#Override
public void onReceiveMsgSDCardDFailed(String arg0) {
// TODO Auto-generated method stub
}
#Override
public void onReceiveMsgTimeout(String arg0) {
Log.d("TIMEOUT","Timed out!");
Toast.makeText(getApplicationContext(), "Timed out!", Toast.LENGTH_SHORT).show();
}
#Override
public void onReceiveMsgToConnect() {
Log.d("CONNECTION","Swiper Powered Up");
Toast.makeText(getApplicationContext(), "Swiper Powered Up", Toast.LENGTH_SHORT).show();
}
#Override
public void onReceiveMsgToSwipeCard() {
Log.d("SWIPE","Ready to swipe!");
Toast.makeText(getApplicationContext(), "Ready to swipe!", Toast.LENGTH_SHORT).show();
}
//********************************************************************************//
private void InitializeReader()
{
if(myUniMagReader==null)
myUniMagReader = new uniMagReader(this,this);
myUniMagReader.setVerboseLoggingEnable(true);
myUniMagReader.registerListen();
//load the XML configuratin file
String fileNameWithPath = getXMLFileFromRaw();
if(!isFileExist(fileNameWithPath)) { fileNameWithPath = null; }
myUniMagReader.setXMLFileNameWithPath(fileNameWithPath);
myUniMagReader.loadingConfigurationXMLFile(true);
myUniMagReader.setTimeoutOfSwipeCard(5);
}
private boolean isFileExist(String path) {
if(path==null)
return false;
File file = new File(path);
if (!file.exists()) {
return false ;
}
return true;
}
private String getXMLFileFromRaw( ){
//the target filename in the application path
String fileNameWithPath = null;
fileNameWithPath = "idt_unimagcfg_default.xml";
try{
InputStream in = getResources().openRawResource(R.raw.idt_unimagcfg_default);
int length = in.available();
byte [] buffer = new byte[length];
in.read(buffer);
in.close();
deleteFile(fileNameWithPath);
FileOutputStream fout = openFileOutput(fileNameWithPath, MODE_PRIVATE);
fout.write(buffer);
fout.close();
// to refer to the application path
File fileDir = this.getFilesDir();
fileNameWithPath = fileDir.getParent() + java.io.File.separator + fileDir.getName();
fileNameWithPath = fileNameWithPath+java.io.File.separator+"idt_unimagcfg_default.xml";
}
catch(Exception e){
e.printStackTrace();
fileNameWithPath = null;
}
return fileNameWithPath;
}
public void swipe(View v)
{
if(myUniMagReader!=null)
{
myUniMagReader.startSwipeCard();
}
if(myUniMagReader.isSwipeCardRunning()==true)
{
Log.d("SWIPE","Swipe Card Running!");
}
}
private String getHexStringFromBytes(byte []data)
{
if(data.length<=0) return null;
StringBuffer hexString = new StringBuffer();
String fix = null;
for (int i = 0; i < data.length; i++) {
fix = Integer.toHexString(0xFF & data[i]);
if(fix.length()==1)
fix = "0"+fix;
hexString.append(fix);
}
fix = null;
fix = hexString.toString();
return fix;
}
public byte[] getBytesFromHexString(String strHexData)
{
if (1==strHexData.length()%2) {
return null;
}
byte[] bytes = new byte[strHexData.length()/2];
for (int i=0;i<strHexData.length()/2;i++) {
bytes[i] = (byte) Integer.parseInt(strHexData.substring(i*2, (i+1)*2) , 16);
}
return bytes;
}
}
(There are some unimplemented methods there as well)
Here's what I used with the UniMag. Using a handler to output the swiped data, and a 'Swipe' button to start the swiping. To improve, one should wait until the card reader reports it is connected / ready to swipe, then enable the button, disable while waiting for swipe, and re-enable after receiving data.
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import IDTech.MSR.XMLManager.StructConfigParameters;
import IDTech.MSR.uniMag.uniMagReader;
import IDTech.MSR.uniMag.uniMagReaderMsg;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
public class MainActivity extends Activity implements uniMagReaderMsg {
private uniMagReader myUniMagReader = null;
private Button btnSwipe;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if(myUniMagReader == null) {
myUniMagReader = new uniMagReader(this,this);
myUniMagReader.setSaveLogEnable(false);
myUniMagReader.setXMLFileNameWithPath(null);
myUniMagReader.loadingConfigurationXMLFile(true);
//myUniMagReader.setVerboseLoggingEnable(true);
myUniMagReader.registerListen();
}
btnSwipe = (Button) findViewById(R.id.button1);
btnSwipe.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
myUniMagReader.startSwipeCard();
}
});
}
#Override
public void onDestroy() {
myUniMagReader.stopSwipeCard();
myUniMagReader.unregisterListen();
myUniMagReader.release();
super.onDestroy();
}
#Override
public boolean getUserGrant(int arg0, String arg1) {
Log.d("UniMag", "getUserGrant -- " + arg1);
return true;
}
#Override
public void onReceiveMsgAutoConfigProgress(int arg0) {
// TODO Auto-generated method stub
Log.d("UniMag", "onReceiveMsgAutoConfigProgress");
}
#Override
public void onReceiveMsgCardData(byte arg0, byte[] arg1) {
Log.d("UniMag", "onReceiveMsgCardData");
Log.d("UniMag", "Successful swipe!");
String strData = new String(arg1);
Log.d("UniMag", "SWIPE - " + strData);
if(myUniMagReader.isSwipeCardRunning()) {
myUniMagReader.stopSwipeCard();
}
// Match the data we want.
String pattern = "%B(\\d+)\\^([^\\^]+)\\^(\\d{4})";
Log.d("UniMag", pattern);
Pattern r = Pattern.compile(pattern);
Matcher m = r.matcher(strData);
String card = "";
String name = "";
String exp = "";
String data = "";
if(m.find()) {
for(int a = 0; a < m.groupCount(); ++a) {
Log.d("UniMag", a + " - "+m.group(a));
}
card = m.group(1);
name = m.group(2);
exp = m.group(3);
data = "Data: " + name + " -- " + card + " -- " + exp;
Log.d("UniMag", data);
Message msg = new Message();
msg.obj = data;
swipeHandler.sendMessage(msg);
}
}
final Handler swipeHandler = new Handler() {
#Override
public void handleMessage(Message msg) {
String text = (String)msg.obj;
TextView dataView = (TextView) findViewById(R.id.text_view);
dataView.setText(text);
}
};
#Override
public void onReceiveMsgCommandResult(int arg0, byte[] arg1) {
Log.d("UniMag", "onReceiveMsgCommandResult");
}
#Override
public void onReceiveMsgConnected() {
Log.d("UniMag", "onReceiveMsgConnected");
Log.d("UniMag", "Card reader is connected.");
}
#Override
public void onReceiveMsgDisconnected() {
Log.d("UniMag", "onReceiveMsgDisconnected");
if(myUniMagReader.isSwipeCardRunning()) {
myUniMagReader.stopSwipeCard();
}
myUniMagReader.release();
}
#Override
public void onReceiveMsgFailureInfo(int arg0, String arg1) {
Log.d("UniMag","onReceiveMsgFailureInfo -- " + arg1);
}
#Override
public void onReceiveMsgSDCardDFailed(String arg0) {
Log.d("UniMag", "onReceiveMsgSDCardDFailed -- " + arg0);
}
#Override
public void onReceiveMsgTimeout(String arg0) {
Log.d("UniMag", "onReceiveMsgTimeout -- " + arg0);
Log.d("UniMag","Timed out!");
}
#Override
public void onReceiveMsgToConnect() {
Log.d("UniMag","Swiper Powered Up");
}
#Override
public void onReceiveMsgToSwipeCard() {
Log.d("UniMag","onReceiveMsgToSwipeCard");
}
#Override
public void onReceiveMsgAutoConfigCompleted(StructConfigParameters arg0) {
Log.d("UniMag", "onReceiveMsgAutoConfigCompleted");
}
}
I found that the 3.8 demo app they ship with the SDK has a bug where it will not connect to an Android gt-p3113 tablet unless you go into settings on the app on the phone and turn off 'Command To Connect'.
Related
I am trying to create an Android activity which sends data through the serial port as a product test. I have some code for doing so, which, so far, finds no serial ports on my device which definitely has a serial port. I intend to use this activity with a loopback connector on the serial port of the device to verify both the read and write functionalities. I have tried these two programs:
import android.app.Activity;
import com.symbol.emdk.EMDKManager;
import com.symbol.emdk.EMDKManager.EMDKListener;
import com.symbol.emdk.EMDKManager.FEATURE_TYPE;
import com.symbol.emdk.EMDKResults;
import com.symbol.emdk.serialcomm.SerialComm;
import com.symbol.emdk.serialcomm.SerialCommException;
import com.symbol.emdk.serialcomm.SerialCommManager;
import com.symbol.emdk.serialcomm.SerialCommResults;
import com.symbol.emdk.serialcomm.SerialPortInfo;
import android.app.Activity;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.Toast;
import java.util.HashMap;
import java.util.List;
public class SerialTry3 extends Activity implements EMDKListener{
private String TAG = SerialTry3.class.getSimpleName();
private EMDKManager emdkManager = null;
private SerialComm serialCommPort = null;
private SerialCommManager serialCommManager = null;
private EditText txtDataToSend = null;
private TextView txtStatus = null;
private Button btnRead = null;
private Button btnWrite = null;
private Spinner spinnerPorts = null;
public HashMap<String, SerialPortInfo> supportedPorts = null;
#Override #SuppressWarnings("SetTextI18n")
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.serial_try);
txtDataToSend = (EditText) findViewById(R.id.txtDataToSend);
txtDataToSend.setText("Serial Communication Write Data Testing.");
spinnerPorts = (Spinner)findViewById(R.id.spinnerPorts);
btnWrite = (Button) findViewById(R.id.btnWrite);
btnRead = (Button) findViewById(R.id.btnRead);
txtStatus = (TextView) findViewById(R.id.statusView);
txtStatus.setText("");
txtStatus.requestFocus();
EMDKResults results = EMDKManager.getEMDKManager(getApplicationContext(), this);
if (results.statusCode != EMDKResults.STATUS_CODE.SUCCESS) {
new AsyncStatusUpdate().execute("EMDKManager object request failed!");
}
new AsyncUiControlUpdate().execute(false);
}
#Override
public void onOpened(EMDKManager emdkManager) {
this.emdkManager = emdkManager;
Log.d(TAG, "EMDK opened");
try{
serialCommManager = (SerialCommManager) this.emdkManager.getInstance(FEATURE_TYPE.SERIALCOMM_EX);
if(serialCommManager != null) {
populatePorts();
}
else
{
new AsyncStatusUpdate().execute(FEATURE_TYPE.SERIALCOMM_EX.toString() + " Feature not supported.");
}
}
catch(Exception e)
{
Log.d(TAG, e.getMessage());
new AsyncStatusUpdate().execute(e.getMessage());
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.splash_main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
#Override
protected void onDestroy() {
super.onDestroy();
deinitSerialComm();
if (emdkManager != null) {
emdkManager.release();
emdkManager = null;
}
}
#Override
protected void onPause()
{
super.onPause();
deinitSerialComm();
serialCommManager = null;
supportedPorts = null;
// Release the serialComm manager resources
if (emdkManager != null) {
emdkManager.release(FEATURE_TYPE.SERIALCOMM_EX);
}
}
#Override
protected void onResume()
{
super.onResume();
// Acquire the serialComm manager resources
if (emdkManager != null) {
serialCommManager = (SerialCommManager) emdkManager.getInstance(FEATURE_TYPE.SERIALCOMM_EX);
if (serialCommManager != null) {
populatePorts();
if (supportedPorts != null)
initSerialComm();
}
}
}
void populatePorts()
{
try {
if(serialCommManager != null) {
List<SerialPortInfo> serialPorts = serialCommManager.getSupportedPorts();
if(serialPorts.size()>0) {
supportedPorts = new HashMap<String, SerialPortInfo> ();
String[] ports = new String[serialPorts.size()];
int count = 0;
for (SerialPortInfo info : serialPorts) {
supportedPorts.put(info.getFriendlyName(), info);
ports[count] = info.getFriendlyName();
count++;
}
spinnerPorts.setAdapter(new ArrayAdapter<String>(this,
android.R.layout.simple_spinner_dropdown_item, ports));
spinnerPorts.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) {
//Disabling previous serial port before getting the new one
deinitSerialComm();
initSerialComm();
}
#Override
public void onNothingSelected(AdapterView<?> adapterView) {
}
});
}
else
{
new AsyncStatusUpdate().execute("Failed to get available ports");
Toast.makeText(this, "Failed to get available ports, serial communication may not be supported.", Toast.LENGTH_LONG).show();
finish();
}
}
else
{
new AsyncStatusUpdate().execute("SerialCommManager is null");
}
}
catch (Exception ex)
{
Log.d(TAG, ex.getMessage());
new AsyncStatusUpdate().execute(ex.getMessage());
}
}
void initSerialComm() {
new AsyncEnableSerialComm().execute(supportedPorts.get(spinnerPorts.getSelectedItem()));
}
#Override
public void onClosed() {
if(emdkManager != null) {
emdkManager.release();
}
new AsyncStatusUpdate().execute("EMDK closed unexpectedly! Please close and restart the application.");
}
public void btnReadOnClick(View arg)
{
new AsyncReadData().execute();
}
public void btnWriteOnClick(View arg)
{
new AsyncUiControlUpdate().execute(false);
try {
String writeData = txtDataToSend.getText().toString();
int bytesWritten = serialCommPort.write(writeData.getBytes(), writeData.getBytes().length);
new AsyncStatusUpdate().execute("Bytes written: "+ bytesWritten);
} catch (SerialCommException e) {
new AsyncStatusUpdate().execute("write: "+ e.getResult().getDescription());
}
catch (Exception e) {
new AsyncStatusUpdate().execute("write: "+ e.getMessage() + "\n");
}
new AsyncUiControlUpdate().execute(true);
}
void deinitSerialComm() {
if (serialCommPort != null) {
try {
serialCommPort.disable();
serialCommPort = null;
} catch (Exception ex) {
Log.d(TAG, "deinitSerialComm disable Exception: " + ex.getMessage());
}
}
}
#SuppressWarnings("StaticFieldLeak")
private class AsyncStatusUpdate extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(String... params) {
return params[0];
}
#Override
protected void onPostExecute(String result) {
txtStatus.setText(result);
}
}
#SuppressWarnings("StaticFieldLeak")
private class AsyncUiControlUpdate extends AsyncTask<Boolean, Void, Boolean> {
#Override
protected Boolean doInBackground(Boolean... arg0) {
return arg0[0];
}
#Override
protected void onPostExecute(Boolean bEnable) {
btnRead.setEnabled(bEnable);
btnWrite.setEnabled(bEnable);
txtDataToSend.setEnabled(bEnable);
spinnerPorts.setEnabled(bEnable);
}
}
#SuppressWarnings("StaticFieldLeak")
private class AsyncEnableSerialComm extends AsyncTask<SerialPortInfo, Void, SerialCommResults>
{
#Override
protected SerialCommResults doInBackground(SerialPortInfo... params) {
SerialCommResults returnvar = SerialCommResults.FAILURE;
try {
serialCommPort = serialCommManager.getPort(params[0]);
} catch (Exception ex) {
ex.printStackTrace();
}
if (serialCommPort != null) {
try {
serialCommPort.enable();
returnvar = SerialCommResults.SUCCESS;
} catch (SerialCommException e) {
Log.d(TAG, e.getMessage());
e.printStackTrace();
returnvar = e.getResult();
}
}
return returnvar;
}
#Override #SuppressWarnings("SetTextI18n")
protected void onPostExecute(SerialCommResults result) {
super.onPostExecute(result);
if (result == SerialCommResults.SUCCESS) {
new AsyncStatusUpdate().execute("Serial comm channel enabled: (" + spinnerPorts.getSelectedItem().toString() + ")");
txtDataToSend.setText("Serial Communication Write Data Testing " + spinnerPorts.getSelectedItem().toString() + ".");
new AsyncUiControlUpdate().execute(true);
} else {
new AsyncStatusUpdate().execute(result.getDescription());
new AsyncUiControlUpdate().execute(false);
}
}
}
#SuppressWarnings("StaticFieldLeak")
private class AsyncReadData extends AsyncTask<Void, Void, String>
{
#Override
protected void onPreExecute() {
super.onPreExecute();
new AsyncUiControlUpdate().execute(false);
new AsyncStatusUpdate().execute("Reading..");
}
#Override
protected String doInBackground(Void... params) {
String statusText = "";
try {
byte[] readBuffer = serialCommPort.read(10000); //Timeout after 10 seconds
if (readBuffer != null) {
String tempString = new String(readBuffer);
statusText = "Data Read:\n" + tempString;
} else {
statusText = "No Data Available";
}
} catch (SerialCommException e) {
statusText = "read:" + e.getResult().getDescription();
} catch (Exception e) {
statusText = "read:" + e.getMessage();
}
return statusText;
}
#Override
protected void onPostExecute(String statusText) {
super.onPostExecute(statusText);
new AsyncUiControlUpdate().execute(true);
new AsyncStatusUpdate().execute(statusText);
}
}
}
and
import android.app.Activity;
import com.symbol.emdk.EMDKManager;
import com.symbol.emdk.EMDKManager.FEATURE_TYPE;
import com.symbol.emdk.EMDKResults;
import com.symbol.emdk.serialcomm.SerialComm;
import com.symbol.emdk.serialcomm.SerialCommException;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import com.symbol.emdk.serialcomm.SerialCommManager;
import com.symbol.emdk.serialcomm.SerialPortInfo;
import java.util.List;
public class SerialTry extends Activity implements EMDKManager.EMDKListener {
private String TAG = SerialTry.class.getSimpleName();
private EMDKManager emdkManager = null;
private SerialComm serialComm = null;
private SerialCommManager serialCommMan = null;
private EditText editText = null;
private TextView statusView = null;
private Button readButton = null;
private Button writeButton = null;
#Override #SuppressWarnings("SetTextI18n")
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.serial_try);
editText = (EditText) findViewById(R.id.editText1);
editText.setText("Serial Communication Write Data Testing.");
statusView = (TextView) findViewById(R.id.statusView);
statusView.setText("");
statusView.requestFocus();
EMDKResults results = EMDKManager.getEMDKManager(getApplicationContext(), this);
if (results.statusCode != EMDKResults.STATUS_CODE.SUCCESS) {
statusView.setText("Failed to open EMDK");
} else {
statusView.setText("Opening EMDK...");
}
//
// Get the serialComm/port object by passing a SerialPortInfo object:
addReadButtonEvents();
writeButtonEvents();
setEnabled(false);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.splash_main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
#Override
protected void onDestroy() {
super.onDestroy();
if (emdkManager != null) {
emdkManager.release();
emdkManager = null;
}
}
#Override
public void onOpened(EMDKManager emdkManager) {
this.emdkManager = emdkManager;
Log.d(TAG, "EMDK opened");
try{
serialCommMan = (SerialCommManager) this.emdkManager.getInstance(EMDKManager.FEATURE_TYPE.SERIALCOMM_EX);
List<SerialPortInfo> serialPorts = serialCommMan.getSupportedPorts();
serialComm = serialCommMan.getPort(serialPorts.get(0));
System.out.println("Supported Ports::::::" + serialPorts);
Thread readThread = new Thread(new Runnable() {
#Override
public void run() {
String statusText;
if (serialComm != null) {
try{
serialComm.enable();
statusText = "Serial comm channel enabled";
setEnabled(true);
} catch(SerialCommException e){
Log.d(TAG, e.getMessage());
e.printStackTrace();
statusText = e.getMessage();
setEnabled(false);
}
} else {
statusText = FEATURE_TYPE.SERIALCOMM_EX.toString() + " Feature not supported or initilization error.";
setEnabled(false);
}
displayMessage(statusText);
}
});
readThread.start();
}
catch(Exception e)
{
Log.d(TAG, e.getMessage());
e.printStackTrace();
displayMessage(e.getMessage());
}
}
#Override
public void onClosed() {
if(emdkManager != null) {
emdkManager.release();
}
displayMessage("EMDK closed abruptly.");
}
private void addReadButtonEvents() {
readButton = (Button) findViewById(R.id.btnRead);
readButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
Thread readThread = new Thread(new Runnable() {
#Override
public void run() {
setEnabled(false);
String statusText;
try {
byte[] readBuffer = serialComm.read(10000); //Timeout after 10 seconds
if(readBuffer != null) {
String tempString = new String(readBuffer);
statusText = "Data Read:\n" + tempString;
} else {
statusText = "No Data Available";
}
}catch (SerialCommException e) {
statusText ="read:"+ e.getResult().getDescription();
e.printStackTrace();
}
catch (Exception e) {
statusText = "read:"+ e.getMessage();
e.printStackTrace();
}
setEnabled(true);
displayMessage(statusText);
}
});
readThread.start();
}
});
}
#SuppressWarnings("SetTextI18n")
private void writeButtonEvents() {
writeButton = (Button) findViewById(R.id.btnWrite);
writeButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
setEnabled(false);
try {
String writeData = editText.getText().toString();
int bytesWritten = serialComm.write(writeData.getBytes(), writeData.getBytes().length);
statusView.setText("Bytes written: "+ bytesWritten);
} catch (SerialCommException e) {
statusView.setText("write: "+ e.getResult().getDescription());
}
catch (Exception e) {
statusView.setText("write: "+ e.getMessage() + "\n");
}
setEnabled(true);
}
});
}
#SuppressWarnings("SetTextI18n")
void displayMessage(String message) {
final String tempMessage = message;
runOnUiThread(new Runnable() {
public void run() {
statusView.setText(tempMessage + "\n");
}
});
}
void setEnabled(boolean enableState) {
final boolean tempState = enableState;
runOnUiThread(new Runnable() {
public void run() {
readButton.setEnabled(tempState);
writeButton.setEnabled(tempState);
editText.setEnabled(tempState);
}
});
}
}
Does the problem seem to be with my code or is there something I am not understanding about the device itself? Any help would be appreciated. Thank you for your time.
I designed a chat application but if I write text and click on send the application is force closed. I send username, ip and port information to the other activity.
messaging code :
import java.io.UnsupportedEncodingException;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.NotificationManager;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.database.Cursor;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.view.KeyEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnKeyListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
import com.android.chat.IAppManager;
import com.android.chat.IMService;
import com.android.chat.FriendController;
import com.android.chat.LocalStorageHandler;
import com.android.chat.FriendInfo;
import com.android.chat.MessageInfo;
import com.android.chats.R;
public class Messaging extends Activity {
private static final int MESSAGE_CANNOT_BE_SENT = 0;
public String username;
private EditText messageText;
private EditText messageHistoryText;
private Button sendMessageButton;
private IAppManager imService;
private FriendInfo friend = new FriendInfo();
private LocalStorageHandler localstoragehandler;
private Cursor dbCursor;
private ServiceConnection mConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className, IBinder service) {
imService = ((IMService.IMBinder)service).getService();
}
public void onServiceDisconnected(ComponentName className) {
imService = null;
Toast.makeText(Messaging.this, R.string.local_service_stopped,
Toast.LENGTH_SHORT).show();
}
};
#Override
protected void onCreate(Bundle savedInstanceState)
{
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.messaging_screen); //messaging_screen);
messageHistoryText = (EditText) findViewById(R.id.messageHistory);
messageText = (EditText) findViewById(R.id.message);
messageText.requestFocus();
sendMessageButton = (Button) findViewById(R.id.sendMessageButton);
Bundle extras = this.getIntent().getExtras();
friend.userName = extras.getString(FriendInfo.USERNAME);
friend.ip = extras.getString(FriendInfo.IP);
friend.port = extras.getString(FriendInfo.PORT);
String msg = extras.getString(MessageInfo.MESSAGETEXT);
setTitle("Messaging with " + friend.userName);
// EditText friendUserName = (EditText) findViewById(R.id.friendUserName);
// friendUserName.setText(friend.userName);
localstoragehandler = new LocalStorageHandler(this);
dbCursor = localstoragehandler.get(friend.userName, IMService.USERNAME );
if (dbCursor.getCount() > 0){
int noOfScorer = 0;
dbCursor.moveToFirst();
while ((!dbCursor.isAfterLast())&&noOfScorer<dbCursor.getCount())
{
noOfScorer++;
this.appendToMessageHistory(dbCursor.getString(2) , dbCursor.getString(3));
dbCursor.moveToNext();
}
}
localstoragehandler.close();
if (msg != null)
{
this.appendToMessageHistory(friend.userName , msg);
((NotificationManager)getSystemService(NOTIFICATION_SERVICE)).cancel((friend.userName+msg).hashCode());
}
sendMessageButton.setOnClickListener(new OnClickListener(){
CharSequence message;
Handler handler = new Handler();
public void onClick(View arg0) {
message = messageText.getText();
if (message.length()>0)
{
appendToMessageHistory(imService.getUsername(), message.toString());
localstoragehandler.insert(imService.getUsername(), friend.userName, message.toString());
messageText.setText("");
Thread thread = new Thread(){
public void run() {
try {
if (imService.sendMessage(imService.getUsername(), friend.userName, message.toString()) == null)
{
handler.post(new Runnable(){
public void run() {
Toast.makeText(getApplicationContext(),R.string.message_cannot_be_sent, Toast.LENGTH_LONG).show();
//showDialog(MESSAGE_CANNOT_BE_SENT);
}
});
}
} catch (UnsupportedEncodingException e) {
Toast.makeText(getApplicationContext(),R.string.message_cannot_be_sent, Toast.LENGTH_LONG).show();
e.printStackTrace();
}
}
};
thread.start();
}
}});
messageText.setOnKeyListener(new OnKeyListener(){
public boolean onKey(View v, int keyCode, KeyEvent event)
{
if (keyCode == 66){
sendMessageButton.performClick();
return true;
}
return false;
}
});
}
#Override
protected Dialog onCreateDialog(int id) {
int message = -1;
switch (id)
{
case MESSAGE_CANNOT_BE_SENT:
message = R.string.message_cannot_be_sent;
break;
}
if (message == -1)
{
return null;
}
else
{
return new AlertDialog.Builder(Messaging.this)
.setMessage(message)
.setPositiveButton(R.string.OK, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
/* User clicked OK so do some stuff */
}
})
.create();
}
}
#Override
protected void onPause() {
super.onPause();
unregisterReceiver(messageReceiver);
unbindService(mConnection);
FriendController.setActiveFriend(null);
}
#Override
protected void onResume()
{
super.onResume();
bindService(new Intent(Messaging.this, IMService.class), mConnection , Context.BIND_AUTO_CREATE);
IntentFilter i = new IntentFilter();
i.addAction(IMService.TAKE_MESSAGE);
registerReceiver(messageReceiver, i);
FriendController.setActiveFriend(friend.userName);
}
public class MessageReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent)
{
Bundle extra = intent.getExtras();
String username = extra.getString(MessageInfo.USERID);
String message = extra.getString(MessageInfo.MESSAGETEXT);
if (username != null && message != null)
{
if (friend.userName.equals(username)) {
appendToMessageHistory(username, message);
localstoragehandler.insert(username,imService.getUsername(), message);
}
else {
if (message.length() > 15) {
message = message.substring(0, 15);
}
Toast.makeText(Messaging.this, username + " says '"+
message + "'",
Toast.LENGTH_SHORT).show();
}
}
}
};
private MessageReceiver messageReceiver = new MessageReceiver();
public void appendToMessageHistory(String username, String message) {
if (username != null && message != null) {
messageHistoryText.append(username + ":\n");
messageHistoryText.append(message + "\n");
}
}
#Override
protected void onDestroy() {
super.onDestroy();
if (localstoragehandler != null) {
localstoragehandler.close();
}
if (dbCursor != null) {
dbCursor.close();
}
}
}
logcat message:
if I write text and click on send the application is force closed. I send username, ip and port information to the other activity.
code messageing :
public class Messaging extends Activity {
private static final int MESSAGE_CANNOT_BE_SENT = 0;
public String username;
private EditText messageText;
private EditText messageHistoryText;
private Button sendMessageButton;
private IAppManager imService;
private FriendInfo friend = new ir.android.chat.FriendInfo();
private LocalStorageHandler localstoragehandler;
private Cursor dbCursor;
public static String res="";
private ServiceConnection mConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className, IBinder service) {
imService = ((IMService.IMBinder)service).getService();
}
public void onServiceDisconnected(ComponentName className) {
imService = null;
Toast.makeText(Messaging.this, R.string.local_service_stopped,
Toast.LENGTH_SHORT).show();
}
};
#Override
protected void onCreate(Bundle savedInstanceState)
{
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.messaging_screen); //messaging_screen);
messageHistoryText = (EditText) findViewById(R.id.messageHistory);
messageText = (EditText) findViewById(R.id.message);
messageText.requestFocus();
sendMessageButton = (Button) findViewById(R.id.sendMessageButton);
Bundle extras = this.getIntent().getExtras();
friend.userName = extras.getString(FriendInfo.USERNAME);
friend.userNamef = extras.getString(FriendInfo.USERNAMEF);
friend.ip = extras.getString(FriendInfo.IP);
friend.port = extras.getString(FriendInfo.PORT);
String msg = extras.getString(MessageInfo.MESSAGETEXT);
setTitle("Messaging with " + friend.userName);
// EditText friendUserName = (EditText) findViewById(R.id.friendUserName);
// friendUserName.setText(friend.userName);
localstoragehandler = new LocalStorageHandler(this);
dbCursor = localstoragehandler.get(friend.userName, IMService.USERNAME );
if (dbCursor.getCount() > 0){
int noOfScorer = 0;
dbCursor.moveToFirst();
while ((!dbCursor.isAfterLast())&&noOfScorer<dbCursor.getCount())
{
noOfScorer++;
this.appendToMessageHistory(dbCursor.getString(2) , dbCursor.getString(3));
dbCursor.moveToNext();
}
}
localstoragehandler.close();
if (msg != null)
{
this.appendToMessageHistory(friend.userName , msg);
((NotificationManager)getSystemService(NOTIFICATION_SERVICE)).cancel((friend.userName+msg).hashCode());
}
sendMessageButton.setOnClickListener(new OnClickListener(){
CharSequence message;
Handler handler = new Handler();
public void onClick(View arg0) {
message = messageText.getText();
if (message.length()>0)
{
//appendToMessageHistory(friend.userNamef, message.toString());
appendToMessageHistory(friend.userNamef, message.toString());
localstoragehandler.insert(friend.userNamef, friend.userName, message.toString());
messageText.setText("");
Thread thread = new Thread(){
public void run() {
try {
if (imService.sendMessage(friend.userNamef, friend.userName, message.toString()) == null)
{
handler.post(new Runnable(){
public void run() {
Toast.makeText(getApplicationContext(),R.string.message_cannot_be_sent, Toast.LENGTH_LONG).show();
//showDialog(MESSAGE_CANNOT_BE_SENT);
}
});
}
} catch (UnsupportedEncodingException e) {
Toast.makeText(getApplicationContext(),R.string.message_cannot_be_sent, Toast.LENGTH_LONG).show();
e.printStackTrace();
}
}
};
thread.start();
}
}});
messageText.setOnKeyListener(new OnKeyListener(){
public boolean onKey(View v, int keyCode, KeyEvent event)
{
if (keyCode == 66){
sendMessageButton.performClick();
return true;
}
return false;
}
});
}
#Override
protected Dialog onCreateDialog(int id) {
int message = -1;
switch (id)
{
case MESSAGE_CANNOT_BE_SENT:
message = R.string.message_cannot_be_sent;
break;
}
if (message == -1)
{
return null;
}
else
{
return new AlertDialog.Builder(Messaging.this)
.setMessage(message)
.setPositiveButton(R.string.OK, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
/* User clicked OK so do some stuff */
}
})
.create();
}
}
#Override
protected void onPause() {
super.onPause();
unregisterReceiver(messageReceiver);
unbindService(mConnection);
FriendController.setActiveFriend(null);
}
#Override
protected void onResume()
{
super.onResume();
bindService(new Intent(Messaging.this, IMService.class), mConnection , Context.BIND_AUTO_CREATE);
IntentFilter i = new IntentFilter();
i.addAction(IMService.TAKE_MESSAGE);
registerReceiver(messageReceiver, i);
FriendController.setActiveFriend(friend.userName);
}
public class MessageReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent)
{
Bundle extra = intent.getExtras();
String username = extra.getString(MessageInfo.USERID);
String message = extra.getString(MessageInfo.MESSAGETEXT);
if (username != null && message != null)
{
if (friend.userName.equals(username)) {
appendToMessageHistory(username, message);
localstoragehandler.insert(username,friend.userNamef, message);
}
else {
if (message.length() > 15) {
message = message.substring(0, 15);
}
Toast.makeText(Messaging.this, username + " says '"+
message + "'",
Toast.LENGTH_SHORT).show();
}
}
}
};
private MessageReceiver messageReceiver = new MessageReceiver();
public void appendToMessageHistory(String username, String message) {
if (username != null && message != null) {
messageHistoryText.append(username + ":\n");
messageHistoryText.append(message + "\n");
}
}
#Override
protected void onDestroy() {
super.onDestroy();
if (localstoragehandler != null) {
localstoragehandler.close();
}
if (dbCursor != null) {
dbCursor.close();
}
}
}
log chat :
http://i.stack.imgur.com/USsul.png
I have successfully integrated Twilio SDK for android but when i am trying to make call with it its not connecting and showing error message in logcat i am getting following errors:
1) Failed to hangup call due to error code: 70015, message: pjsua_call_hangup(): Object already exists (PJ_EEXISTS)
2) Connection disconnected with error code 31000 and message Generic error
this both errors occurs when i am calling disconnect method if i comment this method then my calling is working fine and i make call but if i call this method phone.disconnect(), i am getting error shown as above.
This is my methods which i am using to make calls and to disconnect the calls.
////// To Make Calls
public void connect(String phoneNumber) {
Map parameters = new HashMap();
parameters.put("PhoneNumber", phoneNumber);
connection = device.connect(parameters, null /* ConnectionListener */);
if (connection == null)
Log.w(TAG, "Failed to create new connection");
}
// To Disconnect Phone
public void disconnect() {
if (connection != null) {
connection.disconnect();
connection = null; // will null out in onDisconnected()
if (basicConnectionListener != null)
basicConnectionListener.onConnectionDisconnecting();
}
}
and on my OnClick event:
public void onClick(View view) {
if (view.getId() == R.id.dialButton)
Toast.makeText(getApplicationContext(), "Dialing...", Toast.LENGTH_LONG).show();
phone.connect("PHONE NUMBER");
if (view.getId() == R.id.hangupButton)
Toast.makeText(getApplicationContext(), "Call Disconnected...", Toast.LENGTH_LONG).show();
phone.disconnect();
Please suggest me and help me because i tried all possible thing for hangout but still not able to solve it.Thanks in advance. ![enter image description here][1]
I am sharing my working class for twilio SDK setup.
This the calls which is working perfectly for me.I would like to share my class so any one can take reference of it.
This is the Base class which handle all the events of twillio Calling and Disconnecting the call.
import java.util.HashMap;
import java.util.Map;
import android.content.Context;
import android.media.AudioManager;
import android.util.Log;
import android.view.Gravity;
import android.view.inputmethod.InputMethodManager;
import android.widget.Toast;
import com.twilio.client.Connection;
import com.twilio.client.Connection.State;
import com.twilio.client.ConnectionListener;
import com.twilio.client.Device;
import com.twilio.client.DeviceListener;
import com.twilio.client.PresenceEvent;
import com.twilio.client.Twilio;
public class MonkeyPhone implements Twilio.InitListener, DeviceListener, ConnectionListener {
private static final String TAG = "MonkeyPhone";
private Device device;
private Connection connection;
private final Context context;
private BasicConnectionListener basicConnectionListener;
private BasicDeviceListener basicDeviceListener;
private Connection pendingIncomingConnection;
InputMethodManager imm;
private boolean speakerEnabled;
private boolean muteEnabled;
public interface BasicConnectionListener {
public void onIncomingConnectionDisconnected();
public void onConnectionConnecting();
public void onConnectionConnected();
public void onConnectionFailedConnecting(Exception error);
public void onConnectionDisconnecting();
public void onConnectionDisconnected();
public void onConnectionFailed(Exception error);
}
public interface BasicDeviceListener {
public void onDeviceStartedListening();
public void onDeviceStoppedListening(Exception error);
}
public MonkeyPhone(Context context) {
this.context = context;
Twilio.initialize(context, this /* Twilio.InitListener */);
}
public void setListeners(BasicConnectionListener basicConnectionListener, BasicDeviceListener basicDeviceListener) {
this.basicConnectionListener = basicConnectionListener;
this.basicDeviceListener = basicDeviceListener;
}
/* Twilio.InitListener method */
#Override
public void onInitialized() {
Log.d(TAG, "Twilio SDK is ready");
try {
// String capabilityToken =
// HttpHelper.httpGet("http://------/mobile/auth.php");
String capabilityToken = HttpHelper.httpGet("http:------/auth.php");
device = Twilio.createDevice(capabilityToken, null /* DeviceListener */);
} catch (Exception e) {
Log.e(TAG, "Failed to obtain capability token: " + e.getLocalizedMessage());
}
}
/* Twilio.InitListener method */
#Override
public void onError(Exception e) {
Log.e(TAG, "Twilio SDK couldn't start: " + e.getLocalizedMessage());
}
#Override
protected void finalize() {
if (device != null)
device.release();
if (connection != null)
connection.disconnect();
}
// To Make Calls
public void connect(String phoneNumber) {
Toast toast = Toast.makeText(context, "Dialing...", Toast.LENGTH_LONG);
toast.setGravity(Gravity.CENTER, 0, 0);
toast.show();
Map<String, String> parameters = new HashMap<String, String>();
parameters.put("PhoneNumber", phoneNumber);
String capabilityToken;
try {
// capabilityToken =
// HttpHelper.httpGet("http://------/mobile/auth.php");
capabilityToken = HttpHelper.httpGet("http://------/mobile/auth.php");
device = Twilio.createDevice(capabilityToken, null /* DeviceListener */);
} catch (Exception e1) {
e1.printStackTrace();
}
try {
device.disconnectAll();
} catch (Exception e) {
e.printStackTrace();
}
connection = device.connect(parameters, null /* ConnectionListener */);
if (connection == null) {
Log.w(TAG, "Failed to create new connection");
}
}
// To Disconnect Phone
public void disconnect() {
Toast toast = Toast.makeText(context, "Call Disconnected...", Toast.LENGTH_SHORT);
toast.setGravity(Gravity.CENTER, 0, 0);
toast.show();
if (connection != null) {
connection.disconnect();
connection = null; // will null out in onDisconnected()
if (basicConnectionListener != null)
basicConnectionListener.onConnectionDisconnecting();
}
}
public void setSpeakerEnabled(boolean speakerEnabled) {
if (speakerEnabled != this.speakerEnabled) {
this.speakerEnabled = speakerEnabled;
updateAudioRoute();
}
}
private void updateAudioRoute() {
AudioManager audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
audioManager.setSpeakerphoneOn(speakerEnabled);
}
public void setMuteEnabled(boolean muteEnabled) {
if (muteEnabled != this.muteEnabled) {
this.muteEnabled = muteEnabled;
updateAudioRouteForMute();
}
}
private void updateAudioRouteForMute() {
AudioManager audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
audioManager.setMicrophoneMute(muteEnabled);
}
public State status() {
connection.getState();
State statusHere = connection.getState();
return statusHere;
}
#Override
public void onConnected(Connection arg0) {
updateAudioRoute();
updateAudioRouteForMute();
if (basicConnectionListener != null) {
basicConnectionListener.onConnectionConnected();
}
}
#Override
public void onConnecting(Connection arg0) {
if (basicConnectionListener != null) {
basicConnectionListener.onConnectionConnecting();
}
}
#Override
public void onDisconnected(Connection inConnection) {
if (inConnection == connection) {
connection = null;
if (basicConnectionListener != null)
basicConnectionListener.onConnectionDisconnected();
} else if (inConnection == pendingIncomingConnection) {
pendingIncomingConnection = null;
if (basicConnectionListener != null)
basicConnectionListener.onIncomingConnectionDisconnected();
}
}
#Override
public void onDisconnected(Connection inConnection, int arg1, String inErrorMessage) {
if (inConnection == connection) {
connection = null;
if (basicConnectionListener != null)
basicConnectionListener.onConnectionFailedConnecting(new Exception(inErrorMessage));
}
}
#Override
public void onPresenceChanged(Device arg0, PresenceEvent arg1) {
}
#Override
public void onStartListening(Device arg0) {
if (basicDeviceListener != null) {
basicDeviceListener.onDeviceStartedListening();
}
}
#Override
public void onStopListening(Device arg0) {
if (basicDeviceListener != null) {
basicDeviceListener.onDeviceStoppedListening(null);
}
}
#Override
public void onStopListening(Device arg0, int arg1, String arg2) {
}
#Override
public boolean receivePresenceEvents(Device arg0) {
return false;
}
}
You can use this class like:
private MonkeyPhone phone;
//On create
phone = new MonkeyPhone(getApplicationContext());
//On Call Button Click
#Override
public void onClick(View view) {
if (view.getId() == R.id.btnCallHere) {
phone.connect(newContact);
} else if (view.getId() == R.id.btnDisconnectHere) {
phone.disconnect();
}
I am sending some data to an android application over UDP. Therefore i created the following UDPReceiver-Class:
package com.example.urowatch;
import java.net.*;
import java.nio.ByteBuffer;
import java.io.*;
public class UDPReceiver extends Thread
{
private DatagramSocket m_Socket;
private int m_BufferSize;
private Boolean m_End = false;
private int m_TotalLength;
private int m_Received;
private byte[] m_Buffer;
private byte[] m_Result;
private Boolean m_IsNewResult = false;
private float m_Progress;
private int m_ImageCount = 0;
private int m_FrameErrors = 0;
public UDPReceiver(String name, int port, int bufferSize) throws IOException
{
super(name);
m_Socket = new DatagramSocket(port);
m_BufferSize = bufferSize;
m_Socket.setBroadcast(true);
m_Socket.setReceiveBufferSize(m_BufferSize);
}
public void run()
{
while(!m_End)
{
try
{
byte[] buf = new byte[m_BufferSize];
DatagramPacket packet = new DatagramPacket(buf, buf.length);
m_Socket.receive(packet);
ProcessData(packet);
}
catch (IOException e)
{
if (!m_Socket.isClosed())
e.printStackTrace();
}
}
}
private void ProcessData(DatagramPacket packet)
{
if (packet.getLength() == 4)
{
ByteBuffer bb = ByteBuffer.wrap(packet.getData());
m_TotalLength = bb.getInt();
if (m_Received != 0)
m_FrameErrors++;
m_Received = 0;
m_Buffer = new byte[m_TotalLength];
}
else if (m_Buffer != null && m_Received != m_TotalLength)
{
int length = packet.getLength();
System.arraycopy(packet.getData(), 0, m_Buffer, m_Received, length);
m_Received += length;
m_Progress = 100 * (float)m_Received/(float)m_TotalLength;
if (m_Received == m_TotalLength)
{
m_Result = new byte[m_TotalLength];
System.arraycopy(m_Buffer, 0, m_Result, 0, m_TotalLength);
m_IsNewResult = true;
m_ImageCount++;
m_Received = 0;
}
}
}
public Boolean IsNewResult()
{
return m_IsNewResult;
}
public byte[] GetResult()
{
m_IsNewResult = false;
return m_Result;
}
public float GetProgress()
{
return m_Progress;
}
public float GetRatio()
{
return 100 * (float)m_ImageCount / (float)m_FrameErrors;
}
public void stopServer()
{
m_End = true;
if (m_Socket != null)
m_Socket.close();
}
}
And i am using this class like this:
package com.example.urowatch;
import java.io.IOException;
import java.text.DecimalFormat;
import android.os.*;
import android.app.Activity;
import android.app.AlertDialog;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import android.support.v4.app.NavUtils;
import android.annotation.TargetApi;
import android.content.Context;
import android.graphics.BitmapFactory;
import android.os.Build;
public class LiveActivity extends Activity {
private static ImageView m_ImageView1;
private static TextView m_TextView1;
private static DecimalFormat m_DF;
private static Context m_Context;
private UDPReceiver m_Receiver;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_live);
// Show the Up button in the action bar.
setupActionBar();
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
m_ImageView1 = (ImageView)findViewById(R.id.imageView1);
m_TextView1 = (TextView)findViewById(R.id.textView1);
m_Context = this;
m_DF = new DecimalFormat("00.00");
}
/**
* Set up the {#link android.app.ActionBar}, if the API is available.
*/
#TargetApi(Build.VERSION_CODES.HONEYCOMB)
private void setupActionBar() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
getActionBar().setDisplayHomeAsUpEnabled(true);
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.live, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
// This ID represents the Home or Up button. In the case of this
// activity, the Up button is shown. Use NavUtils to allow users
// to navigate up one level in the application structure. For
// more details, see the Navigation pattern on Android Design:
//
// http://developer.android.com/design/patterns/navigation.html#up-vs-back
//
NavUtils.navigateUpFromSameTask(this);
return true;
}
return super.onOptionsItemSelected(item);
}
private static Handler MyHandler = new Handler()
{
#Override
public void handleMessage(Message msg)
{
if (msg.what == 100)
{
float[] infos = (float[])msg.obj;
m_TextView1.setText("Empfange Bild: " + m_DF.format(infos[0]) + "% (FrameErrors: " + m_DF.format(infos[1]) + "%)");
}
else if (msg.what == 101)
{
byte[] b = (byte[])msg.obj;
m_TextView1.setText("Empfange Bild: 100,00%");
m_ImageView1.setImageBitmap(BitmapFactory.decodeByteArray(b, 0, b.length));
}
else if (msg.what == 102)
{
AlertDialog.Builder b = new AlertDialog.Builder(m_Context);
b.setTitle("Fehler");
b.setMessage("Es ist folgende Exception aufgetreten:\n" + (Exception)msg.obj);
b.setNeutralButton("OK", null);
b.show();
}
}
};
#Override
public void onBackPressed() {
super.onBackPressed();
if (m_Receiver != null)
m_Receiver.stopServer();
finish();
}
#Override
public void onPause()
{
m_Receiver.stopServer();
super.onPause();
}
#Override
protected void onResume()
{
try {
m_Receiver = new UDPReceiver("UDPReceiver", 5678, 1024);
m_Receiver.start();
} catch (IOException e1)
{
// TODO Auto-generated catch block
e1.printStackTrace();
AlertDialog.Builder b = new AlertDialog.Builder(this);
b.setTitle("Fehler");
b.setMessage("Es ist folgende Exception aufgetreten:\n" + e1);
b.setNeutralButton("OK", null);
b.show();
}
// Thread thread = new Thread()
// {
// #Override
// public void run()
// {
// while(true)
// {
// try {
//sleep(250);
Toast.makeText(getBaseContext(), "Runing Thread", Toast.LENGTH_SHORT).show();
Update();
// } catch (InterruptedException e) {
// // TODO Auto-generated catch block
// e.printStackTrace();
// MyHandler.sendMessage(MyHandler.obtainMessage(102, e));
// }
// }
// }
// };
// thread.start();
super.onResume();
}
public void buttonClick(View v)
{
Update();
}
private void Update()
{
if (m_Receiver != null)
{
if (m_Receiver.IsNewResult())
{
byte[] b = m_Receiver.GetResult();
MyHandler.sendMessage(MyHandler.obtainMessage(101, b));
}
else
{
float[] infos = new float[2];
infos[0] = m_Receiver.GetProgress();
infos[1] = m_Receiver.GetRatio();
MyHandler.sendMessage(MyHandler.obtainMessage(100, infos));
}
}
}
}
As you see i want to check the status of the UDPReceiver-Object (Is there a new complete byte[] ready?) by a thread. To update the GUI, the thread has to send a Message to MyHandler which will update the GUI.
In the moment i have to to click a button to raise the buttonClick-Event. Later on i want to do this in the commented thread-structure.
Now, here's my problem:
I start the Activity and everything works fine. Then i am starting to send ONE packet manually with my UDP-Sender (which works, i validated it with a C#-UDP-Receiver). The first packet get received fine. Then i send the second packet which get received, too. But from now on, my breakpoint at m_Socket.receive(packet); wont get hit anymore!
I have NO idea what this behaviour causes and it is very important for me to make this application work.
Please, if you have ANY Idea or just a guess, please let me know.
I need to prevent against lazy load in my custom list-view. so i found that scrollview onscroll listner are helpfull over there i have tryed it but not getting success to implement this functionality.
Code:
lviewAdapter = new ListViewAdapter(SaxParser2.this, Arr_ActivityName, Arr_AudioScript,Arr_RequestID,Arr_FolderPath,Arr_RequestTo);
lview.setOnScrollListener(SaxParser2.this);
#Override
public void onScroll(AbsListView arg0, int arg1, int arg2, int arg3) {
// TODO Auto-generated method stub
lview.setAdapter(lviewAdapter);
}
#Override
public void onScrollStateChanged(AbsListView arg0, int arg1) {
// TODO Auto-generated method stub
}
here is my BaseAdapter
package com.RecordingApp;
import it.sauronsoftware.ftp4j.FTPClient;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.io.Writer;
import java.net.HttpURLConnection;
import java.net.URL;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.graphics.Typeface;
import android.graphics.drawable.AnimationDrawable;
import android.media.MediaPlayer;
import android.media.MediaRecorder;
import android.os.AsyncTask;
import android.os.CountDownTimer;
import android.os.Environment;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
import com.Sharedpreferance.GMailSender;
public class ListViewAdapter extends BaseAdapter {
public static Activity context;
String title[];
String description[];
String RequestId[];
String Folderpath[];
String RequestTo[];
boolean b_Flag_Record_or_not = false;
boolean b_upload_or_not = false;
boolean start_or_not = false;
boolean start_play = false;
boolean upload_or_not = false;
boolean b_play_or_not = false;
boolean isplaying2 = false;
Thread welcomeThread,welcomeThread2;
int glob_position;
MediaPlayer mPlayer2;
int flag_stop_position;
AudioRecorder recorder;
AnimationDrawable frameAnimation, frameAnimation_play;
private static String mFileName = null;
private MediaRecorder mRecorder = null;
private MediaPlayer mPlayer = null;
Recording login = new Recording();
MediaPlayer MP_completeRequest = new MediaPlayer();
public ListViewAdapter(Activity context, String[] title,
String[] description, String[] req_id, String[] FolderPath,
String[] Arr_RequestTo) {
super();
this.context = context;
this.title = title;
this.description = description;
this.RequestId = req_id;
this.Folderpath = FolderPath;
this.RequestTo = Arr_RequestTo;
}
public int getCount() {
// TODO Auto-generated method stub
return title.length;
}
public Object getItem(int position) {
// TODO Auto-generated method stub
return null;
}
public long getItemId(int position) {
// TODO Auto-generated method stub
return 0;
}
private class ViewHolder {
TextView txtViewTitle;
TextView txtViewDescription;
Button record, stop, play, upload;
}
public View getView(final int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
final ViewHolder holder;
LayoutInflater inflater = context.getLayoutInflater();
glob_position = position;
if (convertView == null) {
convertView = inflater.inflate(R.layout.listitem_row, null);
holder = new ViewHolder();
holder.txtViewTitle = (TextView) convertView
.findViewById(R.id.textView1);
holder.txtViewDescription = (TextView) convertView
.findViewById(R.id.textView2);
holder.record = (Button) convertView.findViewById(R.id.record);
holder.stop = (Button) convertView.findViewById(R.id.stop);
holder.play = (Button) convertView.findViewById(R.id.play1);
holder.upload = (Button) convertView
.findViewById(R.id.audio_upload);
holder.record.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
if (isplaying2 == true) {
} else {
if (b_Flag_Record_or_not == true) {
} else {
try {
holder.record.setBackgroundResource(R.drawable.record_green);
b_Flag_Record_or_not = true;
b_play_or_not = true;
flag_stop_position = position;
AuthHandler dataHandler = new AuthHandler();
AuthDataset dataset = dataHandler
.getParsednewJobdtl_DataSet();
// Login l = new Login();
String str_useid = RequestTo[position];
recorder = new AudioRecorder(
"/audiometer/shanesh"
+ RequestId[position] + "-"
+ str_useid);
start_or_not = true;
recorder.start();
Toast.makeText(context, "Recording Started",
Toast.LENGTH_LONG).show();
CountDownTimer countDowntimer = new CountDownTimer(
120000000, 1000) {
public void onTick(long millisUntilFinished) {
}
public void onFinish() {
try {
Toast.makeText(
context,
"Stop recording Automatically ",
Toast.LENGTH_LONG).show();
recorder.stop();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
};
countDowntimer.start();
} catch (IOException e) {
gotoGmail(e);
} catch (Exception e) {
gotoGmail(e);
}
}
}
}
});
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
try {
Typeface face = Typeface.createFromAsset(context.getAssets(),
"fonts/tahoma.ttf");
holder.txtViewTitle.setTypeface(face);
holder.txtViewTitle.setText(title[position]);
holder.txtViewDescription.setText(description[position]);
} catch (ArrayIndexOutOfBoundsException e) {
e.printStackTrace();
}
holder.stop.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
try {
if (isplaying2 == true) {
mPlayer2.stop();
isplaying2 = false;
} else {
holder.record.setBackgroundResource(R.drawable.page7_15);
if (flag_stop_position == position) {
b_Flag_Record_or_not = false;
if (start_or_not == true) {
b_play_or_not = false;
recorder.stop();
upload_or_not = true;
start_play = true;
Toast.makeText(context, "Stoped Recording",
Toast.LENGTH_LONG).show();
} else {
Toast.makeText(context,
" Please Start recording ",
Toast.LENGTH_LONG).show();
}
} else {
}
}
} catch (Exception e) {
gotoGmail(e);
}
}
});
holder.play.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
String temp = SaxParser2.str_completeORpendingFlag;
if (temp.equalsIgnoreCase("c")) {
try {
final MediaPlayer mPlayer = new MediaPlayer();
try {
mPlayer.setDataSource(Folderpath[position]);
mPlayer.prepare();
final int welcomeScreenDisplay = mPlayer
.getDuration();
welcomeThread = new Thread() {
int wait = 0;
#Override
public void run() {
try {
isplaying2 = true;
mPlayer.start();
while (wait < welcomeScreenDisplay) {
sleep(100);
wait += 100;
}
} catch (Exception e) {
} finally {
isplaying2 = false;
}
}
};
welcomeThread.start();
} catch (Exception e) {
gotoGmail(e);
}
} catch (Exception e) {
gotoGmail(e);
}
} else if (temp.equalsIgnoreCase("p")) {
try {
if (b_play_or_not == true) {
} else {
String str_useid = RequestTo[position];
java.io.File file = new java.io.File(Environment
.getExternalStorageDirectory()
+ "/audiometer/", "shanesh"
+ RequestId[position] + "-" + str_useid
+ ".amr");
if (file.exists()) {
Toast.makeText(context, "Playing",
Toast.LENGTH_LONG).show();
mPlayer2 = new MediaPlayer();
try {
mPlayer2.setDataSource(Environment
.getExternalStorageDirectory()
+ "/audiometer/shanesh"
+ RequestId[position]
+ "-"
+ str_useid + ".amr");
mPlayer2.prepare();
mPlayer2.start();
isplaying2 = true;
final int welcomeScreenDisplay = mPlayer2
.getDuration();
/**
* create a thread to show splash up to
* splash time
*/
welcomeThread = new Thread() {
int wait = 0;
#Override
public void run() {
try {mPlayer2.prepare();
while (wait < welcomeScreenDisplay) {
sleep(100);
wait += 100;
}
} catch (Exception e) {
} finally {
welcomeThread2 = new Thread() {
int wait = 0;
#Override
public void run() {
try {
mPlayer2.start();
while (wait < welcomeScreenDisplay) {
sleep(100);
wait += 100;
}
} catch (Exception e) {
} finally {
// frameAnimation_play.stop();
isplaying2 = false;
}
}
};
welcomeThread2.start();
}
}
};
welcomeThread.start();
} catch (Exception e) {
gotoGmail(e);
}
} else {
Toast.makeText(context, " File Not Found ",
Toast.LENGTH_LONG).show();
}
}
} catch (Exception e) {
gotoGmail(e);
}
}
}
});
holder.upload.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
glob_position = position;
// String str_useid = RequestTo[position];
if (upload_or_not == true) {
try {
new xyz().execute();
} catch (Exception e) {
gotoGmail(e);
}
}
}
});
return convertView;
}
private class xyz extends AsyncTask<Void, Void, Void> {
private final ProgressDialog dialog = new ProgressDialog(context);
protected void onPreExecute() {
try {
this.dialog.setMessage("Uploading...Please Wait..");
dialog.setIndeterminate(true);
dialog.setCancelable(false);
this.dialog.show();
// put your code which preload with processDialog
} catch (Exception e) {
gotoGmail(e);
}
}
#Override
protected Void doInBackground(Void... arg0) {
for (int i = 0; i < 100000; i++) {
}
it.sauronsoftware.ftp4j.FTPClient con = new it.sauronsoftware.ftp4j.FTPClient();
try {
String str_useid = RequestTo[glob_position];
con.connect("URL");
con.login("as", "asdasd");
con.changeDirectory("/rangam/RequestContent/audio");
con.setPassive(true);
con.setType(FTPClient.TYPE_BINARY);
con.upload(new java.io.File(Environment
.getExternalStorageDirectory()
+ "/audiometer/shanesh"
+ RequestId[glob_position] + "-" + str_useid + ".amr"));
String filename = "/shanesh" + RequestId[glob_position] + "-"
+ str_useid + ".amr";
con.logout();
con.disconnect(true);
String MachineName = Machinelist.str_Machinename;
sendFlagToServer(RequestId[glob_position], filename,
MachineName);
} catch (Exception e) {
gotoGmail(e);
}
return null;
}
protected void onPostExecute(final Void unused) {
if (this.dialog.isShowing()) {
try {
this.dialog.dismiss();
AlertDialog.Builder alertbox = new AlertDialog.Builder(
context);
alertbox.setTitle("Message");
alertbox.setMessage(":: Uploaded Successfully ::");
alertbox.setPositiveButton("OK",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface arg0,
int arg1) {
Intent intent_request = new Intent(context,
SaxParser2.class);
intent_request.putExtra("value", Machinelist.str_UIDValue);
intent_request.putExtra("machineName",
Machinelist.str_Machinename);
intent_request.putExtra("captureBack_or_not", 2);
context.startActivity(intent_request);
context.finish();
}
});
alertbox.show();
} catch (Exception e) {
gotoGmail(e);
}
}
}
}
private void sendFlagToServer(String requestID, String filename,
String machineName) {
HttpURLConnection connection;
OutputStreamWriter request = null;
String MachineName = Machinelist.str_Machinename;
URL url = null;
String parameters = "RequestID=" + requestID + "&FileName=" + filename
+ "&MachineName=" + MachineName + "&RequestType=A";
try {
url = new URL(
"URL");
connection = (HttpURLConnection) url.openConnection();
connection.setDoOutput(true);
connection.setRequestProperty("Content-Type",
"application/x-www-form-urlencoded");
connection.setRequestMethod("POST");
request = new OutputStreamWriter(connection.getOutputStream());
request.write(parameters);
request.flush();
request.close();
String line = "";
InputStreamReader isr = new InputStreamReader(
connection.getInputStream());
BufferedReader reader = new BufferedReader(isr);
StringBuilder sb = new StringBuilder();
while ((line = reader.readLine()) != null) {
sb.append(line + "\n");
}
isr.close();
reader.close();
} catch (Exception e) {
gotoGmail(e);
}
}
public boolean onKeyDown(int keyCode, KeyEvent event) {
if ((keyCode == KeyEvent.KEYCODE_BACK)) {
try {
context.finish();
} catch (Exception e) {
gotoGmail(e);
}
}
return false;
}
void gotoGmail(Exception e) {
Writer writer = new StringWriter();
PrintWriter printWriter = new PrintWriter(writer);
e.printStackTrace(printWriter);
String s = writer.toString();
}
}
Ok,
So first you'll have to define "what is the number of views I'd need to load in order my user not to see that it's lazy loading ?" :
Let's say, you'd want to load 20 rows...
Now in you onscroll, or wherever you want but somewhere like on scroll or Adapter.getView, you'll have to know what is displayed on screen at the moment... Let me explain :
I want to load 20 rows so my user doesn't notice,
I am display 10 of them
and 10 of them are just hidden (not displayed if the guy doesn't scroll).
Now, I wan't to load 10 more when the guy just hit my 15th row
What could be the best way to do that ???
Humm, let's see, trying to find something that returns the (ABSOLUTE) number of the last row displayed on screen - this could be a nice solution.
An otehr solution could be that your 10 or 15th row is the first one displayed on screen ?
etc, etc...
I think stuffs like that should do the trick. ;)
Here is a sample I grabbed from Net. It is loading the items by listening to the Scroll of the ListView . For sample it is loading dates in ListView. After reached the end position it will load next 15 dates. It is Never Ending List . You can modify the adapter to your custom adapter. The concept is:
You have set of data
Loading first n no of items
Set the scroll listener to the listview
If scroll reaches Last Visible Item in Listview , You trigger the worker thread to load additional m no of items.
Notify listview from an UI thread.
int itemsPerPage = 15;
boolean loadingMore = false;
ArrayList<String> myListItems;
ArrayAdapter<String> adapter;
//For test data :-)
Calendar d = Calendar.getInstance();
this.getListView().setOnScrollListener(new OnScrollListener(){
//useless here, skip!
#Override
public void onScrollStateChanged(AbsListView view, int scrollState) {}
#Override
public void onScroll(AbsListView view, int firstVisibleItem,
int visibleItemCount, int totalItemCount) {
//what is the bottom item that is visible
int lastInScreen = firstVisibleItem + visibleItemCount;
//is the bottom item visible & not loading more already ? Load more !
if((lastInScreen == totalItemCount) && !(loadingMore)){
Thread thread = new Thread(null, loadMoreListItems);
thread.start();
}
}
});
//Load the first 15 items
Thread thread = new Thread(null, loadMoreListItems);
thread.start();
}
//Runnable to load the items
private Runnable loadMoreListItems = new Runnable() {
#Override
public void run() {
//Set flag so we cant load new items 2 at the same time
loadingMore = true;
//Reset the array that holds the new items
myListItems = new ArrayList<String>();
//Get 15 new listitems
for (int i = 0; i < itemsPerPage; i++) {
//Fill the item with some bogus information
myListItems.add("Date: " + (d.get(Calendar.MONTH)+ 1) + "/" + d.get(Calendar.DATE) + "/" + d.get(Calendar.YEAR) );
// +1 day :-D
d.add(Calendar.DATE, 1);
}
//Done! now continue on the UI thread
runOnUiThread(returnRes);
}
};
//Since we cant update our UI from a thread this Runnable takes care of that!
private Runnable returnRes = new Runnable() {
#Override
public void run() {
//Loop thru the new items and add them to the adapter
if(myListItems != null && myListItems.size() > 0){
for(int i=0;i<myListItems.size();i++)
adapter.add(myListItems.get(i));
}
//Update the Application title
setTitle("Neverending List with " + String.valueOf(adapter.getCount()) + " items");
//Tell to the adapter that changes have been made, this will cause the list to refresh
adapter.notifyDataSetChanged();
//Done loading more.
loadingMore = false;
}
};
EDIT:
You can get tutorial and full project here