I have an activity where a user sends messages to another user, I created an onKey listener to send messages when a user pressed enter as well.
When a user actually clicks the send button, everything works perfectly, when a user presses the enter button a blank message is sent.
Here is the onkeylistener code
Code:
messageText.setOnKeyListener(new OnKeyListener() {
#Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
if (keyCode == 66) {
sendMessageButton.performClick();
return true;
}
return false;
}
});
and this is the sendmessagebutton
Code:
sendMessageButton.setOnClickListener(new OnClickListener() {
CharSequence message;
Handler handler = new Handler();
#Override
public void onClick(View arg0) {
// android.text.format.DateFormat df = new
// android.text.format.DateFormat();
message = messageText.getText();
String messageSent = DateFormat.format("dd MMM yy, kk:mm",
new java.util.Date()).toString();// java.text.DateFormat.getDateTimeInstance().format("yyyy-MM-dd kk:mm:ss");
if (message.length() > 0) {
appendToMessageHistory(imService.getUsername(),
message.toString(), messageSent);
((ScrollView) findViewById(R.id.scrollView))
.fullScroll(View.FOCUS_DOWN);
localstoragehandler.insert(imService.getUsername(),
friend.userName, message.toString(), messageSent);
messageText.setText("");
Thread thread = new Thread() {
#Override
public void run() {
try {
if (imService.sendMessage(
imService.getUsername(),
friend.userName, message.toString()) == null) {
handler.post(new Runnable() {
#Override
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();
}
}
});
When user clicks button
message = messageText.getText();// get message
Then you do
messageText.setText("");
So when user presses the enter button in onKey you have sendMessageButton.performClick() a blank message is sent since you already set messageText.setText("")
Related
I have a 2 Insole (left and right insole), then 2 data generated from the left and right insole will be sent to firebase every 1 second. To send data per second I use 2 timers namely left_timer.scheduleAtFixedRate and right_timer.scheduleAtFixedRate but the data generated from these 2 insoles is still out of sync. because the resulting data is messy. the reason the resulting data is messy is that if we walk only one foot will step on the insole. but with this code, two feet will be on the ground when we walk. I suspect this delay is due to the process of sending data. is there any solution for this problem
Here My code:
connectLeftBtn:
connectLeftBtn.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton compoundButton, boolean isChecked) {
if(isChecked)
{
connectDevice(L_insole_mac);
}
else
{
if (is_L_insole_connected)
if(is_L_insole_started)
left_insole_device_interface.stopInsole();
startLeftBtn.setText("Start Left");
is_L_insole_started = false;
bluetoothManager.closeDevice(left_insole_device_interface);
is_L_insole_connected = false;
Toast.makeText(Visualization.this, "Left Insole Disconnected.", Toast.LENGTH_SHORT).show();
}
}
private void connectDevice(String mac) {
bluetoothManager.openSerialDevice(mac)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(this::onConnected, this::onError);
}
#RequiresApi(api = Build.VERSION_CODES.N)
private void onConnected(BluetoothSerialDevice connectedDevice) {
// You are now connected to this device!
// Here you may want to retain an instance to your device:
left_insole_device_interface = connectedDevice.toSimpleDeviceInterface();
// Listen to bluetooth events
left_insole_device_interface.setListeners(message -> onMessageReceived(message), this::onMessageSent, this::onError);
left_insole_device_interface.stopInsole();
is_L_insole_connected = true;
Toast.makeText(getApplication(), "Connected to Left Insole.", Toast.LENGTH_SHORT).show();
}
#RequiresApi(api = Build.VERSION_CODES.N)
private void onMessageReceived(String message) {
//store incoming bytes temporarily
if(!is_L_insole_started){
left_temp_bytes+=message+" ";
}
//check whether the start_bytes exits in the temporary buffer
if(!is_L_insole_started && left_temp_bytes.contains(start_bytes)){
is_L_insole_started = true;
left_temp_bytes ="";
}
//if the start_bytes are found in the temporary buffer, start storing the incoming messages in the actual buffer
if(is_L_insole_started){
left_data_len++;
if(left_data_len>15) {
left_sensor_data_count++;
if (!non_sensor_indeces.contains(left_sensor_data_count)) {
l_data_double_arr[left_data_index] = Double.parseDouble(message);
// System.out.println("NON SENSOR INDEX:" + left_data_index + " "+ message);
left_data_index++;
}
}
Date date = new Date();
leftDataDict.put(String.valueOf(formatter.format(date)), Arrays.toString(l_data_double_arr));
//if the data length reach the max_data_length, release the buffer and invert the start flag
if(left_data_len>=max_data_len+15){
heatMapLeft.clearData();
for(int i=0; i<x_L.length; i++) {
HeatMap.DataPoint point = new HeatMap.DataPoint(x_L[i], y[i], l_data_double_arr[i]);
heatMapLeft.addData(point);
heatMapLeft.forceRefresh();
}
left_package_count++;
left_data_index= 0;
left_sensor_data_count = 0;
left_data_len=0;
is_L_insole_started=false;
}
}
}
private void onMessageSent(String message) {
// We sent a message! Handle it here.
// Toast.makeText(getApplication(), "Sent a message! Message was: " + message, Toast.LENGTH_LONG).show(); // Replace context with your context instance.
}
private void onError(Throwable error) {
// Handle the error
}
});
connectRightBtn:
connectRightBtn.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton compoundButton, boolean isChecked) {
if (isChecked) {
connectDevice(R_insole_mac);
} else {
if (is_R_insole_connected) {
if (is_R_insole_started) {
right_insole_device_interface.stopInsole();
startRightBtn.setText("Start Right");
is_R_insole_started = false;
}
bluetoothManager.closeDevice(right_insole_device_interface);
is_R_insole_connected = false;
Toast.makeText(Visualization.this, "Right Insole Disconnected.", Toast.LENGTH_SHORT).show();
}
}
}
private void connectDevice (String mac){
bluetoothManager.openSerialDevice(mac)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(this::onConnected, this::onError);
}
#RequiresApi(api = Build.VERSION_CODES.O)
private void onConnected (BluetoothSerialDevice connectedDevice){
// You are now connected to this device!
// Here you may want to retain an instance to your device:
right_insole_device_interface = connectedDevice.toSimpleDeviceInterface();
// Listen to bluetooth events
right_insole_device_interface.setListeners(message -> onMessageReceived(message), this::onMessageSent, this::onError);
right_insole_device_interface.stopInsole();
is_R_insole_connected = true;
Toast.makeText(getApplication(), "Connected to Right Insole.", Toast.LENGTH_SHORT).show();
}
private void onMessageSent (String message){
// We sent a message! Handle it here.
}
#RequiresApi(api = Build.VERSION_CODES.N)
private void onMessageReceived (String message){
//store incoming bytes temporarily
if(!is_R_insole_started){
right_temp_bytes+=message+" ";
}
//check whether the start_bytes exits in the temporary buffer
if(!is_R_insole_started && right_temp_bytes.contains(start_bytes)){
is_R_insole_started = true;
right_temp_bytes ="";
}
//if the start_bytes are found in the temporary buffer, start storing the incoming messages in the actual buffer
if(is_R_insole_started){
right_data_len++;
if(right_data_len>15) {
right_sensor_data_count++;
if (!non_sensor_indeces.contains(right_sensor_data_count)) {
r_data_double_arr[right_data_index] = Double.parseDouble(message);
// System.out.println("NON SENSOR INDEX:" + right_data_index + " "+ message);
right_data_index++;
}
}
Date date = new Date();
rightDataDict.put(String.valueOf(formatter.format(date)),Arrays.toString(r_data_double_arr));
// if the data length reach the max_data_length, release the buffer and invert the start flag
if(right_data_len>=max_data_len+15){
heatMapRight.clearData();
for(int i=0; i<x_R.length; i++) {
HeatMap.DataPoint point = new HeatMap.DataPoint(x_R[i], y[i], r_data_double_arr[i]);
heatMapRight.addData(point);
heatMapRight.forceRefresh();
}
right_data_index= 0;
right_sensor_data_count = 0;
right_data_len=0;
is_R_insole_started=false;
}
}
}
private void onError(Throwable error) {
// Handle the error
}
});
startLeftBtn:
startLeftBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if (is_L_insole_connected) {
if (is_L_insole_started) {
left_insole_device_interface.stopInsole();
is_L_insole_started = false;
startLeftBtn.setText("Start Left");
left_timer.cancel();
} else {
left_insole_device_interface.startInsole();
is_L_insole_started = true;
startLeftBtn.setText("Stop Left");
left_timer.scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
runOnUiThread(new Runnable() {
#RequiresApi(api = Build.VERSION_CODES.N)
public void run() {
// Log.d("TAG", "Hashmap: "+ leftDataDict);
sendToFirebase(leftDataDict, "Left_Insole");
}
});
}
},1000, 1000);
Toast.makeText(Visualization.this, "Left Insole Started.", Toast.LENGTH_SHORT).show();
}
}else
{
Toast.makeText(Visualization.this, "Left Insole Not Connected!", Toast.LENGTH_SHORT).show();
}
}
});
startRightBtn:
startRightBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if(is_R_insole_connected) {
if (is_R_insole_started) {
right_insole_device_interface.stopInsole();
is_R_insole_started = false;
startRightBtn.setText("Start Right");
right_timer.cancel();
} else {
right_insole_device_interface.startInsole();
is_R_insole_started = true;
startRightBtn.setText("Stop Right");
right_timer.scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
runOnUiThread(new Runnable() {
public void run() {
sendToFirebase(rightDataDict, "Right_Insole");
}
});
}
},1000, 1000);
Toast.makeText(Visualization.this, "Right Insole Started.", Toast.LENGTH_SHORT).show();
}
}else{
Toast.makeText(Visualization.this, "Right Insole Not Connected!", Toast.LENGTH_SHORT).show();
}
}
});
SendToFirebase:
public void sendToFirebase(Map<String,Object> data, String of_insole){
Date date = new Date();
db.collection("Experiments").document(PATIENT_NAME).set(patientRecord);
db.collection("Experiments")
.document(PATIENT_NAME)
.collection(of_insole)
.document(String.valueOf(formatter2.format(date)))
.set(data)
.addOnSuccessListener(new OnSuccessListener<Void>() {
#Override
public void onSuccess(Void unused) {
data.clear();
Toast.makeText(Visualization.this, "Succesfully saved to Firebase", Toast.LENGTH_SHORT).show();
}
})
.addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
Toast.makeText(Visualization.this, "Failed to saved to Firebase", Toast.LENGTH_SHORT).show();
}
});
}
I'm having some problems trying to set togglebutton (LeftLightButton) state and text after receiving value 1 at novo.charAt(0) for example. The main idea is, i click the button, it makes webview.loadUrl, and if the page changes to what i expected the toggle button state should be on, if not, it must stay off and vice versa. The way it is now, doesnt change the text neither state in case the site didnt update to the value that i was expecting.
public class MainActivity extends Activity {
private WebView webView;
private ToggleButton LeftLightButton;
private Thread webviewthread;
private String baseURL;
private boolean LeftLightButtonState;
public void onCreate(Bundle savedInstanceState) {
final Context context = this;
baseURL = "http://192.168.1.4/i.php";
LeftLightButton = (ToggleButton) findViewById(R.id.toggleButton1);
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
runOnUiThread(new Runnable() {
public void run()
{
synchronized(this) {
webView = (WebView) findViewById(R.id.webView1);
webView.getSettings().setJavaScriptEnabled(true);
webView.addJavascriptInterface(context, "HTMLOUT");
webView.setWebViewClient(new WebViewClient() {
#Override
public void onPageFinished(WebView view, String url) {
webView.loadUrl("javascript:window.HTMLOUT.processHTML('<head>'+document.getElementsByTagName('html')[0].innerHTML+'</head>');");
}
});
webView.loadUrl(baseURL);
}
}
});
showToast("Getting current status...");
}
public void notify(final boolean state, final ToggleButton buttonName) {
Thread thread = new Thread() {
#Override
public void run() {
synchronized (this) {
try {
wait(1000);
final ToggleButton button = (ToggleButton) findViewById(R.id.toggleButton1);
if (!state && button.isChecked()) {
showToast("Couldnt turn OFF");
// UI
runOnUiThread(new Runnable() {
#Override
public void run() {
button.setChecked(false);
button.setTextOff("OFF");
}
});
// end of UI
}
if (state && !button.isChecked()) {
showToast("Couldnt turn ON");
// UI
runOnUiThread(new Runnable() {
#Override
public void run() {
button.setChecked(true);
button.setTextOn("ON");
}
});
// end of UI
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
};
thread.start();
}
public void showToast(final String toast)
{
runOnUiThread(new Runnable() {
public void run()
{
Toast.makeText(MainActivity.this, toast, Toast.LENGTH_SHORT).show();
}
});
}
public void onClick(View arg0) {
final int id = arg0.getId();
switch (id) {
case R.id.toggleButton1:
if (LeftLightButtonState == true) {
webView.loadUrl(baseURL+"?L=0");
notify(false, LeftLightButton);
} else {
webView.loadUrl(baseURL+"?L=1");
notify(true, LeftLightButton);
}
break;
// even more buttons here
}
}
#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;
}
public void processHTML(String html) { // <html> <body> 1 0 0 0 </body> </html>
LeftLightButton = (ToggleButton) findViewById(R.id.toggleButton1);
String novo = android.text.Html.fromHtml(html).toString();
System.out.println("RECEIVED: "+novo);
if (novo != null) {
if (novo.charAt(0) == '0') {
LeftLightButtonState = false;
LeftLightButton.setTextOff("OFF");
LeftLightButton.setChecked(false);
}
if (novo.charAt(0) == '1') {
LeftLightButtonState = true;
LeftLightButton.setTextOn("ON");
LeftLightButton.setChecked(true);
}
System.out.println("CHEGUEI");
}
}
}
Use different string in the xml files itself. Then based on the state appropriate text will be displayed. You can call setChecked(true/false) to select or unselect the Toggle Button.. It is working fine in my project.
android:textOff="#string/dontshowtraffic"
android:textOn="#string/showtraffic"
I want to display an alert dialog depending upon the property and when the user clicks on the OK button, call the function again to get updated values within the running process.
I have the following code:
importingProgress = ProgressDialog.show(context, getString(R.string.progressNewsListTitle),
getString(R.string.progressProjectListMessage), true);
new Thread(new Runnable() {
public void run() {
try {
app.SetOtherTaskRunning(true);
Ib_clients client = db.Ib_clients_GetById(app.GetCustomerId());
try {
LogManager.WriteToFile("---------------- Getting News from Webservice :- " + DateFormat.getDateTimeInstance().format(new Date()) + "----------------");
CommonFuctions.CreateXml(context, h, client, db, app.GetBookMonth(), app.GetBookQuater(), app.GetBookYear(), Constants.News, app.GetWebServiceLastSyncDate(Constants.ServiceType.NEWS.toString()), Constants.ServiceType.NEWS, null, null, null, null, null);
Return reponse = null;
do {
reponse = CommonFuctions.SendingRequest(context, handler, db);
if (reponse.type.compareTo("warning") == 0) {
h.post(new Runnable() {
public void run() {
AlertDialog.Builder alert = new AlertDialog.Builder(context);
alert.setTitle(context.getString(R.string.information));
alert.setMessage("dsgdgd");
alert.setPositiveButton(context.getString(R.string.logoutDialogOk), new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
}
});
alert.show();
}
});
}
} while (reponse.type.compareTo("warning") == 0);
} catch (IOException e) {
e.printStackTrace();
}
} catch (Exception e) {
//Log.d(Constants.TAG, e.getMessage());
e.printStackTrace();
}
if (importingProgress != null) {
importingProgress.dismiss();
importingProgress = null;
}
}
}).start();
If response type is warning, then display a message to the user and if the user clicks the OK button , then call CommonFuctions.SendingRequest(context, handler, db) again to get updated values. Until we get a.response type of warning , we need to display an alert dialog to the user and call CommonFuctions.SendingRequest(context, handler, db) again.
Class to return:
public class Return {
public String type;
public String msg;
public boolean isSuccess;
public int client_id; // for getting clientid from server
public int booking_id; // for getting bookingid form server
}
You will have to use handler to display the AlertDialog because UI can be handled by the main thread only.
The other way is to use asyncTask for multiprocessing and then using the onPostExcecute() of asyncTask to display the AlertDialog
Please feel free to ask any further doubts.
Try to run your dialog as below in runonUIthread:
runOnUiThread(new Runnable() {
#Override
public void run() {
AlertDialog.Builder alert = new AlertDialog.Builder(context);
alert.setTitle(context.getString(R.string.information));
alert.setMessage("dsgdgd");
alert.setPositiveButton(context.getString(R.string.logoutDialogOk), new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
}
});
alert.show();
}
});
How can I configure the back button to be pressed twice before the app exits? I want to trigger
#Override
public void onBackPressed() {
//custom actions
//display toast "press again to quit app"
super.onBackPressed();
}
Try this:
private boolean doubleBackToExitPressedOnce = false;
#Override
protected void onResume() {
super.onResume();
// .... other stuff in my onResume ....
this.doubleBackToExitPressedOnce = false;
}
#Override
public void onBackPressed() {
if (doubleBackToExitPressedOnce) {
super.onBackPressed();
return;
}
this.doubleBackToExitPressedOnce = true;
Toast.makeText(this, "Press twice to exit", Toast.LENGTH_SHORT).show();
}
This snippet handle also the reset state when the activityis resumed
I see this question is a bit old but I though this might help some people looking for an alternative to the answers already given.
This is how I handle backing out of my applications. If someone has a better -- or a Google suggested -- method of accomplishing this I'd like to know.
Edit -- Forgot to mention this is for Android 2.0 and up. For previous versions override onKeyDown(int keyCode, KeyEvent event) and check for keyCode == KeyEvent.KEYCODE_BACK. Here is a good link to check out.
private boolean mIsBackEligible = false;
#Override
public void onBackPressed() {
if (mIsBackEligible) {
super.onBackPressed();
} else {
mIsBackEligible = true;
new Runnable() {
// Spin up new runnable to reset the mIsBackEnabled var after 3 seconds
#Override
public void run() {
CountDownTimer cdt = new CountDownTimer(3000, 3000) {
#Override
public void onTick(long millisUntilFinished) {
// I don't want to do anything onTick
}
#Override
public void onFinish() {
mIsBackEligible = false;
}
}.start();
}
}.run(); // End Runnable()
Toast.makeText(this.getApplicationContext(),
"Press back once more to exit", Toast.LENGTH_SHORT).show();
}
}
You could do what you're asking with a global integer and just count it, if > 2, quit.
But you could take a better (IMO) approach, where you question the user if they would like to quit or not:
private void questionQuit(){
final CharSequence[] items = {"Yes, quit now", "No, cancel and go back"};
builder = new AlertDialog.Builder(mContext);
builder.setCancelable(false);
builder.setTitle("Are you sure you want to quit?");
builder.setItems(items, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int item) {
switch(item){
case 0:
quit();
break;
case 1:
default:
break;
}
}
}).show();
AlertDialog alert = builder.create();
}
#Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (event.getAction() == KeyEvent.ACTION_DOWN) {
switch (keyCode) {
case KeyEvent.KEYCODE_BACK :
int i = 0 ;
if(i == 1 )
{
finish();
}
i++;
return true;
}
}
return super.onKeyDown(keyCode, event);
}
I have a video view that is full screen and would like to trigger a popupMenu when a certain key is pressed. The log shows that the key event is captured, but the popup view will not show. Any ideas why?
#Override
public boolean onKeyDown(int keyCode , KeyEvent event ){
switch(keyCode){
case KeyEvent.KEYCODE_DPAD_CENTER:
Log.i("POP uP MENU","Show");
mVideoView.pause();
showPopupMenu(new View(VideoPlayer.this));
case KeyEvent.KEYCODE_D:
popupMenu.dismiss();
}
return true;
}
private void showPopupMenu(View v){
popupMenu = new PopupMenu(VideoPlayer.this, v);
if(bitRates != null){
for(int i=0;i<bitRates.size();i++){
int menuItem = i;
popupMenu.getMenu().add(0,menuItem, 0,qualityList.get(i)+" : "+bitRates.get(i));
}
}
popupMenu.show();
popupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
public boolean onMenuItemClick(final MenuItem item) {
progressDialog = ProgressDialog.show(VideoPlayer.this, "", "Loading video...");
final int position = mVideoView.getCurrentPosition();
new Thread() {
public void run() {
try{
runOnUiThread(new Runnable() {
public void run() {
play(streamUrls.get(item.getItemId()),position);
}
});
}
catch (Exception e)
{
Log.e("tag", e.getMessage());
}
progressDialog.dismiss();
}
}.start();
return true;
}
});
}
It seems that
KeyEvent.KEYCODE_DPAD_CENTER
is an event that is set to be triggered by the VideoView by default. So when I pressed that key VideoView triggered its event event instead of the event I was requesting it to. I changed the KeyEvent KEYCODE to another key(One not used by Videoview) and it worked.