I'm making a settings page, with a bunch of checkboxes. The user picks the options he wants, and then hits the submit button, which saves the results on a text file, like 1;0;1;1;1;0 etc, with the 1 representing checked and the 0 unchecked.
Upon the next program start, the program will look for the settings file. If it can't find it, the checkboxes are left at their default true vale (all on). If it can, it will read the file, and set the checkboxes accordingly. This last step is where I'm having the problem- using toasts, I can see that the program finds the file, splits it correctly, and has the correct value for the given checkbox. I even have a toast that fires in the if() block where I check if the value is a 0, the line after I use the setChecked() code. That toast fires, so the setChecked() code is being read. However, the checkbox does not get updated, and remains checked. My guess would be that the view isn't being refreshed after I change the boxes.
This is the first time I've made an android option that isn't entirely a service, and has a GUI, so I'm a bit unclear on it. What would be the simplest way to quickly get the screen to refresh after the boxes have been set, or is there some other problem?
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
//establish checkBoxes
checkBatteryLevel = (CheckBox) findViewById(R.id.checkBox1);
checkBatteryVoltage = (CheckBox) findViewById(R.id.checkBox2);
checkBluetooth = (CheckBox) findViewById(R.id.checkBox5);
checkCall = (CheckBox) findViewById(R.id.checkBox4);
checkCharger = (CheckBox) findViewById(R.id.checkBox3);
checkScreen = (CheckBox) findViewById(R.id.checkBox8);
checkWifiPermis = (CheckBox) findViewById(R.id.checkBox6);
checkWifiCnct = (CheckBox) findViewById(R.id.checkBox7);
submitButton = (Button) findViewById(R.id.button1);
Toast toast = Toast.makeText(getApplicationContext(), "Text here", Toast.LENGTH_LONG);
//check if text settings are there
textSettings = new File (root, "UsageMonitorSettings.txt");
if(textSettings.exists())
{
toast = Toast.makeText(getApplicationContext(), "File Exists", Toast.LENGTH_LONG);
toast.show();
//if present, read it and set buttons accordingly
try {
Scanner myScanner = new Scanner(textSettings);
while (myScanner.hasNextLine())
{
String line = myScanner.next();
toast = Toast.makeText(getApplicationContext(), line, Toast.LENGTH_LONG);
toast.show();
String[] lineArray = line.split(";");
toast = Toast.makeText(getApplicationContext(), lineArray[0], Toast.LENGTH_LONG);
toast.show();
if(lineArray[0].equals("0"))
{
checkBatteryLevel.setChecked(false);
toast = Toast.makeText(getApplicationContext(), "batt check changed", Toast.LENGTH_LONG);
toast.show();
}
if(lineArray[1].equals("0"))
{
checkBatteryVoltage.setChecked(false);
}
if(lineArray[2].equals("0"))
{
checkCharger.setChecked(false);
}
if(lineArray[3].equals("0"))
{
checkCall.setChecked(false);
}
if(lineArray[4].equals("0"))
{
checkBluetooth.setChecked(false);
}
if(lineArray[5].equals("0"))
{
checkWifiPermis.setChecked(false);
}
if(lineArray[6].equals("0"))
{
checkWifiCnct.setChecked(false);
}
if(lineArray[7].equals("0"))
{
checkScreen.setChecked(false);
}
}
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
else
{
toast = Toast.makeText(getApplicationContext(), "File does not exist", Toast.LENGTH_LONG);
toast.show();
//if not, make one with all defaulting to on
try {
BufferedWriter myFileWriter = new BufferedWriter(new FileWriter(textSettings));
myFileWriter.write("1;1;1;1;1;1;1;1");
myFileWriter.flush();
myFileWriter.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
submitButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
//when button hit update text settings with checked values
try {
BufferedWriter myFileWriter = new BufferedWriter(new FileWriter(textSettings, true));
if(checkBatteryLevel.isChecked())
{
myFileWriter.write("1"+";");
}
else
{
myFileWriter.write("0"+";");
}
if(checkBatteryVoltage.isChecked())
{
myFileWriter.write("1"+";");
}
else
{
myFileWriter.write("0"+";");
}
if(checkCharger.isChecked())
{
myFileWriter.write("1"+";");
}
else
{
myFileWriter.write("0"+";");
}
if(checkCall.isChecked())
{
myFileWriter.write("1"+";");
}
else
{
myFileWriter.write("0"+";");
}
if(checkBluetooth.isChecked())
{
myFileWriter.write("1"+";");
}
else
{
myFileWriter.write("0"+";");
}
if(checkWifiPermis.isChecked())
{
myFileWriter.write("1"+";");
}
else
{
myFileWriter.write("0"+";");
}
if(checkWifiCnct.isChecked())
{
myFileWriter.write("1"+";");
}
else
{
myFileWriter.write("0"+";");
}
if(checkScreen.isChecked())
{
myFileWriter.write("1");
}
else
{
myFileWriter.write("0");
}
myFileWriter.flush();
myFileWriter.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
}
And here are the relevant parts of main.xml:
<CheckBox
android:id="#+id/checkBox1"
android:layout_width="138dp"
android:layout_height="wrap_content"
android:text="Battery Level"
android:checked="true" />
<CheckBox
android:id="#+id/checkBox2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Battery Voltage"
android:checked="true" />
<CheckBox
android:id="#+id/checkBox5"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Bluetooth State"
android:checked="true" />
<CheckBox
android:id="#+id/checkBox4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Call State"
android:checked="true" />
<CheckBox
android:id="#+id/checkBox3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Charger State"
android:checked="true" />
<CheckBox
android:id="#+id/checkBox8"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Screen State"
android:checked="true" />
<CheckBox
android:id="#+id/checkBox6"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Wifi Permission"
android:checked="true" />
<CheckBox
android:id="#+id/checkBox7"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Wifi Connection"
android:checked="true" />
<Button
android:id="#+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Start Service" />
The problem is probably that,
with onCreate, you first read the settings if they exist, then you make the onClickListeners.
what do you do in the method onResume? Do you do anything there?!!
This means that you should look a bit more into the Android Activity Lifecycle.
Also, your settings file is not a good implementation of preferences. Unless you want 1 application to read another Android application's settings, you should look into SharedPreferences for storing application-wide settings - it's real easy to use.
If you want a simple UI, and want to finish quickly, there is a special activity designed especially for settings UI: PreferenceActivity - although later on you may find it lacks some functions.
Related
I have a button(button) and a textview(text) in my application. Before clicking on the button the textview text will always be "Start Search".But After clicking on the button , a function(scanning()) will be called. For executing the function it takes some times. So I want the texview text to be "Please wait" between the time after clicking the button and before getting the result of the function. And after getting the result of the function the textview text will be change to "Found" or "Not Found".
But problem is ,it never shows "please wait". After clicking on the button it shows "Start search" until getting the result of the function.
How to show "please wait" on the textview until it gets the result from the function after clicking on the button ??
Button button = (Button) findViewById(R.id.search);
TextView text = (TextView) findViewById(R.id.searchR);
text.setText("Start Search");
button.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
text.setText("Please Wait");
boolean res=scanning();
if(res==true)
text.setText("Found");
else text.setText("Not Found");
}
});
XML Part:
<Button
android:id="#+id/search"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="60dp"
android:layout_marginLeft="60dp"
android:layout_marginTop="30dp"
android:text="Search"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="#+id/searchR"
android:layout_width="0dp"
android:layout_height="34dp"
android:layout_marginStart="97dp"
android:layout_marginLeft="97dp"
android:layout_marginTop="30dp"
android:layout_marginEnd="16dp"
android:layout_marginRight="16dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="#+id/search"
app:layout_constraintTop_toTopOf="parent" />
In the scanning part, I did some searching for BLE devices using UUID. If that device is found then I returned true otherwise false;
Introduce a small delay after you change the text to "Please Wait" and before calling scanning().
button.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
text.setText("Please Wait");
Handler delayHandler = new Handler();
delayHandler.postDelayed(new Runnable() {
#Override
public void run() {
boolean res=scanning();
if(res) {
text.setText("Found");
}
else{
text.setText("Not Found");
}
}
},100);
}
});
Edit: Depending on your code, you may need to declare your variables as static or maybe global for this to work.
I found some mistakes in your code.
You are changing text of Button instead of TextView.
public void onClick(View v) {
text.setText("Please Wait");
boolean res=scanning();
if(res==true)
but1.setText("Found");
else but1.setText("Not Found");
}
Here
but1.setText
should be replaced with
text.setText
Your scanning method is returning result very fast, that's why you will not get Please Wait text.
Write external method for change text,
for example:
public void onClick(View v)
{
changeText("Please Wait");
boolean res = scanning();
if (res) // (res == true) is unnecessary, you can use like this
changeText("Found");
else changeText("Not Found");
}
private void changeText(string s)
{
text.setText(s);
}
I am trying to check whether the user has enter his/her mobile number in the EditText on the button click event, but I am not able to check whether the EditText is empty or not when control comes to "editRegMobile". When I click on the button it doesn't show the message in the Toast. I also want to check the format of the mobile number i.e "+91 999999999" country code. I am able to check for other EditText but not for Mobile EditText.
xml code:
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="phone"
android:ems="10"
android:id="#+id/editRegMobile"
android:layout_gravity="center_horizontal"
android:background="#drawable/sign_in_up_textbox"
android:layout_marginLeft="15dp"
android:layout_marginRight="15dp"
android:layout_marginBottom="35dp"
android:textSize="16sp"
android:letterSpacing="0.08"
android:singleLine="true" />
Java code:
btnSignUp.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (editRegName != null && TextUtils.isEmpty(editRegName.getText().toString().trim())) {
editRegName.setError("Required!");
editRegName.requestFocus();
} else if (editRegEmail != null && TextUtils.isEmpty(editRegEmail.getText().toString())) {
editRegEmail.setError("Required!");
editRegEmail.requestFocus();
} else if (!(editRegEmail != null && TextUtils.isEmpty(editRegEmail.getText().toString()))) {
if (!Patterns.EMAIL_ADDRESS.matcher(editRegEmail.getText().toString()).matches()) {
editRegEmail.setError("Invalid Format!");
editRegEmail.requestFocus();
}
} else if ((editRegMobile != null) && TextUtils.isEmpty(editRegMobile.getText().toString())) {
Toast.makeText(getApplicationContext(), "Please enter mobile number!", Toast.LENGTH_SHORT).show();
} else if (!(editRegMobile != null && TextUtils.isEmpty(editRegMobile.getText().toString()))) {
if (!Patterns.PHONE.matcher(editRegMobile.getText().toString()).matches()) {
Toast.makeText(getApplicationContext(), "Please enter valid mobile number!", Toast.LENGTH_SHORT).show();
}
}
}
});
You can make
if(editRegMobile.getText().length() == 0)
Or
editRegMobile.getText().toString().length()
The second way cost some performance because need convert to String first
Simple to check for empty :
edittext.getText().toString().length() == 0
I am writing code for an inbox-like activity which has a button that leads to the messages. This button has a text field that counts how many messages are in the inbox.
My problem is that the button's text field is not changing when the number of messages changes. It is not a problem of the app not checking for updates, and the code with setText is being called with the correct number to update.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Log.v("onCreate", "Main");
// Checking if there is login
if (ParseUser.getCurrentUser() == null) {
navigateToLogin();
} else {
// Setting pointers for buttons.
// onClick methods follow.
askButton = (Button) findViewById(R.id.buttonAsk);
ansButton = (Button) findViewById(R.id.buttonAnswer);
inboxButton = (Button) findViewById(R.id.buttonCenter);
mUser = ParseUser.getCurrentUser();
updateInbox();
}
This is the method that checks for new messages and updates the button.
private void updateInbox() {
Log.v(TAG, "Updating inbox");
ParseQuery responses = new ParseQuery(ParseConstants.CLASS_ANSWER);
responses.whereMatches(ParseConstants.KEY_SENDER_ID, mUser.getObjectId());
try {
responsesCount = responses.count();
Log.v("responses count" ,""+responsesCount);
if (responsesCount > 0) {
inboxButton.setText(String.valueOf(responsesCount));
}
Log.v("InboxActivity","Label set to " + responsesCount);
} catch (ParseException e) {
Log.v("InboxActivity", e.getMessage());
}
}
updateInbox gets called correctly and in the correct moments, so I only added its code to make this as clean as possible. Here is the xml:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#0099cc"
tools:context=".MainActivity"
android:clickable="false"
>
<Button
android:layout_width="80sp"
android:layout_height="80sp"
android:id="#+id/buttonCenter"
android:layout_gravity="center"
android:layout_centerInParent="true"
android:textSize="30sp"
android:text=""
android:textColor="#color/black_overlay"
android:background="#drawable/greenbutton"/>
EDIT:
Hi all, thanks for the help. I figured out the problem and posted it as an answer. It was a logical error, nothing to do with Android.
try this:
inboxButton.post(new Runnable(){
#Override
public void run(){
inboxButton.setText(String.valueOf(responsesCount));
}
});
(responsesCount should be final)
Try below code
import android.widget.RemoteViews;
if (responsesCount > 0) {
RemoteViews remoteViews = new RemoteViews(getPackageName(), R.layout.my_layout); //where my_layout is the layout file where the button resides.
remoteViews.setTextViewText(R.id.button, "Set button text here");// where button is id of the button.
}
findViewById doesn't exist for a widget.
Below code will work for you
runOnUiThread(new Runnable() {
#Override
public void run() {
if (responsesCount > 0) {
inboxButton.setText(String.valueOf(responsesCount));
}
}
});
You may use AsyncTask for smoothness of app flow.
I realized that the text was only getting updated when the number of responses was > 0. The button was updating correctly otherwise so I had to put an else statement to make sure the button always got updated. I edited the question with the correct answer in comments.
responsesCount = responses.count();
Log.v("responses count" ,""+responsesCount);
if (responsesCount > 0) {
inboxButton.setText(String.valueOf(responsesCount));
///////////////////////////////////
// MY EDIT HERE
//} else{
// inboxButton.setText("");
///////////////////////////////////
Quite new to coding for android but this issue has me tearing my hair out because it seems to make no sense at all...
I have an activity with four form elements in the layout: a CheckBox, two EditTexts and a Button.
When the user presses the button, it saves the content of the EditTexts as two preference values.
When the user presses the checkbox, it does the following:
If the checkbox is checked, load the preferences and store them into two variables.
Check if either of those variables contain empty strings after trimming them.
If so, show an error message, otherwise show a success message.
Essentially, the two text fields are used to set a pair of preferences which must not be empty when the checkbox is clicked.
It seems to work fine if I click the checkbox before pressing the button - error message or success message shown as appropriate.
If I press the save button and then click the checkbox, it always shows the success message regardless of the preferences.
Code follows (trimmed from the program as a whole)...
layout.xml
<CheckBox android:id="#+id/cboxActive" android:text="Click me!" android:onClick="toggleActive" android:layout_width="wrap_content" android:layout_height="wrap_content" />
<EditText android:id="#+id/editFrom" android:layout_width="fill_parent" android:layout_height="wrap_content" android:inputType="phone"><requestFocus /></EditText>
<EditText android:id="#+id/editTo" android:layout_width="fill_parent" android:layout_height="wrap_content" android:inputType="phone"></EditText>
<Button android:id="#+id/btnSave" android:onClick="savePrefs" android:text="Save" android:layout_width="120dp" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" />
</LinearLayout>
main class:
public class AutoMessengerActivity extends Activity
{
SharedPreferences settings;
CheckBox cboxActive;
EditText editFrom, editTo;
boolean active;
String from, to;
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
editFrom = (EditText) findViewById(R.id.editFrom);
editTo = (EditText) findViewById(R.id.editTo);
showPrefsInUI();
}
private void loadPrefs()
{
//Load preferences
settings = getPreferences(MODE_PRIVATE);
from = settings.getString("from", "");
to = settings.getString("to", "");
}
private void showPrefsInUI()
{
loadPrefs();
//Set UI elements to preference values
editFrom.setText(from);
editTo.setText(to);
}
public void savePrefs(View view)
{
SharedPreferences.Editor editor = settings.edit();
editor.putString("from", editFrom.getText().toString());
editor.putString("to", editTo.getText().toString());
editor.commit();
Toast.makeText(this, "Prefs saved!", Toast.LENGTH_SHORT).show();
}
public void toggleActive(View view)
{
if (cboxActive.isChecked())
{
loadPrefs();
//This toast is for debugging
//It shows the correct data in all circumstances...
Toast.makeText(this, "F: " + from + " T: " + to, Toast.LENGTH_SHORT).show();
//This is the part that seems to fail if you save then click checkbox
if (from.trim() == "" || to.trim() == "")
{
Toast.makeText(this, "Error - Prefs not saved", Toast.LENGTH_LONG).show();
cboxActive.setChecked(false);
}
else
{
Toast.makeText(this, "Success!", Toast.LENGTH_SHORT).show();
}
}
else
{
Toast.makeText(this, "Unchecked!", Toast.LENGTH_SHORT).show();
}
}
}
Hopefully that code gives an idea of the problem and allows it to be replicated...
Oh god, how silly of me - Urban and jcxavier hit the nail on the head... I forgot about that damn annoying quirk of Java! Changed the line to
from.trim().equals("") || to.trim().equals("")
And it works fine!
For what it's worth, that HAD actually crossed my mind briefly, but it was 2am when I tried equals and I got confused about requiring an Object as the parameter and ended up specifying null rather than "" - which didn't work...
I working on a chat app.
Whenever I submit or receive a text message, I append them to the chatbox.
When the list get longer, I need to scroll down to see them.
How can I make it to autoscroll to the newly append text?
<ScrollView
android:id="#+id/scrollView01"
android:layout_width="fill_parent"
android:layout_height="100px" >
<TextView
android:id="#+id/txtChat"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text=""
/>
</ScrollView>
//
SendMsg.setOnClickListener(new View.OnClickListener()
{
public void onClick(View v)
{
String name = txtName.getText().toString();
String message = txtMessage.getText().toString();
if (message.length() > 0) {
sendMsg(name, message);
String myMessage = message + "\n";
tvChat.append(myMessage);
}
else
Toast.makeText(getBaseContext(),
"Please enter both name and message.", Toast.LENGTH_SHORT).show();
}
});
I had the same issue, this is what I'm using:
//delay must be expressed in milliseconds. For 3 seconds, delay = 3000
private void scrollToBottom(int delay) {
// If we don't call fullScroll inside a Runnable, it doesn't scroll to
// the bottom but to the (bottom - 1)
mChatBox.postDelayed(new Runnable() {
public void run() {
mChatBox.fullScroll(ScrollView.FOCUS_DOWN);
}
}, delay);
}
where mChatBox is:
ScrollView mChatBox;