Open cesarev91 opened 7 years ago
The node connection is done inside the NodeContainerFragment, so you can't be secure about when it starts and when the connection is done.
Are you secure that the node is connected when the onResume method is celled?
Try to implementa a logic like this one: FeatureListActivity#onResume
Giovanni
Ciao Giovanni,
I tried how you told me and you were right the knot was not connected. But now I have a problem with interacting more features on a single activity. My layout is unique and is handled with a single activity on which I elaborate the data of all the feature. Microphone and Activity Recognition combined to return the animal's status. Battery to handle the battery of SensorTile and AudioADPCM and ADPCMSync to play audio. I tried to keep the features to read the dog's status and it works, but trying to enable ADPCM audio also the node disconnects and the app crashes Do you think it's a problem to handle everything on a single activity, or can you do it?
Cesare
Ciao Cesare,
Do you have some error before the app crashes? The possible problem could be that the audio transmit a lot of data and enabling also the other features could freeze the system.
Giovanni
I have to try to reactivate audio features and see if it hangs. At the moment I'm trying to use microphone and activity in a combination and work, that is, they come into one of the conditions I've created and make a change of image. I've created two textview so you can read the event and the microphone level in real time. I do not understand why both of them are set continuously on ERROR (event) and -128 (level).
This is the code at the moment: `public class MainActivity extends AppCompatActivity {
/**
* create an intent for start the activity that will log the information from the node
*
* @param c context used for create the intent
* @param node note that will be used by the activity
* @return intent for start this activity
*/
public static Intent getStartIntent(Context c, @NonNull Node node) {
Intent i = new Intent(c, MainActivity.class);
i.putExtra(NODE_TAG, node.getTag());
i.putExtras(NodeContainerFragment.prepareArguments(node));
return i;
}
private final static String NODE_FRAGMENT = MainActivity.class.getCanonicalName() + "" +
".NODE_FRAGMENT";
private final static String NODE_TAG = MainActivity.class.getCanonicalName() + "" +
".NODE_TAG";
/** fragment used for keep the connection open */
private NodeContainerFragment mNodeContainer;
/**
* nodo che mostrerà i dati
*/
private Node mNode;
// Feature on which to apply the listener
private FeatureActivity mfeatureAct;
private FeatureMicLevel mMicLevel;
//private FeatureBattery mBattery;
private FeatureAudioADPCM mAudio;
// feature where we read the audio sync values
private FeatureAudioADPCMSync mAudioSync;
// Audio track builder
private AudioTrack mAudioTrack;
// The sampling rate
private static final int SAMPLE_RATE = 8000;
//object containing the sync data needed in a ADPCM stream decoding
private BVAudioSyncManager mBVAudioSyncManager = new BVAudioSyncManager();
// audio manager
private static final int AUDIO_STREAM = AudioManager.STREAM_MUSIC;
private boolean mIsRecording;
private AudioBuffer mRecordedAudio;
//private AudioRecord mRecordedAudio;
private static final int MAX_RECORDING_TIME_S = 30;
/**
* listener that will be used for enable the notification when the node is connected
*/
public Node.NodeStateListener mNodeStatusListener = new Node.NodeStateListener() {
@Override
public void onStateChange(final Node node, final Node.State newState, final Node.State prevState) {
if (newState == Node.State.Connected) {
MainActivity.this.runOnUiThread(new Runnable() {
@Override
public void run() {
// Feature Activity Listener
mfeatureAct.addFeatureListener(mListeners);
mNode.enableNotification(mfeatureAct);
//mNode.readFeature(mfeatureAct);
// Feature MicLevel Listener
mMicLevel.addFeatureListener(mListeners);
mNode.enableNotification(mMicLevel);
mNode.readFeature(mMicLevel);
// Feature Battery Listener
// mBattery.addFeatureListener(mBatteryListner);
// mNode.enableNotification(mBattery);
// mNode.readFeature(mBattery);
}//run
});
}//if
}//onStateChange
};
TextView eventText;
TextView levelText;
public final Feature.FeatureListener mListeners = new Feature.FeatureListener() {
@Override
public void onUpdate(Feature f, Feature.Sample sample) {
final FeatureActivity.ActivityType event = FeatureActivity.getActivityStatus(sample);
final byte levelMic = FeatureMicLevel.getMicLevel(sample,1);
if(event!=null){
MainActivity.this.runOnUiThread(new Runnable() {
@Override
public void run() {
eventText.setText("Event:"+event);
levelText.setText("MicLevel:"+levelMic);
if ((event.equals(FeatureActivity.ActivityType.STATIONARY))&& levelMic < 30) {
mStatusImage.setImageResource(R.drawable.cane_zen);
mStatusText.setText("Calm");
mStatusText.setBackgroundColor(Color.GREEN);
}
else if(event.equals(FeatureActivity.ActivityType.WALKING)&& levelMic>35){
mStatusImage.setImageResource(R.drawable.cane_nervoso);
mStatusText.setText("Nervous");
mStatusText.setBackgroundColor(Color.RED);
}
else if (event.equals(FeatureActivity.ActivityType.JOGGING) && (levelMic>=30&&levelMic<=35)) {
mStatusImage.setImageResource(R.drawable.cane_giocoso);
mStatusText.setText("Playful");
mStatusText.setBackgroundColor(Color.YELLOW);
}
}
});
}
}
};
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
ImageView mStatusImage;
TextView mStatusText;
ImageView mBatteryImage;
TextView mBatteryText;
Button mPlayButton;
Button mStopButton;
SeekBar mVolumeBar;
FloatingActionButton mRecordButton;
ProgressBar mRecordBar;
AudioManager mAudioManager;
private TextView mRequestStatus;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// find the node.
String nodeTag = getIntent().getStringExtra(NODE_TAG);
mNode = Manager.getSharedInstance().getNodeWithTag(nodeTag);
//create/recover the NodeContainerFragment (DebugConsoleActivity.java)
if (savedInstanceState == null) {
Intent i = getIntent();
mNodeContainer = new NodeContainerFragment();
mNodeContainer.setArguments(i.getExtras());
getFragmentManager().beginTransaction()
.add(mNodeContainer, NODE_FRAGMENT).commit();
} else {
mNodeContainer = (NodeContainerFragment) getFragmentManager()
.findFragmentByTag(NODE_FRAGMENT);
}//if-else
mfeatureAct = mNode.getFeature(FeatureActivity.class);
mMicLevel = mNode.getFeature(FeatureMicLevel.class);
//mBattery = mNode.getFeature(FeatureBattery.class);
//mAudio = mNode.getFeature(FeatureAudioADPCM.class);
//mAudioSync = mNode.getFeature(FeatureAudioADPCMSync.class);
mStatusImage = (ImageView)findViewById(R.id.statusImage);
mStatusText = (TextView)findViewById(R.id.statusText);
mBatteryImage = (ImageView)findViewById(R.id.batteryImage);
mBatteryText = (TextView)findViewById(R.id.batteryText);
mPlayButton = (Button) findViewById(R.id.playButton);
mStopButton = (Button) findViewById(R.id.stopButton);
mVolumeBar = (SeekBar)findViewById(R.id.volumeBar);
mRecordBar = (ProgressBar) findViewById(R.id.recordTimeValue);
mRecordBar.setIndeterminate(false);
mRecordButton = (FloatingActionButton) findViewById(R.id.recordButton);
mRequestStatus = (TextView) findViewById(R.id.requestStatus);
eventText = (TextView)findViewById(R.id.eventText);
levelText = (TextView)findViewById(R.id.levelText);
}
@Override
public void onResume() {
super.onResume();
mNode.addNodeStateListener(mNodeStatusListener);
}
@Override
public void onPause() {
super.onPause();
mNode.removeNodeStateListener(mNodeStatusListener);
}
}`
public void onUpdate(Feature f, Feature.Sample sample) {
final FeatureActivity.ActivityType event = FeatureActivity.getActivityStatus(sample);
final byte levelMic = FeatureMicLevel.getMicLevel(sample,1);
I don't know it the problem is this, but for secure you can't call both the getActivityStatus
and getMicLevel
passing the same sample object, because a sample contains the activity OR the micLevel..
so one of the two call is giving you an error code..
Check the feature type using instanceof
or create 2 different listener.
I tried with two different listeners and it works, there was also a mistake in getMicLevel (), it was put 0 in place of 1, so I can even read the microphone level and there is no more -128. Then I also activated the whole part to handle the audio but unfortunately nothing works even if it does not hang up, just do not give me any data. I noticed that she does not enter the listener of the audio part. By activating only the audio part and disabling the dog's state, the audio is working. I'm not sure but managing too much data in an activity brings the app into confusion. What do you think about it?
Current code:
`public class MainActivity extends AppCompatActivity {
/**
* create an intent for start the activity that will log the information from the node
*
* @param c context used for create the intent
* @param node note that will be used by the activity
* @return intent for start this activity
*/
public static Intent getStartIntent(Context c, @NonNull Node node) {
Intent i = new Intent(c, MainActivity.class);
i.putExtra(NODE_TAG, node.getTag());
i.putExtras(NodeContainerFragment.prepareArguments(node));
return i;
}
private final static String NODE_FRAGMENT = MainActivity.class.getCanonicalName() + "" +
".NODE_FRAGMENT";
private final static String NODE_TAG = MainActivity.class.getCanonicalName() + "" +
".NODE_TAG";
/** fragment used for keep the connection open */
private NodeContainerFragment mNodeContainer;
/**
* nodo che mostrerà i dati
*/
private Node mNode;
// Feature on which to apply the listener
private FeatureActivity mfeatureAct;
private FeatureMicLevel mMicLevel;
//private FeatureBattery mBattery;
private FeatureAudioADPCM mAudio;
// feature where we read the audio sync values
private FeatureAudioADPCMSync mAudioSync;
// Audio track builder
private AudioTrack mAudioTrack;
// The sampling rate
private static final int SAMPLE_RATE = 8000;
//object containing the sync data needed in a ADPCM stream decoding
private BVAudioSyncManager mBVAudioSyncManager = new BVAudioSyncManager();
// audio manager
private static final int AUDIO_STREAM = AudioManager.STREAM_MUSIC;
private boolean mIsRecording;
private AudioBuffer mRecordedAudio;
//private AudioRecord mRecordedAudio;
private static final int MAX_RECORDING_TIME_S = 30;
/**
* listener that will be used for enable the notification when the node is connected
*/
public Node.NodeStateListener mNodeStatusListener = new Node.NodeStateListener() {
@Override
public void onStateChange(final Node node, final Node.State newState, final Node.State prevState) {
if (newState == Node.State.Connected) {
MainActivity.this.runOnUiThread(new Runnable() {
@Override
public void run() {
// Feature Activity Listener
mfeatureAct.addFeatureListener(mActListener);
mNode.enableNotification(mfeatureAct);
//mNode.readFeature(mfeatureAct);
// Feature MicLevel Listener
mMicLevel.addFeatureListener(mMicListener);
mNode.enableNotification(mMicLevel);
mNode.readFeature(mMicLevel);
// Feature Battery Listener
// mBattery.addFeatureListener(mBatteryListner);
// mNode.enableNotification(mBattery);
// mNode.readFeature(mBattery);
// Features Audio Listener
mAudio.addFeatureListener(mAudioListener);
mBVAudioSyncManager.reinitResetFlag();
mAudio.setAudioSyncManager(mBVAudioSyncManager);
mNode.enableNotification(mAudio);
mAudioSync.addFeatureListener(mAudioSyncListener);
mNode.enableNotification(mAudioSync);
}//run
});
}//if
}//onStateChange
};
TextView eventText;
TextView levelText;
FeatureActivity.ActivityType event;
public final Feature.FeatureListener mActListener = new Feature.FeatureListener() {
@Override
public void onUpdate(Feature f, Feature.Sample sample) {
event = FeatureActivity.getActivityStatus(sample);
MainActivity.this.runOnUiThread(new Runnable() {
@Override
public void run() {
eventText.setText("Event:"+event);
}
});
MainActivity.this.runOnUiThread(new Runnable() {
@Override
public void run() {
if ((event.equals(FeatureActivity.ActivityType.STATIONARY)||event.equals(FeatureActivity.ActivityType.WALKING))&& levelMic < 30) {
mStatusImage.setImageResource(R.drawable.cane_zen);
mStatusText.setText("Calm");
mStatusText.setBackgroundColor(Color.GREEN);
}
else if (event.equals(FeatureActivity.ActivityType.FASTWALKING)&& levelMic > 50){
mStatusImage.setImageResource(R.drawable.cane_nervoso);
mStatusText.setText("Nervous");
mStatusText.setBackgroundColor(Color.RED);
}
else if(event.equals(FeatureActivity.ActivityType.JOGGING)){
mStatusImage.setImageResource(R.drawable.cane_giocoso);
mStatusText.setText("Playful");
mStatusText.setBackgroundColor(Color.YELLOW);
}
}
});
}
};
byte levelMic;
public final Feature.FeatureListener mMicListener = new Feature.FeatureListener() {
@Override
public void onUpdate(Feature f, Feature.Sample sample) {
levelMic = FeatureMicLevel.getMicLevel(sample,0);
MainActivity.this.runOnUiThread(new Runnable() {
@Override
public void run() {
if(levelMic > 0 && levelMic < 128){
levelText.setText("MicLevel:"+levelMic);
}
}
});
}
};
/**
* listener for the audio feature, it will updates the audio values
*/
public final Feature.FeatureListener mAudioListener = new Feature.FeatureListener() {
@Override
public void onUpdate(final Feature f, final Feature.Sample sample) {
short[] audioSample = FeatureAudioADPCM.getAudio(sample);
/* Write audio data for playback
* @param short : The array that contains the data for playback
* @param int: offset in rawAudio where playback data begins
* @param int: The number of shorts to read in rawAudio after the offset
*/
mAudioTrack.write(audioSample,0,audioSample.length);
}
};
/**
* listener for the audioSync feature, it will update the synchronism values
*/
public final Feature.FeatureListener mAudioSyncListener = new Feature.FeatureListener() {
@Override
public void onUpdate(Feature f, final Feature.Sample sample) {
if(mBVAudioSyncManager!=null){
mBVAudioSyncManager.setSyncParams(sample);
}
}
};
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
ImageView mStatusImage;
TextView mStatusText;
ImageView mBatteryImage;
TextView mBatteryText;
Button mPlayButton;
Button mStopButton;
SeekBar mVolumeBar;
FloatingActionButton mRecordButton;
ProgressBar mRecordBar;
AudioManager mAudioManager;
private TextView mRequestStatus;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// find the node.
String nodeTag = getIntent().getStringExtra(NODE_TAG);
mNode = Manager.getSharedInstance().getNodeWithTag(nodeTag);
//create/recover the NodeContainerFragment (DebugConsoleActivity.java)
if (savedInstanceState == null) {
Intent i = getIntent();
mNodeContainer = new NodeContainerFragment();
mNodeContainer.setArguments(i.getExtras());
getFragmentManager().beginTransaction()
.add(mNodeContainer, NODE_FRAGMENT).commit();
} else {
mNodeContainer = (NodeContainerFragment) getFragmentManager()
.findFragmentByTag(NODE_FRAGMENT);
}//if-else
mfeatureAct = mNode.getFeature(FeatureActivity.class);
mMicLevel = mNode.getFeature(FeatureMicLevel.class);
//mBattery = mNode.getFeature(FeatureBattery.class);
mAudio = mNode.getFeature(FeatureAudioADPCM.class);
mAudioSync = mNode.getFeature(FeatureAudioADPCMSync.class);
//builder audio track
mAudioTrack = new AudioTrack(
AudioManager.STREAM_MUSIC,
SAMPLE_RATE,
AudioFormat.CHANNEL_OUT_MONO,
AudioFormat.ENCODING_PCM_16BIT,
FeatureAudioADPCM.AUDIO_PACKAGE_SIZE,
AudioTrack.MODE_STREAM);
mStatusImage = (ImageView)findViewById(R.id.statusImage);
mStatusText = (TextView)findViewById(R.id.statusText);
mBatteryImage = (ImageView)findViewById(R.id.batteryImage);
mBatteryText = (TextView)findViewById(R.id.batteryText);
mPlayButton = (Button) findViewById(R.id.playButton);
mStopButton = (Button) findViewById(R.id.stopButton);
mVolumeBar = (SeekBar)findViewById(R.id.volumeBar);
mRecordBar = (ProgressBar) findViewById(R.id.recordTimeValue);
mRecordBar.setIndeterminate(false);
mRecordButton = (FloatingActionButton) findViewById(R.id.recordButton);
mRequestStatus = (TextView) findViewById(R.id.requestStatus);
eventText = (TextView)findViewById(R.id.eventText);
levelText = (TextView)findViewById(R.id.levelText);
// When the play button is pressed
mPlayButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mAudioTrack.play();
mAudioManager.setStreamVolume(AUDIO_STREAM,mVolumeBar.getProgress(),0);
}
});
//When the stop button is pressed
mStopButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
stopAudioTrack();
mAudioManager.setStreamVolume(AUDIO_STREAM,0,0);
}
});
//enable control volume
setVolumeControlStream(AudioManager.STREAM_MUSIC);
initControls();
}
private void stopAudioTrack(){
synchronized(this) {
mAudioTrack.pause();
mAudioTrack.flush();
}
}
// Volume control from SeekBar
private void initControls()
{
try
{
mVolumeBar = (SeekBar)findViewById(R.id.volumeBar);
mAudioManager = (AudioManager)getSystemService(Context.AUDIO_SERVICE);
mVolumeBar.setMax(mAudioManager
.getStreamMaxVolume(AudioManager.STREAM_MUSIC));
mVolumeBar.setProgress(mAudioManager
.getStreamVolume(AudioManager.STREAM_MUSIC));
mVolumeBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener()
{
@Override
public void onStopTrackingTouch(SeekBar arg0)
{
}
@Override
public void onStartTrackingTouch(SeekBar arg0)
{
}
@Override
public void onProgressChanged(SeekBar arg0, int progress, boolean arg2)
{
mAudioManager.setStreamVolume(AudioManager.STREAM_MUSIC,
progress, 0);
}
});
}
catch (Exception e)
{
e.printStackTrace();
}
}
@Override
public void onResume() {
super.onResume();
mNode.addNodeStateListener(mNodeStatusListener);
}
@Override
public void onPause() {
super.onPause();
mNode.removeNodeStateListener(mNodeStatusListener);
}
} `
Ciao Giovanni,
I've changed the way I work, because managing a lot of data on a single activity does not allow the app to work Now I'm using three activities and three layouts, I've also created an activity that shows the features (status, audio, battery). ScanActivity -> FunctionActivity -> StatusActivity, AudioActivity, BatteryActivity The app starts without errors but I do not receive any data. This is the StatusActivity class: `public class StatusActivity extends AppCompatActivity {
/**
* create an intent for start the activity that will log the information from the node
*
* @param c context used for create the intent
* @param node note that will be used by the activity
* @return intent for start this activity
*/
public static Intent getStartIntent(Context c, @NonNull Node node) {
Intent i = new Intent(c, StatusActivity.class);
i.putExtra(NODE_TAG, node.getTag());
i.putExtras(NodeContainerFragment.prepareArguments(node));
return i;
}
private final static String NODE_TAG = StatusActivity.class.getCanonicalName() + "" +
".NODE_TAG";
private final static String NODE_FRAGMENT = StatusActivity.class.getCanonicalName() + "" +
".NODE_FRAGMENT";
/** fragment used for keep the connection open */
private NodeContainerFragment mNodeContainer;
/**
* nodo che mostrerà i dati
*/
private Node mNode;
// Feature on which to apply the listener
private FeatureActivity mActivity;
private FeatureMicLevel mMicLevel;
/**
* listener that will be used for enable the notification when the node is connected
*/
public Node.NodeStateListener mNodeStatusListener = new Node.NodeStateListener() {
@Override
public void onStateChange(final Node node, final Node.State newState, final Node.State prevState) {
if (newState == Node.State.Connected) {
StatusActivity.this.runOnUiThread(new Runnable() {
@Override
public void run() {
// Feature Activity Listener
mActivity.addFeatureListener(mActListener);
mNode.enableNotification(mActivity);
mNode.readFeature(mActivity);
// Feature MicLevel Listener
mMicLevel.addFeatureListener(mMicListener);
mNode.enableNotification(mMicLevel);
mNode.readFeature(mMicLevel);
}//run
});
}//if
}//onStateChange
};
TextView mEventText;
TextView mLevelText;
FeatureActivity.ActivityType event;
public Feature.FeatureListener mActListener = new Feature.FeatureListener() {
@Override
public void onUpdate(Feature f, Feature.Sample sample) {
if(f.getName().equals("Activity Recognition")){
event = FeatureActivity.getActivityStatus(sample);
StatusActivity.this.runOnUiThread(new Runnable() {
@Override
public void run() {
mEventText.setText("Event:"+event);
}
});
}
StatusActivity.this.runOnUiThread(new Runnable() {
@Override
public void run() {
if ((event.equals(FeatureActivity.ActivityType.STATIONARY)||event.equals(FeatureActivity.ActivityType.WALKING))&& levelMic < 30) {
mStatusImage.setImageResource(R.drawable.cane_zen);
mStatusText.setText("Calm");
mStatusText.setBackgroundColor(Color.GREEN);
}
else if (event.equals(FeatureActivity.ActivityType.FASTWALKING)&& levelMic > 50){
mStatusImage.setImageResource(R.drawable.cane_nervoso);
mStatusText.setText("Nervous");
mStatusText.setBackgroundColor(Color.RED);
}
else if(event.equals(FeatureActivity.ActivityType.JOGGING)){
mStatusImage.setImageResource(R.drawable.cane_giocoso);
mStatusText.setText("Playful");
mStatusText.setBackgroundColor(Color.YELLOW);
}
}
});
}
};
byte levelMic;
public Feature.FeatureListener mMicListener = new Feature.FeatureListener() {
@Override
public void onUpdate(Feature f, Feature.Sample sample) {
if(f.getName().equals("Mic Level")){
levelMic = FeatureMicLevel.getMicLevel(sample,0);
StatusActivity.this.runOnUiThread(new Runnable() {
@Override
public void run() {
if(levelMic > 0 && levelMic <= 128){
mLevelText.setText("MicLevel:"+levelMic);
}
}
});
}
}
};
ImageView mStatusImage;
TextView mStatusText;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_status);
// find the node.
String nodeTag = getIntent().getStringExtra(NODE_TAG);
mNode = Manager.getSharedInstance().getNodeWithTag(nodeTag);
//create/recover the NodeContainerFragment
if (savedInstanceState == null) {
Intent i = getIntent();
mNodeContainer = new NodeContainerFragment();
mNodeContainer.setArguments(i.getExtras());
getFragmentManager().beginTransaction()
.add(mNodeContainer, NODE_FRAGMENT).commit();
} else {
mNodeContainer = (NodeContainerFragment) getFragmentManager()
.findFragmentByTag(NODE_FRAGMENT);
}//if-else
mActivity = mNode.getFeature(FeatureActivity.class);
mMicLevel = mNode.getFeature(FeatureMicLevel.class);
mStatusImage = (ImageView)findViewById(R.id.statusImage);
mStatusText = (TextView)findViewById(R.id.statusText);
mEventText = (TextView)findViewById(R.id.eventText);
mLevelText = (TextView)findViewById(R.id.mic_levelText);
}
@Override
public void onResume() {
super.onResume();
mNode.addNodeStateListener(mNodeStatusListener);
}
@Override
public void onPause() {
super.onPause();
mNode.removeNodeStateListener(mNodeStatusListener);
}
/**
* if we have to leave this activity, we force to keep the connection open, since we go back
* in the {@link FunctionsActivity}
*
*/
@Override
public void onBackPressed() {
mNodeContainer.keepConnectionOpen(true);
super.onBackPressed();
}//onBackPressed
} `
How do I keep the node connected during the operation of each activity?
Note that if the node is already connected your activity will not work, since you will not receive the connection event. Please see FeatureListActivity#onResume()
The connection is managed inside the NodeContainerFragment, to avoid to close it you have to call mNodeContainer.keepConnectionOpen(true)
before start the new activity this will avoid to disconnect the node when the fragment is destroyed
see:
FeatureListActivity#onOptionsItemSelected()
In the FunctionActivity class when I call other activities I use keepConnectionOpen (true) This is the FunctionActivity class: `public class FunctionsActivity extends AppCompatActivity {
/**
* create an intent for start the activity that will log the information from the node
*
* @param c context used for create the intent
* @param node note that will be used by the activity
* @return intent for start this activity
*/
public static Intent getStartIntent(Context c, @NonNull Node node) {
Intent i = new Intent(c, FunctionsActivity.class);
i.putExtra(NODE_TAG, node.getTag());
i.putExtras(NodeContainerFragment.prepareArguments(node));
return i;
}
/**
* tag used for store the node id that permit us to find the node selected by the user
*/
private final static String NODE_TAG = FunctionsActivity.class.getCanonicalName() + "" +
".NODE_TAG";
/**
* tag used for retrieve the NodeContainerFragment
*/
private final static String NODE_FRAGMENT = FunctionsActivity.class.getCanonicalName() + "" +
".NODE_FRAGMENT";
/**
* fragment that manage the node connection and avoid a re connection each time the activity
* is recreated
*/
private NodeContainerFragment mNodeContainer;
/**
* node that will stream the data
*/
private Node mNode;
Button statusButton;
Button audioButton;
Button batteryButton;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_functions);
//find the node
String nodeTag = getIntent().getStringExtra(NODE_TAG);
mNode = Manager.getSharedInstance().getNodeWithTag(nodeTag);
// Node.State state = mNode.getState();
// System.out.print("Stato: "+state);
//create or recover the NodeContainerFragment
if (savedInstanceState == null) {
Intent i = getIntent();
mNodeContainer = new NodeContainerFragment();
mNodeContainer.setArguments(i.getExtras());
getFragmentManager().beginTransaction()
.add(mNodeContainer, NODE_FRAGMENT).commit();
} else {
mNodeContainer = (NodeContainerFragment) getFragmentManager()
.findFragmentByTag(NODE_FRAGMENT);
}//if-else
statusButton = (Button)findViewById(R.id.status_button);
audioButton = (Button)findViewById(R.id.audio_button);
batteryButton = (Button)findViewById(R.id.battery_button);
statusButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
mNodeContainer.keepConnectionOpen(true);
startActivity(StatusActivity.getStartIntent(getApplicationContext(),mNode));
}
});
audioButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
mNodeContainer.keepConnectionOpen(true);
startActivity(AudioActivity.getStartIntent(getApplicationContext(),mNode));
}
});
batteryButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
mNodeContainer.keepConnectionOpen(true);
startActivity(BatteryActivity.getStartIntent(getApplicationContext(),mNode));
}
});
}
`
Usually you pass the current activity as a context, but anyway it seems ok, it is not working?
if the keepConnectionOpen
is not working please open a new issue..
About your activity that doesn't receive data: Since you split the activity and you have the same problem probably you don't have to much data, but you or the SDK are doing something wrong..
As already told the only weak point that I see is the onResume
function that will not enable the notification if the node connect before the onResume
is called.
Try to isolate the problem, create an activity that only enable the micLevel, get it works, than add another feature..
maybe you can set a breakpoint into the BluetoothGattCallbacks object to follow all the low level BLE comunication..
Ciao Giovanni,
In the StatusActivity class, I inserted these two lines of code after instantiating mNode, which tell me if the node is connected:
Node.State state = mNode.getState (); System.out.print ("Status:" + state);
The node is connected to the onCreate but I can not get into any of the listeners; the app starts without errors but does not show any data. Now I will try to run MicLevel only.
I tried with this configuration and MicLevel works. But I do get a strange thing when I stop the app from android studio. To do this I need to unplug and reattach the SensorTile usb socket. If not, the app starts but does not show me any data and the SensorTile LED blinks mildly with respect to the first operation
`public class StatusActivity extends AppCompatActivity {
/**
* create an intent for start the activity that will log the information from the node
*
* @param c context used for create the intent
* @param node note that will be used by the activity
* @return intent for start this activity
*/
public static Intent getStartIntent(Context c, @NonNull Node node) {
Intent i = new Intent(c, StatusActivity.class);
i.putExtra(NODE_TAG, node.getTag());
i.putExtras(NodeContainerFragment.prepareArguments(node));
return i;
}
private final static String NODE_TAG = StatusActivity.class.getCanonicalName() + "" +
".NODE_TAG";
private final static String NODE_FRAGMENT = StatusActivity.class.getCanonicalName() + "" +
".NODE_FRAGMENT";
/** fragment used for keep the connection open */
private NodeContainerFragment mNodeContainer;
/**
* nodo che mostrerà i dati
*/
private Node mNode;
// Feature on which to apply the listener
private FeatureActivity mActivity;
private FeatureMicLevel mMicLevel;
/**
* listener that will be used for enable the notification when the node is connected
*/
TextView mEventText;
TextView mLevelText;
byte levelMic;
public Feature.FeatureListener mMicListener = new Feature.FeatureListener() {
@Override
public void onUpdate(Feature f, Feature.Sample sample) {
if(f.getName().equals("Mic Level")){
levelMic = FeatureMicLevel.getMicLevel(sample,0);
StatusActivity.this.runOnUiThread(new Runnable() {
@Override
public void run() {
//if(levelMic > 0 && levelMic <= 128){
mLevelText.setText("MicLevel: "+levelMic);
//}
}
});
}
}
};
ImageView mStatusImage;
TextView mStatusText;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_status);
// find the node.
String nodeTag = getIntent().getStringExtra(NODE_TAG);
mNode = Manager.getSharedInstance().getNodeWithTag(nodeTag);
Node.State state = mNode.getState();
System.out.print("Stato: "+state);
//create/recover the NodeContainerFragment
if (savedInstanceState == null) {
Intent i = getIntent();
mNodeContainer = new NodeContainerFragment();
mNodeContainer.setArguments(i.getExtras());
getFragmentManager().beginTransaction()
.add(mNodeContainer, NODE_FRAGMENT).commit();
} else {
mNodeContainer = (NodeContainerFragment) getFragmentManager()
.findFragmentByTag(NODE_FRAGMENT);
}//if-else
//mActivity = mNode.getFeature(FeatureActivity.class);
mMicLevel = mNode.getFeature(FeatureMicLevel.class);
mStatusImage = (ImageView)findViewById(R.id.statusImage);
mStatusText = (TextView)findViewById(R.id.statusText);
mEventText = (TextView)findViewById(R.id.eventText);
mLevelText = (TextView)findViewById(R.id.mic_levelText);
}
@Override
public void onResume() {
super.onResume();
mMicLevel.addFeatureListener(mMicListener);
mNode.enableNotification(mMicLevel);
}
@Override
public void onPause() {
super.onPause();
mMicLevel.removeFeatureListener(mMicListener);
mNode.disableNotification(mMicLevel);
}
/**
* if we have to leave this activity, we force to keep the connection open, since we go back
* in the {@link FunctionsActivity}
*
*/
@Override
public void onBackPressed() {
mNodeContainer.keepConnectionOpen(true);
super.onBackPressed();
}//onBackPressed
} `
Since every time I make changes I have several issues that do not match the question I asked about github so for any problem I should open a new discussion, if it is good for you to communicate directly in some way?
However, by adding the activity along with the microphone, the app detects both events, even though it sometimes disconnects and stops working.
Don't worry open a new GitHub issue, its better have a public discussion to help also other people.
I'm reporting the problem with the Andrioid Studio to my colleges that develop the FW.
For your problem with the micLevel + activity try the example app and see if it happen also with that app.. I try and it works..
PS: your onResume method is still wrong..
Is it wrong to add listeners and enable notifications onResume? In another version of my app I created an activity for each feature and onResume I did this and everything works.
I've always worked on the BlueSTExample module.
At the moment I'm working with both features (MicLevel + Activity) and work together. Problems remain the same: some disconnection during operation and when I stop the app from android studio I have to unplug the usb socket to reboot the app. This is the code:
`public class StatusActivity extends AppCompatActivity {
/**
* create an intent for start the activity that will log the information from the node
*
* @param c context used for create the intent
* @param node note that will be used by the activity
* @return intent for start this activity
*/
public static Intent getStartIntent(Context c, @NonNull Node node) {
Intent i = new Intent(c, StatusActivity.class);
i.putExtra(NODE_TAG, node.getTag());
i.putExtras(NodeContainerFragment.prepareArguments(node));
return i;
}
private final static String NODE_TAG = StatusActivity.class.getCanonicalName() + "" +
".NODE_TAG";
private final static String NODE_FRAGMENT = StatusActivity.class.getCanonicalName() + "" +
".NODE_FRAGMENT";
/** fragment used for keep the connection open */
private NodeContainerFragment mNodeContainer;
/**
* nodo che mostrerà i dati
*/
private Node mNode;
// Feature on which to apply the listener
private FeatureActivity mActivity;
private FeatureMicLevel mMicLevel;
TextView mEventText;
TextView mLevelText;
//FeatureActivity.ActivityType event;
public final Feature.FeatureListener mActListener = new Feature.FeatureListener() {
@Override
public void onUpdate(Feature f, Feature.Sample sample) {
if(f.getName().equals("Activity Recognition")){
final FeatureActivity.ActivityType event = FeatureActivity.getActivityStatus(sample);
StatusActivity.this.runOnUiThread(new Runnable() {
@Override
public void run() {
mEventText.setText("Event: "+event);
if ((event.equals(FeatureActivity.ActivityType.STATIONARY)||event.equals(FeatureActivity.ActivityType.WALKING))&& levelMic < 30) {
mStatusImage.setImageResource(R.drawable.cane_zen);
mStatusText.setText("Calm");
mStatusText.setBackgroundColor(Color.GREEN);
}
else if (event.equals(FeatureActivity.ActivityType.FASTWALKING)&& levelMic > 50){
mStatusImage.setImageResource(R.drawable.cane_nervoso);
mStatusText.setText("Nervous");
mStatusText.setBackgroundColor(Color.RED);
}
else if(event.equals(FeatureActivity.ActivityType.JOGGING)){
mStatusImage.setImageResource(R.drawable.cane_giocoso);
mStatusText.setText("Playful");
mStatusText.setBackgroundColor(Color.YELLOW);
}
}
});
}
}
};
byte levelMic;
public Feature.FeatureListener mMicListener = new Feature.FeatureListener() {
@Override
public void onUpdate(Feature f, Feature.Sample sample) {
if(f.getName().equals("Mic Level")){
levelMic = FeatureMicLevel.getMicLevel(sample,0);
StatusActivity.this.runOnUiThread(new Runnable() {
@Override
public void run() {
//if(levelMic > 0 && levelMic <= 128){
mLevelText.setText("MicLevel: "+levelMic);
//}
}
});
}
}
};
ImageView mStatusImage;
TextView mStatusText;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_status);
// find the node.
String nodeTag = getIntent().getStringExtra(NODE_TAG);
mNode = Manager.getSharedInstance().getNodeWithTag(nodeTag);
Node.State state = mNode.getState();
System.out.print("Stato: "+state);
//create/recover the NodeContainerFragment
if (savedInstanceState == null) {
Intent i = getIntent();
mNodeContainer = new NodeContainerFragment();
mNodeContainer.setArguments(i.getExtras());
getFragmentManager().beginTransaction()
.add(mNodeContainer, NODE_FRAGMENT).commit();
} else {
mNodeContainer = (NodeContainerFragment) getFragmentManager()
.findFragmentByTag(NODE_FRAGMENT);
}//if-else
mActivity = mNode.getFeature(FeatureActivity.class);
mMicLevel = mNode.getFeature(FeatureMicLevel.class);
mStatusImage = (ImageView)findViewById(R.id.statusImage);
mStatusText = (TextView)findViewById(R.id.statusText);
mEventText = (TextView)findViewById(R.id.eventText);
mLevelText = (TextView)findViewById(R.id.mic_levelText);
}
@Override
public void onResume() {
super.onResume();
//mNode.addNodeStateListener(mNodeStatusListener);
mActivity.addFeatureListener(mActListener);
mNode.enableNotification(mActivity);
mNode.readFeature(mActivity);
mMicLevel.addFeatureListener(mMicListener);
mNode.enableNotification(mMicLevel);
}
@Override
public void onPause() {
super.onPause();
//mNode.removeNodeStateListener(mNodeStatusListener);
mActivity.removeFeatureListener(mActListener);
mNode.disableNotification(mActivity);
mMicLevel.removeFeatureListener(mMicListener);
mNode.disableNotification(mMicLevel);
}
/**
* if we have to leave this activity, we force to keep the connection open, since we go back
* in the {@link FunctionsActivity}
*
*/
@Override
public void onBackPressed() {
mNodeContainer.keepConnectionOpen(true);
super.onBackPressed();
}//onBackPressed
} `
Hello Giovanni,
I'm creating an app to monitor a dog's activities through motion, microphone level, and audio features. I have created a unique activity and a single layout where I manage the above features plus the battery.
The battery code is commented because I do not need it right now.
This is the code of the only activity that follows the activity of the node search (ScanActivity): `public class MainActivity extends AppCompatActivity {