I'm trying to implement a way to listen to a client's connection event on the smartphone hotspot. I see that android.net.wifi.WIFI_HOTSPOT_CLIENTS_CHANGED is no longer avaible. How can i do this? I think that this is possible because the smartphone notify me when i client make a connection to the smartphone hotspot.
You can't use the Intent Action...You have to use a custom method, i'l suggest you create a background thread that checks/reads the I.P table (/proc/net/arp) constantly and update you...here's a snippet I've used.
Read i.p list table
public ArrayList<String> getConnectedDevices() {
ArrayList<String> arrayList = new ArrayList();
try {
BufferedReader bufferedReader = new BufferedReader(new FileReader("/proc/net/arp"));
while (true) {
String readLine = bufferedReader.readLine();
if (readLine == null) {
break;
}
String[] split = readLine.split(" +");
if (split != null && split.length >= 4) {
arrayList.add(split[0]);
}
}
} catch (Exception e) {
e.printStackTrace();
}
return arrayList;
}
Create runnable to check
class CheckHotSpotConnection implements Runnable {
private CheckHotSpotConnection() {
}
public void run() {
int i = 0;
while (discoverClient()) {
i = getConnectedDevices().size();
if (i > 1) {
//client discovered
//disable client discovery to end thread
} else {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
Start Thread
new Thread(new CheckHotSpotConnection()).start();
I developing VOIP android application that make and receive the sip call.I Build the pjsip lilbrary as described in "http://trac.pjsip.org/repos/wiki/Getting-Started/Android".
1. Hold
MainActivity.prm.setOptions(pjsua_call_flag.PJSUA_CALL_UPDATE_CONTACT
.swigValue());
try {
MainActivity.currentCall.setHold(MainActivity.prm);
} catch (Exception e) {
e.printStackTrace();
}
I found this code on pjsip documentation,but this code does not work for put a call on Hold.There is no error message return.
2.Unhold
MainActivity.prm = new CallOpParam(true);
MainActivity.prm.getOpt().setFlag(1);
try {
MainActivity.currentCall.reinvite(MainActivity.prm);
} catch (Exception e) {
e.printStackTrace();
}
Thanks.
Here is my code for hold and unHold:
public void setHold(boolean hold) {
if ((localHold && hold) || (!localHold && !hold)) return;
if(currentCall == null) return;
CallOpParam param = new CallOpParam(true);
try {
if (hold) {
currentCall.setHold(param);
localHold = true;
} else {
CallSetting opt = param.getOpt();
opt.setAudioCount(1);
opt.setVideoCount(0);
opt.setFlag(pjsua_call_flag.PJSUA_CALL_UNHOLD.swigValue());
currentCall.reinvite(param);
localHold = false;
}
} catch (Exception e) {}
}
I hope it's helpful.
I am writing an app on Android Studio.
I communicate from an Android device to an arduino board via Bluetooth.
For now everything works but i am starting a new Activity and i need to stop the actual BT connection. so i want to call a stop method.
The problem is that it crash when i call it.
here is the code
public class BtInterface {
private BluetoothDevice device = null;
private BluetoothSocket socket = null;
private InputStream receiveStream = null;
private OutputStream sendStream = null;
String GlobalBuff="";
String Right_Buff="";
private ReceiverThread receiverThread;
Handler handler;
public BtInterface(Handler hstatus, Handler h,String Device_Name) {
Set<BluetoothDevice> setpairedDevices = BluetoothAdapter.getDefaultAdapter().getBondedDevices();
BluetoothDevice[] pairedDevices = (BluetoothDevice[]) setpairedDevices.toArray(new BluetoothDevice[setpairedDevices.size()]);
for(int i=0;i<pairedDevices.length;i++) {
if(pairedDevices[i].getName().contains(Device_Name)) {
device = pairedDevices[i];
try {
socket = device.createRfcommSocketToServiceRecord(UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"));
receiveStream = socket.getInputStream();
sendStream = socket.getOutputStream();
} catch (IOException e) {
e.printStackTrace();
}
break;
}
}
handler = hstatus;
receiverThread = new ReceiverThread(h);
}
public void sendData(String data) {
sendData(data, false);
}
public void sendData(String data, boolean deleteScheduledData) {
try {
sendStream.write(data.getBytes());
sendStream.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
public void connect() {
new Thread() {
#Override public void run() {
try {
socket.connect();
Message msg = handler.obtainMessage();
msg.arg1 = 1;
handler.sendMessage(msg);
receiverThread.start();
} catch (IOException e) {
Log.v("N", "Connection Failed : " + e.getMessage());
e.printStackTrace();
}
}
}.start();
}
public void close() {
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
socket=null; //???
}
public BluetoothDevice getDevice() {
return device;
}
private class ReceiverThread extends Thread {
Handler handler;
ReceiverThread(Handler h) {
handler = h;
}
#Override public void run() {
while(true) {
try {
if(receiveStream.available() > 0) {
byte buffer[] = new byte[1000];
int k = receiveStream.read(buffer, 0, 1000);
if(k > 0) {
byte rawdata[] = new byte[k];
for(int i=0;i<k;i++)
rawdata[i] = buffer[i];
String data = new String(rawdata);
GlobalBuff= GlobalBuff+data;
Right_Buff= GlobalBuff.substring(GlobalBuff.length()-1,GlobalBuff.length());
if(Right_Buff.equals("\n")){
Message msg = handler.obtainMessage();
Bundle b = new Bundle();
b.putString("receivedData", GlobalBuff);
msg.setData(b);
handler.sendMessage(msg);
GlobalBuff="";
}
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
i try some extra code :
receiverThread.interrupt();
receiverThread=null;
if (receiveStream != null) {
try {receiveStream.close();} catch (Exception e) {}
receiveStream = null;
}
if (sendStream != null) {
try {sendStream.close();} catch (Exception e) {}
sendStream = null;
}
before closing but the result is the same , it crash.
The strange behavior is that it didn't crash immediately as it could happen with a type error or else ( i am talking of the behavior in debug mode...)
If anybody got an idea.
Googling this bring me to people with this issue but no solution that works for my case.
Thanks
UPDATE
what i found as a trace when it crash is that :
06-02 07:45:27.369 9025-9133/fr.icservice.sechage A/libc? Fatal signal 11 (SIGSEGV) at 0x00000008 (code=1), thread 9133 (Thread-1436)
I also made a test on a sony Z3 phone under 5.0.2 (compare to my T210 samsung galaxy tab3 under 4.4.2)and it not crash..!
maybe it's a ROM bug?! or a android version problem...
This is a known problem (or bug?) on Android. If you close the Bluetooth socket and then access it later on, some devices will crash with a segmentation fault (like yours). A common workaround is to check socket.isConnected() before or to synchronize the access to close(), write(), read(), ... by setting a flag like closeWasCalled = true and prevent any further calls to methods of this socket in your code after a close() call.
The problem comes with Socket Input/Output. I faced this problem when disconnecting with peer bluetooth device.
Reason :
From code, we are trying to read() , write() from socket object/connection which is closed.
Solution :
Add checking socket.isConnected() before above operations
You can read more about this problem on Stack Overflow question : Here
I m getting exception "Can't create handler inside thread that has not called Looper.prepare()
in the function doFirstTime().
I m trying to upload my data at Dropbox using Dropbox API
Can you tell me how to fix it?
public class DownloadFile extends AsyncTask<Void, Long, Boolean>
`{
private Context mContext;
private DropboxAPI<?> mApi;
private String mPath;
private FileOutputStream mFos;
private String mErrorMsg;
private StringBuilder xmlcode,newXMLCode;
private final static String FILE_NAME = "fuelrecords.xml";
private final static String ZIP_FILE_NAME = "fuelpad.zip";
private String dropbox_xml_records[];
private ArrayList<ArrayList<String>> dropbox_records;
private ArrayList<ArrayList<String>> database_records;
private ExpenseOperations eop;
private UploadFile up;
private boolean no_file;
public DownloadFile(Context context, DropboxAPI<?> api,String dropboxPath)
{
// We set the context this way so we don't accidentally leak activities
mContext = context.getApplicationContext();
mApi = api;
mPath = dropboxPath;
dropbox_records = new ArrayList<ArrayList<String>>();
database_records = new ArrayList<ArrayList<String>>();
eop = new ExpenseOperations(mContext);
xmlcode=new StringBuilder("");
newXMLCode=new StringBuilder("");
no_file = false;
}
#Override
protected Boolean doInBackground(Void... params)
{
Log.d("yes1", " in do in back of download..");
try
{
// Get the metadata for a directory
Entry dirent = mApi.metadata(mPath, 1000, null, true, null);
if (!dirent.isDir || dirent.contents == null)
{
// It's not a directory, or there's nothing in it
mErrorMsg = "Could not locate the file...";
return false;
}
String cachefilePath = mContext.getCacheDir().getAbsolutePath() + "/" + FILE_NAME;
String cachezipPath = mContext.getCacheDir().getAbsolutePath() + "/" + ZIP_FILE_NAME;
try
{
mFos = new FileOutputStream(cachezipPath);
}
catch (FileNotFoundException e)
{
mErrorMsg = "Couldn't create a local file to store the image";
return false;
}
Notification("SmartExpense", "Now syncing to dropbox");
mApi.getFile("/SmartExpenses.zip",null,mFos,null);
try
{
FileInputStream fin = new FileInputStream(cachezipPath);
ZipInputStream zin = new ZipInputStream(fin);
ZipEntry ze = null;
if((ze = zin.getNextEntry()) != null)
{
Log.v("Decompress", "Unzipping " + ze.getName());
if(ze.isDirectory())
{
}
else
{
FileOutputStream fout = new FileOutputStream(cachefilePath);
for (int c = zin.read(); c != -1; c = zin.read())
{
fout.write(c);
}
zin.closeEntry();
fout.close();
}
}
zin.close();
}
catch(Exception ee)
{
Log.d("In unzip:", ""+ee);
}
try
{
FileInputStream fs =new FileInputStream(cachefilePath);
byte buff[] =new byte[1024];
while(fs.read(buff)>0)
{
xmlcode.append(new String(buff));
}
fs.close();
Log.d("Hhhhhhhhhhhaaaaaaaaaaaaa : ",""+xmlcode);
Looper.prepare();
if(!(xmlcode.toString().contains("<expenserecord>")) && getDBRecords())
{
doFirstTime();
Log.d("1","1");
}
else if((xmlcode.toString().contains("<expenserecord>")) && getDBRecords())
{
Log.d("2","2");
makeDropboxRecordArray();
performSync();
}
else if((xmlcode.toString().contains("<expenserecord>")) && !getDBRecords())
{
Log.d("3","3");
makeDropboxRecordArray();
fillDBwithDropboxRecords();
}
else if(!(xmlcode.toString().contains("<expenserecord>")) && !getDBRecords())
{
Log.d("4","4");
mErrorMsg ="No records exist to sync";
}
}
catch (Exception e)
{
Log.d("Exception in doback: ",""+e);
}
return true;
}
catch (DropboxUnlinkedException e)
{
mErrorMsg = "Error :Dropbox unliked";
// The AuthSession wasn't properly authenticated or user unlinked.
}
catch (DropboxPartialFileException e)
{
// We canceled the operation
mErrorMsg = "Download canceled";
}
catch (DropboxServerException e)
{
// Server-side exception. These are examples of what could happen,
// but we don't do anything special with them here.
if (e.error == DropboxServerException._304_NOT_MODIFIED)
{
mErrorMsg = "Server Error.....";
// won't happen since we don't pass in revision with metadata
}
else if (e.error == DropboxServerException._401_UNAUTHORIZED)
{
mErrorMsg = "Server Error : Unautherized user...";
// Unauthorized, so we should unlink them. You may want to
// automatically log the user out in this case.
}
else if (e.error == DropboxServerException._403_FORBIDDEN)
{
mErrorMsg = "Server Error : Access denied";
// Not allowed to access this
}
else if (e.error == DropboxServerException._404_NOT_FOUND)
{
no_file = true;
doFirstTime();
// path not found
}
else if (e.error == DropboxServerException._406_NOT_ACCEPTABLE)
{
mErrorMsg = "Server Error : Congestion...";
// too many entries to return
}
else if (e.error == DropboxServerException._507_INSUFFICIENT_STORAGE)
{
// user is over quota
mErrorMsg = "Server Error : Insufficient Storage...";
}
else
{
// Something else
mErrorMsg = "Server Error...";
}
// This gets the Dropbox error, translated into the user's language
mErrorMsg = e.body.userError;
if (mErrorMsg == null)
{
mErrorMsg = e.body.error;
}
}
catch (DropboxIOException e)
{
// Happens all the time, probably want to retry automatically.
mErrorMsg = "Network error. Try again.";
}
catch (DropboxParseException e)
{
// Probably due to Dropbox server restarting, should retry
mErrorMsg = "Dropbox error. Try again.";
}
catch (DropboxException e)
{
// Unknown error
mErrorMsg = "Unknown error. Try again.";
}
return false;
}
public void fillDBwithDropboxRecords()
{
Log.d("In fill db","yetoy");
try
{
for(int i=0 ; i<dropbox_records.size()-1 ; i++)
{
{
eop.addRecord(Integer.parseInt(dropbox_records.get(i).get(0)), dropbox_records.get(i).get(1), dropbox_records.get(i).get(2), Integer.parseInt(dropbox_records.get(i).get(3)));
}
}
}
catch (Exception e)
{
Log.d("In fill db", ""+e);
}
}
private void doFirstTime()
{
Log.d("yes2", " in do first time of download..");
try
{
if(!getDBRecords())
{
mErrorMsg = "No records exist to sync";
return;
}
newXMLCode.append("<smartexpense>");
for(int i=0 ; i<database_records.size() ; i++)
{
newXMLCode.append("<expenserecord>");
newXMLCode.append("<c_id>"+database_records.get(i).get(0)+"</c_id>");
newXMLCode.append("<title>"+database_records.get(i).get(1)+"</title>");
newXMLCode.append("<date>"+database_records.get(i).get(2)+"</date>");
newXMLCode.append("<amount>"+database_records.get(i).get(3)+"</amount>");
newXMLCode.append("</expenserecord>");
}//for
newXMLCode.append("</smartexpense>");
up = new UploadFile(mContext,mApi,newXMLCode.toString());
up.execute();
}
catch(Exception e)
{
Log.d("Exception in doFirtstTime : ",""+e);
}
}//doFirstTime
public void makeDropboxRecordArray()
{
Log.d("yes3", " in make record array of download..");
try
{
dropbox_xml_records = (xmlcode.toString()).split("</expenserecord>");
for(int i=0 ; i< dropbox_xml_records.length ; i++)
{
dropbox_records.add(new ArrayList<String>());
dropbox_records.get(i).add(dropbox_xml_records[i].substring(
((dropbox_xml_records[i].indexOf("<c_id>"))+
("<c_id>".length())),
dropbox_xml_records[i].indexOf("</c_id>")
));
dropbox_records.get(i).add(dropbox_xml_records[i].substring(
((dropbox_xml_records[i].indexOf("<title>"))+
("<title>".length())),
dropbox_xml_records[i].indexOf("</title>")
));
dropbox_records.get(i).add(dropbox_xml_records[i].substring(
((dropbox_xml_records[i].indexOf("<date>"))+
("<date>".length())),
dropbox_xml_records[i].indexOf("</date>")
));
dropbox_records.get(i).add(dropbox_xml_records[i].substring(
((dropbox_xml_records[i].indexOf("<amount>"))+
("<amount>".length())),
dropbox_xml_records[i].indexOf("</amount>")
));
}
}
catch (Exception e)
{
Toast.makeText(mContext,"In fill records :"+e , 2000).show();
}
}
public boolean getDBRecords()
{
Log.d("yes4", " in get dbrecords of download..");
try
{
Cursor cc = eop.getRecords();
if(cc.getCount() == 0)
return false;
int i=0;
if(cc.moveToFirst())
{
do
{
database_records.add(new ArrayList<String>());
database_records.get(i).add(cc.getString(cc.getColumnIndex("c_id")));
database_records.get(i).add(cc.getString(cc.getColumnIndex("title")));
database_records.get(i).add(cc.getString(cc.getColumnIndex("date")));
database_records.get(i).add(cc.getString(cc.getColumnIndex("amount")));
i++;
}while(cc.moveToNext());
}
cc.close();
}
catch(Exception ee)
{
Toast.makeText(mContext,"getDBRecords :"+ee , 2000).show();
}
return true;
}
public void performSync()
{
try
{
//compare database records with dropbox records
newXMLCode.append("<smartexpense>");
for(int i=0 ; i<database_records.size() ; i++)
{
newXMLCode.append("<expenserecord>");
newXMLCode.append("<c_id>"+database_records.get(i).get(0)+"</c_id>");
newXMLCode.append("<title>"+database_records.get(i).get(1)+"</title>");
newXMLCode.append("<date>"+database_records.get(i).get(2)+"</date>");
newXMLCode.append("<amount>"+database_records.get(i).get(3)+"</amount>");
newXMLCode.append("</expenserecord>");
}
for(int i=0 ; i<dropbox_records.size()-1 ; i++)
{
eop.addRecord(Integer.parseInt(dropbox_records.get(i).get(0)),
dropbox_records.get(i).get(1),
dropbox_records.get(i).get(2),
Integer.parseInt(dropbox_records.get(i).get(3)));
newXMLCode.append("<expenserecord>");
newXMLCode.append("<c_id>"+dropbox_records.get(i).get(0)+"</c_id>");
newXMLCode.append("<title>"+dropbox_records.get(i).get(1)+"</title>");
newXMLCode.append("<date>"+dropbox_records.get(i).get(2)+"</date>");
newXMLCode.append("<amount>"+dropbox_records.get(i).get(3)+"</amount>");
newXMLCode.append("</expenserecord>");
}
//}
newXMLCode.append("</smartexpense>");
Log.d("Comming : ","yetoy..");
up = new UploadFile(mContext,mApi,newXMLCode.toString());
up.execute();
}
catch (Exception e)
{
Log.d("Perform sync: ",""+e);
}
}
#Override
protected void onPostExecute(Boolean result)
{
//mDbHelper.close();
if (result)
{
//showToast("File successfully downloaded");
}
else
{
if(!no_file)
{
// Couldn't download it, so show an error
showToast("Error in sync.Check notification.");
Notification("SmartExpense", mErrorMsg);
}
}
}
private void showToast(String msg)
{
Toast error = Toast.makeText(mContext, msg, Toast.LENGTH_LONG);
error.show();
}
// Notification Function
private void Notification(String notificationTitle, String notificationMessage)
{
NotificationManager notificationManager = (NotificationManager)mContext.getSystemService(Context.NOTIFICATION_SERVICE);
Notification notification = new Notification(android.R.drawable.ic_menu_save, "Dropbox Sync", System.currentTimeMillis());
Intent notificationIntent = new Intent(mContext, UploadFile.class);
PendingIntent pendingIntent = PendingIntent.getActivity(mContext, 0, notificationIntent, 0);
notification.setLatestEventInfo(mContext, notificationTitle, notificationMessage, pendingIntent);
notificationManager.notify(10001, notification);
}
}
This error is received while you try and update your UI from a background thread. In your case the doInBackground method.
It appears that you are trying to post a notification from doInBackground from the following line.
Notification("SmartExpense", "Now syncing to dropbox");
This might be causing the issue. Try commenting this and any other UI updates you might be doing in doInBackground
This Exception indicates that you are trying to access UI elements in a non UI thread. From your code probably the problem is caused by these two lines inside your doInBackground method (you are accessing the Activity's context):
String cachefilePath = mContext.getCacheDir().getAbsolutePath() + "/" + FILE_NAME;
String cachezipPath = mContext.getCacheDir().getAbsolutePath() + "/" + ZIP_FILE_NAME;
If you declare this two variables outside the doInBackgroud method and instatiate them in your constructor, you should be ok. Also, remove the lines in your code that you are calling Looper.prepare() since they will not fix the problem.
So I have 2 threads (among others) on my application, one that modify an object (in the example , setting the position of a rectangle) and call methods so the second thread can send it on network.
First thread:
public void run(){
while(mIsRunning){
Log.i("MovingRectThread", "Run");
mX += 10;
mRect.setPos(mX,mY);
//Send Rect
mInterface.writeData(mRect);
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
Second thread:
public void run(){
int commandSize=-1;
byte[] bufferR = new byte[ANSWER_SIZE];
int answerResult = 0;
while(mIsRunning){
Log.i("ProcessThreadGraphic", "Run");
switch(mState){
case IDLEREAD:
//****************
try {
commandSize = mmInStream.read(bufferR, 0, ANSWER_SIZE);
}
catch (IOException e) {
connectionLost();
}
// We received something
if(commandSize != -1 && bufferR[0] == 0x02){
answerResult = bufferR[2];
if(answerResult == 0){
//Authorize sending again
mState = IDLEWRITE;
}
}
//*********************
break;
case IDLEWRITE:
//Trying to send something
if(mBuffer != null ){
try {
mmOutStream.write(mBuffer);
mBuffer = null;
mState = IDLEREAD;
Thread.yield();
} catch (IOException e) {
connectionLost();
}
}
//**************
break;
default:
Log.e(TAG, "Error: state unknown");
break;
}
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
and mInterface.writeData only end to call to:
public void write(byte[]buffer){
mBuffer = buffer;
}
My problem is, the threads are not working well together: one is looping multiple time before the other restart, which doesn't fit my needs as you can probably imagine, I need the first one to modify my object once, then the second thread to send it, and then only modify the object again...
Hope I've been clear enough.