I am new at Android programming and firstly I would like to make a simple options menu demo with SharedPreferences. I have created the basic structure, but I have no idea how to attach OnPreferenceClickListener to the Preference. Nonetheless, I can use onSharedPreferenceChanged method, but there are no other event listeners. (Again, I am a beginner so I don't know why this is so.)
I have read a documentation about the steps of creating a menu: https://developer.android.com/guide/topics/ui/settings/customize-your-settings#java
I have also seen a question here: Preference Activity on Preference Click Listener
I have tried some of the solutions, but they didn't work at all. (I couldn't implement OnPreferenceClickListener, so that could be the main reason, but I don't know why)
As you can see I created a CheckBoxPreference and a Preference elem in a PreferenceCategory. (This is in /res/xml/settings_pref.xml)
<PreferenceCategory
android:key="category_basic"
android:title="Basic settings">
<CheckBoxPreference
android:defaultValue="true"
android:key="my_checkbox"
android:summaryOff="Off"
android:summaryOn="On"
android:title="#string/my_checkbox"
/>
<Preference
android:key="my_preference"
android:title="#string/my_preference"
/>
</PreferenceCategory>
This method checks the state of the CheckBoxPreference (checked / not checked)
(This is in /java/MainActivity.java)
#Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { // called when I change the state of the CheckBoxPreference
if (key.equals("my_checkbox")) {
// some interesting stuff
}
}
But my aim is to detect if the user clicked at a Preference and do something (for example open a dialog box)
onClickPreference.setOnPreferenceClickListener(preference -> {
// do something
return true;
});
When I tried out to create a click listener, I got this error message: Cannot resolve symbol 'onClickPreference'
Try this code hope it will help you
findPreference("my_preference").setOnPreferenceClickListener(preference -> {
// do something
return true;
});
I'm trying to make a soundboard, such that when you press a button with a particular android:id it will play an .ogg file of the same name. I have the layout setup, just need assistance with referencing the XML id.
For instance, if I have this particular button setup
<Button
android:id="#+id/file022"
android:layout_weight="1"
android:layout_margin="1dp"
android:layout_height="fill_parent"
android:layout_width="fill_parent"
android:text="Sample Text"
android:textColor="#000000"
android:textStyle="normal"
android:onClick="playSound"
android:background="#B3EDEDED"/>
I could use the following code to play back the corresponding sound to play file022.ogg
(v.getId()==R.id.button14){
MediaPlayer mpSound = MediaPlayer.create(this, R.raw.file022);
mpSound.start();
What do I need to change such that I can avoid hardcoding case statements for 'R.raw.file001', 'R.raw.file002', and instead dynamically reference the id as set in the XML?
You should do this using instead the tag attribute, as retrieving the field name for the ID would require reflection.
<Button
...
android:tag="file022"
... />
Then, in your code, you just retrieve the tag, and get the raw resource identifier for that name.
String tag = (String) v.getTag();
int resId = getResources().getIdentifier(tag, "raw", getPackageName());
MediaPlayer mpSound = MediaPlayer.create(this, resId);
mpSound.start();
For your button, you can give it a tag to identify the sound resource to play
<Button
android:id="#+id/file022"
... contents skipped for brevity
android:tag="file022" <--- add a tag which maps to your sound resource name
/>
Then assign a View.OnClickListener to the button in your Activity (or Fragment).
For the implementation of onClick(View), you can do something similar to this:
public void onClick(View v){
int soundResourceId = [yourContextObject].getResources().getIdentifier(v.getTag(), "raw", this.getPackageName());
// play the sound
MediaPlayer mpSound = MediaPlayer.create(this, soundResourceId );
// etc...
}
Note: this assumes that the tag is set and the OnClickListener is only assigned to buttons that play the sound. Also, i used a placeholder [yourContextObject], so you can use YourActivity.this or if its in a Fragment getContext() so you can access the app resources
This might be a little tedious to maintain if you change your resource names though since you would have to change the value of the android:tag attribute in your view.
Credit to this StackOverflow thread for the string to resource conversion: Android: Howto get a resource id of an android resource
Note: Resources.getResource(...) might be a bit slow, instead you can store the R file resource references in a static final array in your class and create a mapping between the array and your buttons by storing an index instead of the file name in the android:tag, and just use: int soundResourceId = yourResourceArray[Integer.parseInt(v.getTag())] to get the index for the array
EDIT: another alternative if you wanna stick with the tag == file name is to use something like this:
Android, getting resource ID from string?
Is there any possibility to group the R.id?
android:id="#+id/button1"
R.id.button1
I want something like this:
android:id="#+id/main/button1"
R.id.main.button1
But that does not work.
The only way I know to group like id's like that is to set all the tags the same. Then you get reference the id's with the same tag.
Button myButton = (Button)findViewById(R.id.button1);
Button mySecondButton = (Button)findViewById(R.id.button2);
myButton.setTag("Tag1");
mySecondButton.setTag("Tag1");
This way you can still programatically reference your group.
In the R.java file, the id itself is a group, and there is no way to superclass it with something else.
As a matter of fact you can. This isn't documented, and IntelliJ does not play along nicely (Eclipse does), but you can do something like this...
layout.xml
android:id="#+id_group1/button1"
Activity.java
Button myButton = (Button)findViewById(R.id_group1.button1);
My work computer that Eclipse is installed on does not have internet connectivity due to work related issues so all code and LogCat text has been hand typed instead of copy and pasted since I am on a separate laptop that Eclipse is installed right now. So bear with me for any typos.
Now to the issue. In the new version of my app, I am making it Spanish supported. I localized all my strings in strings.xml. Below is my Java code that I am not usuing to implement.
public class SplashScreen extends SwarmActivity {
Context c;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.splashscreen);
loading = (TextView)findViewById(R.id.loading);
//loading.setText(c.getResources().setString(R.string.loading)); //This way gives NPE
//loading.setText(R.string.loading); //This way works
//loading.setText("Test"); //This way works
}
}
If I understand localization correctly, I have to getResources() first so the app knows what language of the string to display. But the getResources() is what is messing me up.
What do I need to do to get the string displaying correctly?
To answer your problem, your forgot to initialize your Context object. So c is null. Replace
loading.setText(c.getResources().setString(R.string.loading));
by
loading.setText(getResources().setString(R.string.loading));
But actually there is no need to do that.
Android loads the appropriate resources according to the locale settings of the device at run time.
You just have to respect this hierarchy in your project :
res/
values/
strings.xml
values-es / (here for spanish values)
strings.xml
values-fr /
strings.xml (here for french values)
You have this code
Context c;
public void onCreate(Bundle savedInstanceState) {
...
loading.setText(c.getResources().setString(R.string.loading)); //This way gives NPE
The member c is never set before it is used. This is the reason for the NullPointerException. You must first initialize c with View.getContext() for example.
Localization is handled automatically according to the device's capabilities and settings.
In your layout definition, you can define the text string with a reference to a string id and Android will automatically load the appropriate resource
In res/layout/splashscreen.xml:
...
<TextView android:id="#+id/loading"
android:text="#string/loading"
.../>
...
So there is no need to explicitly set the text string in your code, because Android will do so already. The only thing you have to do, is to define the appropriate text strings in the res/values*/strings.xml files.
I have the following layout (virtually empty):
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/set_layout"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:contentDescription="content desc"
android:orientation="vertical" >
<TextView android:id="#+id/text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello, I am a TextView" />
</LinearLayout>
The Activity class contains the following:
public class TestActivity extends Activity {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_test);
}
}
When I run this on my mobile device I get the following error:
SpannableStringBuilder
SPAN_EXCLUSIVE_EXCLUSIVE spans cannot have a zero length
I have tried this with and without the TextView and the error still remains, I must be doing something fundamentally wrong for such a basic layout to cause this.
Does anyone have any ideas on how I can get this to load without the error?
I have run into the same error entries in LogCat. In my case it's caused by the 3rd party keyboard I am using. When I change it back to Android keyboard, the error entry does not show up any more.
Because the error you're getting is not related to an EditText, then it's not related to your keyboard.
The errors you are getting are not a result of your code; you probably are testing on a Samsung device that has Samsung's TouchWiz.
I had the same errors, then I tested on a Nexus S (also by Samsung, but pure Android OS without TouchWiz) and I didn't get this error.
So, in your case, just ignore these errors while testing on a device! :)
Looking at your code, I'm not sure why you're getting that error, but I had this same error but with EditText fields.
Changing android:inputType="text" (or any of the other inputType text variations) to android:inputType="textNoSuggestions" (or android:inputType="textEmailAddress|textNoSuggestions", for example) fixed it for me.
You can also set this in Code with something like
mInputField.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS);
Looks like Android assumes by default that EditText fields will have suggestions. When they don't, it errors. Not 100% confident in that explanation, but the above mentioned changes fixed it for me.
http://developer.android.com/reference/android/text/Spanned.html#SPAN_EXCLUSIVE_EXCLUSIVE
Hope this helps!
On your android phone go to:
settings -> application manager -> all -> samsung keyboard and then click on "clear cache"
(delete all data collected by this application).
Try using the default Android keyboard it will disappear
Make clear you have pass a value in your MainAcitivity for the following methods onCreateOptionsMenu and onCreate
In some cases, the developer deletes the "return super.onCreateOptionsMenu(menu)" statement and changed to "return true".
This worked for me...on every device
<EditText
android:maxLines="1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:textSize="15sp"
android:layout_centerVertical="true"
android:textColor="#000"
android:id="#+id/input_search"
android:background="#null"
android:inputType="text"
android:hint="Enter Address, City or Zip Code"
android:imeOptions="actionSearch"
/>
In Java code:
mSearchText.setOnEditorActionListener(new TextView.OnEditorActionListener() {
#Override
public boolean onEditorAction(TextView textView, int actionId, KeyEvent keyEvent) {
if(actionId == EditorInfo.IME_ACTION_SEARCH
|| actionId == EditorInfo.IME_ACTION_DONE
|| keyEvent.getAction() == KeyEvent.ACTION_DOWN
|| keyEvent.getAction() == KeyEvent.KEYCODE_ENTER){
//execute our method for searching
}
return false;
}
});
I had the same warning and found that removing an unused #id got rid of the warning. For me it was obvious as the #id was associated with a growing list of textViews linked to a database, so there was a warning for each entry.
Masood Moshref is right, this error occur because the option menu of Menu is not well prepared by lacking "return super.onCreateOptionsMenu(menu)" in onCreate() method.
To try to debug this error, first go to your android terminal / console and execute this command:
ps | grep THE_ERROR_PID_YOU_GET_(IT_IS_A_NUMBER)
then if the output comes out as your app... it is your app causing the error. Try to look for empty Strings that you pass into the layout.
I had this exact same problem and it was my fault as I was passing an empty String into my layout. After changing the "" to " " this error went away.
If you don't get your app from the console output, then it is something else causing it (probably, as others said, the android keyboard)
I have faced the same issue. I almost wasted almost couple of weeks to resolved this issue.
Finally I had on doubt on myself and tried to create another project by copy and paste some startup files like SplashScreen & LoginScreen.
But with the same code still i was getting SPAN_EXCLUSIVE_EXCLUSIVE.
Then i have removed the handler code from splash screen and tried again and Wow its working.
I am not getting SPAN_EXCLUSIVE_EXCLUSIVE issue in logcat.
I wondering, why it is? till the time did not get any other solution but by removing handler from splash screen it is working.
Try and update here if it is resolved or not.
Check if you have any element such as button or text view duplicated (copied twice) in the screen where this encounters. I did this unnoticed and had to face the same issue.
I ran into this problem too when I copied some text from the Internet. My solution is to trim the text/remove formatting before doing any further processing.
I had the same problem but with a listView.... i solved it because i was using a wrong R.id.listView that list View needed to have a value, in my case it was strings that i saved on listView2... so the right code was R.id.listView2
I had the same problem then i fixed it by following code!
text = (EditText)findViewById(R.id.TextVoiceeditText);
text.setInputType(InputType.TYPE_CLASS_TEXT|InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS);
this error also occurs due to changed API URL. try hitting the URL you are using in postman and c if it's working properly.
rechecking the APIs solved my problem
try avoiding use of view in xml design.I too had the same probem but when I removed the view. its worked perfectly.
like example:
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Username"
android:inputType="number"
android:textColor="#fff" />
<view
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="#f9d7db" />
also check and try changing by trial and error android:inputType="number" to android:inputType="text" or better not using it if not required .Sometimes keyboard stuck and gets error in some of the devices.
In my case, the EditText fields with inputType as text / textCapCharacters were casing this error. I noticed this in my logcat whenever I used backspace to completely remove the text typed in any of these fields.
The solution which worked for me was to change the inputType of those fields to textNoSuggestions as this was the most suited type and didn't give me any unwanted errors anymore.
in my case i click on recent apps shortcut on my cell phone and close all apps. This solution always work for me, because this error not related to code.
**DONT PUT SET TEXT IN TEXT WATCHER**etSearch.addTextChangedListener(object : TextWatcher {
override fun afterTextChanged(s: Editable) {
visibleResultList = false
if (s.toString().length != 0) {
getSearchSuggetion(no_of_rec, 0, s.toString())
} else {
// etSearch.setText("")
}
Log.e("text_change","============"+s.toString())
}
override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {}
override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {
}
})
To solve this problem just add android:usesCleartextTraffic="true" in your AndroidManifest.xml file which is at ..\app\src\main\AndroidManifest.xml just like bellow...