Discovery System for android and desktop machines - android

I have a distributed system that consists of androids and desktop machines and they need to pass data (a simple serialized object) among themselves. I am interested in a jini-like discovery system for android using which androids/desktop machines can discover each other and then transfer data to each other. The distributed system is very dynamic, in the sense, devices come and go quite abruptly and frequently.
I tried to work with Cling and I could discover my router but could not discover other devices such as android phones. So I was wondering whether android devices are really UPnP compatible or there might be something wrong with my code.
I am using the code discussed in the Cling user manual.
EDIT: Posting the code below-
public class UpnpBrowserActivity extends ListActivity {
private AndroidUpnpService upnpService;
Registry registry;
private ArrayAdapter<DeviceDisplay> listAdapter;
private BrowseRegistryListener registryListener = new BrowseRegistryListener();
private ServiceConnection serviceConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className, IBinder service) {
upnpService = (AndroidUpnpService) service;
registry = upnpService.getRegistry();
// Refresh the list with all known devices
listAdapter.clear();
for (Device device : registry.getDevices()) {
registryListener.deviceAdded(registry,device);
}
// Getting ready for future device advertisements
registry.addListener(registryListener);
// Search asynchronously for all devices
upnpService.getControlPoint().search();
}
public void onServiceDisconnected(ComponentName className) {
upnpService = null;
}
};
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_upnp_browser);
listAdapter = new ArrayAdapter(this,android.R.layout.simple_list_item_1);
setListAdapter(listAdapter);
getApplicationContext().bindService(new Intent(this, AndroidUpnpServiceImpl.class),serviceConnection, Context.BIND_AUTO_CREATE);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.upnp_browser, menu);
menu.add(0, 0, 0, "Menu1").setIcon(android.R.drawable.ic_menu_search);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == 0 && upnpService != null) {
upnpService.getRegistry().removeAllRemoteDevices();
upnpService.getControlPoint().search();
}
return false;
}
#Override
protected void onDestroy() {
super.onDestroy();
if (upnpService != null) {
upnpService.getRegistry().removeListener(registryListener);
}
getApplicationContext().unbindService(serviceConnection);
}
class BrowseRegistryListener extends DefaultRegistryListener {
#Override
public void remoteDeviceDiscoveryStarted(Registry registry, RemoteDevice device) {
deviceAdded(device);
}
#Override
public void remoteDeviceDiscoveryFailed(Registry registry, final RemoteDevice device, final Exception ex) {
runOnUiThread(new Runnable() {
public void run() {
Toast.makeText(
UpnpBrowserActivity.this,
"Discovery failed of '" + device.getDisplayString() + "': " +
(ex != null ? ex.toString() : "Couldn't retrieve device/service descriptors"),
Toast.LENGTH_LONG
).show();
}
});
deviceRemoved(device);
}
#Override
public void remoteDeviceAdded(Registry registry, RemoteDevice device) {
deviceAdded(device);
}
#Override
public void remoteDeviceRemoved(Registry registry, RemoteDevice device) {
deviceRemoved(device);
}
#Override
public void localDeviceAdded(Registry registry, LocalDevice device) {
deviceAdded(device);
}
#Override
public void localDeviceRemoved(Registry registry, LocalDevice device) {
deviceRemoved(device);
}
public void deviceAdded(final Device device) {
runOnUiThread(new Runnable() {
public void run() {
DeviceDisplay d = new DeviceDisplay(device);
int position = listAdapter.getPosition(d);
if (position >= 0) {
// Device already in the list, re-set new value at same position
listAdapter.remove(d);
listAdapter.insert(d, position);
} else {
listAdapter.add(d);
}
}
});
}
public void deviceRemoved(final Device device) {
runOnUiThread(new Runnable() {
public void run() {
listAdapter.remove(new DeviceDisplay(device));
}
});
}
}
}
I also read this question on SO but if android devices cannot be discovered with Cling or another similar library, I would prefer to write a small discovery system using TCP/IP sockets.
Kindly guide me if I am missing or misunderstanding something. Any help is appreciated. Thanks in advance.

Related

Callback method only get called when debugger is attached

I'm writing an Android app which connects to an BLE device and shows the end result of the measurement. I'm using a library of the company for communicating with the device and the problem I have is that the callback functions (onMeasurementFinished,onMeasurementFailed, etc.) only get called if I set a breakpoint and run the app with a debugger attached.
Here is how I connect to the device:
#Override
public void onClick(View view) {
try {
if (view.getId() == R.id.btnConnect) {
deviceArm.scan(this, this);
}
} catch (Exception ex) {
Toast.makeText(this, ex.getMessage(), Toast.LENGTH_SHORT).show();
}
}
This is the callback of the scan that is working:
#Override
public void onDeviceConnected() {
txtResults.setText("Connected");
deviceArm.startMeasurement(this);
}
These are the callbacks of startMeasurement that only work if I debug:
#Override
public void onMeasurementError(Error error) {
runOnUiThread(new Runnable() {
#Override
public void run() {
txtResults.setText("Error");
}
});
}
#Override
public void onMeasurementFinished(MeasurementType measurementType, final Object o) {
runOnUiThread(new Runnable() {
#Override
public void run() {
txtResults.setText("Finished"+o.toString());
}
});
}
#Override
public void onMeasurementStarted() {
}
#Override
public void onMeasurementProgress(final MeasurementType measurementType, final Object o) {
runOnUiThread(new Runnable() {
#Override
public void run() {
txtResults.setText(o.toString());
}
});
}
I know it's not much information but I can only hope that mabey some of you have an idea what the problem could be.
What's likely happening is the peripheral device is doing some extra setup after connection. So putting a breakpoints in onDeviceConnected gives it time to do this.
As you say, not much information to go on, but it's possible the peripheral is sending the measurement results via notification/indication. So the peripheral needs time to configure these before starting measurments.
Try adding a delay in onDeviceConnected before starting the measurment. Ideally your library will have a callback along the lines of onDeviceReady, that you could use instead.

Bluetooth develop:sometimes the bluetoothadapter cannot find the device

I'm working at BLE develop and there is my problem.
Sometimes my bluetoothadapter cannot find the device when I used method bluetoothAdapter.startLeScan(callback).
And when adapter cannot found device,I just restart bluetoothadapter(meant:turn off the bluetoothadapter then turn on).
And then the callback will return the device instead null.
I have search much about BLE develop ,but it seems like nobody found this problem.
This is my callback:
private BluetoothAdapter.LeScanCallback mLeScanCallback = new BluetoothAdapter.LeScanCallback() {
#Override
public void onLeScan(final BluetoothDevice device, int rssi,byte[] scanRecord) {
runOnUiThread(new Runnable() {
#Override
public void run() {
synchronized (m_LeDevices) {
if (m_device_mac != null && m_device_mac.equals(device.getAddress().replace(":", ""))) {
mHandler.postDelayed(new Runnable() {
#Override
public void run() {
forwardToMain();
}
}, DELAY_FORWARD_TIME);
}
}
}
});
}
};

Voice Listen API in background using more battery

I am developing a app in android which listens to voice all the time in background. i am using SpeechRecognizer offline api . please can any body tell me any best option . My code is :
public void raise() {
try {
handler.post(new Runnable() {
#Override
public void run() {
offSound();
speech = SpeechRecognizer.createSpeechRecognizer(getApplicationContext());
listener = new MyRecognitionListener();
speech.setRecognitionListener(listener);
Intent intent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_PREFERENCE, SharedPreferenceWriter.getInstance(getApplicationContext()).getString(SPreferenceKey.SELECTED_LANGUAGE));
intent.putExtra(RecognizerIntent.EXTRA_CALLING_PACKAGE, getApplication().getPackageName());
intent.putExtra(RecognizerIntent.EXTRA_SPEECH_INPUT_POSSIBLY_COMPLETE_SILENCE_LENGTH_MILLIS, 1000);
intent.putExtra(RecognizerIntent.EXTRA_SPEECH_INPUT_COMPLETE_SILENCE_LENGTH_MILLIS, 1000);
intent.putExtra(RecognizerIntent.EXTRA_SPEECH_INPUT_MINIMUM_LENGTH_MILLIS, 1000);
intent.putExtra(RecognizerIntent.EXTRA_ONLY_RETURN_LANGUAGE_PREFERENCE, true);
enter code here
speech.startListening(intent);
/*
* if (countPrintLog++ > 150) { countPrintLog = 0;
* LogManager
* .getInstance().writeToLog(LogManager.LOG_STORAGE_FILE,
* "Speech Recogniser is working"); }
*/
Log.i("", "Calling the Recognise");
}
});
} catch (Exception e) {
e.printStackTrace();
}
}
class MyRecognitionListener implements RecognitionListener {
#Override
public void onBeginningOfSpeech() {
}
#Override
public void onBufferReceived(byte[] buffer) {
}
#Override
public void onEndOfSpeech() {
}
#Override
public void onError(int error) {
onSound();
Log.i("", "onError");
isCriticalSectionRaise = false;
}
#Override
public void onEvent(int eventType, Bundle params) {
}
#Override
public void onPartialResults(Bundle partialResults) {
}
#Override
public void onReadyForSpeech(Bundle params) {
}
#Override
public void onResults(Bundle results) {
}
#Override
public void onRmsChanged(float rmsdB) {
}
}
This consumes a lot of battery resource and heats the device. I'm looking for a better option
Large vocabulary speech recognition requires quite a lot of resources, you need to use special solution to listen continuously.
If you are interested, take a look on CMUSphinx on Android
http://cmusphinx.sourceforge.net/wiki/tutorialandroid
Demo above can listen for keyword "oh mighty computer" efficiently, you can configure the keyword and detection threshold. On our experiment the listening takes less resources than screen and the battery easily lasts whole day.

Android Network Service Discovery not firing listener

I've been playing around with Android's Network Service Discovery capabilities recently. I have everything working, but for some reason I can't get the NsdManager.RegistrationListener to ever get called now.
I'm initializing it with a simple callback and then calling registerService, but it's not calling onServiceRegistered or onRegistrationFailed. The code is below. I am running this registration inside a service, if that matters.
What I see in the log is "registering service", but never one of the callbacks in the listener.
private NsdManager mNsdManager;
private NsdManager.RegistrationListener mRegistrationListener;
#Override
public void onCreate() {
super.onCreate();
mNsdManager = (NsdManager) getApplicationContext().getSystemService(getApplicationContext().NSD_SERVICE);
initializeRegistrationListener();
startAdvertising();
}
public void initializeRegistrationListener() {
mRegistrationListener = new NsdManager.RegistrationListener() {
#Override
public void onRegistrationFailed(NsdServiceInfo serviceInfo, int errorCode) {
Log.i("myapp", "failed");
}
#Override
public void onUnregistrationFailed(NsdServiceInfo serviceInfo, int errorCode) {
}
#Override
public void onServiceRegistered(NsdServiceInfo serviceInfo) {
Log.i("myapp", "success");
}
#Override
public void onServiceUnregistered(NsdServiceInfo serviceInfo) {
}
};
}
public void startAdvertising() {
NsdServiceInfo serviceInfo = new NsdServiceInfo();
serviceInfo.setPort(new ServerSocket(0).getLocalPort());
serviceInfo.setServiceName("_myapp_one");
serviceInfo.setServiceType("_http._tcp.");
Log.i("myapp", "registering service");
mNsdManager.registerService(serviceInfo, NsdManager.PROTOCOL_DNS_SD, mRegistrationListener);
}
I had the same problem. The callbacks onServiceRegistered or onRegistrationFailed never occurred. In my case I solved it by uninstalling my app and rebooting the mobile phones I was using.
Android changes the service name in order to resolve a conflict, so that's why we need to update the name that we initially requested with the name Android actually used. I run the application so many times that could it be that Android may have ran out of service names?

How to update UI thread when Network call is placed before rotating?

Okay this is driving me nuts. I have a worker thread, (Network call) that needs to run separate of the UI thread, (Its actually a ThreadPoolExecutor but I simplified it to prove my point). If you run this code in portrait, without rotation, the text updates. I put in the delay there to allow for rotations to show my issue. If you start in portrait and before text updates rotation to landscape the text does not update. If you comment the code you can see the listener fire but the text never updates.
I am trying to simulate a custom network call running in a separate thread that may take some time to come back if the user rotates in between then the data gets lost. We are trying to prevent multiple network calls to save data usage on a phone.
package com.example.test;
import android.os.Bundle;
import android.os.Handler;
import android.app.Activity;
import android.content.res.Configuration;
import android.view.Menu;
import android.widget.TextView;
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
int orientation = getResources().getConfiguration().orientation;
if (Configuration.ORIENTATION_LANDSCAPE == orientation) {
//Do SomeThing; // Landscape
} else {
startBackgroundWork();
//Do SomeThing; // Portrait
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
private Handler mHandler = new Handler();
public void startBackgroundWork() {
new WorkingThread(new SomeListener() {
public void onSomethingDone(final Object result) {
mHandler.post(new Runnable() {
public void run() {
((TextView)findViewById(R.id.text)).setText((String)result);
//showMyDialog(result);
}
});
}
}).start();
}
public interface SomeListener {
public void onSomethingDone(Object result);
}
public class WorkingThread extends Thread {
private SomeListener mListener;
public WorkingThread(SomeListener listener) {
mListener = listener;
}
public void run() {
/* do some work */
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
mListener.onSomethingDone("New Text");
}
}
}
It's because on rotation, the activity is re created, therefore all your code is binded to the old activity. You should make a reference to your working thread :
private static WorkingThread mWorkingThread;
public void startBackgroundWork() {
mWorkingThread = new WorkingThread(new SomeListener() {
public void onSomethingDone(final Object result) {
mHandler.post(new Runnable() {
public void run() {
((TextView)findViewById(R.id.text)).setText((String)result);
//showMyDialog(result);
}
});
}
}).start();
}
then onCreate update it :
public class WorkingThread extends Thread {
private SomeListener mListener;
public WorkingThread(SomeListener listener) {
mListener = listener;
}
public void run() {
/* do some work */
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
mListener.onSomethingDone("New Text");
}
public void updateListener(SomeListener listener) {
mListener = listener;
}
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
startBackgroundWork();
}
public void startBackgroundWork() {
if (mWorkingThread == null || mWorkingThread.isFinished()) { // Use a boolean to know if it still running
mWorkingThread = new WorkingThread(new SomeListener() {
public void onSomethingDone(final Object result) {
mHandler.post(new Runnable() {
public void run() {
((TextView)findViewById(R.id.text)).setText((String)result);
//showMyDialog(result);
}
});
}
});
mWorkingThread.start();
} else {
mWorkingThread.updateListener(new SomeListener() {
public void onSomethingDone(final Object result) {
mHandler.post(new Runnable() {
public void run() {
((TextView)findViewById(R.id.text)).setText((String)result);
//showMyDialog(result);
}
});
}
});
}
}
But there is some improvments you could make :
The WorkingThread class should be static to avoid direct reference to the old activity : Java: Static vs non static inner class
Then make a reference to the current activity, and update it when it is recreated
Make a method for update of the text, instead of having the code directly in the listener

Categories

Resources