How to use preferencesResId instead addPreferencesFromResource - android

I just start to study android, so have some problem
i have a file res/xml/settings.xml - settings from menu
create class Prefs and try to use settings from file above
package org.example.sudoku;
import android.os.Bundle;
import android.preference.PreferenceActivity;
public class Prefs extends PreferenceActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.settings);
}
}
Problem, that addPreferencesFromResource cant be used and i need to use preferencesResId (according to comments), but if i write something like this
preferencesResId(R.xml.settings);
its not good.
Where is error in code? Could any1 help?
Also i try to learn android by using book - Hello Android.

preferencesResId() is not a method, it is a placeholder in conversation for your resource id (R.xml.settings).
So although
addPreferencesFromResource(R.xml.settings);
Is deprecated, if you're using this approach, this is still the most correct way - there isn't another way using the deprecated approach.
I suggest you look at this SO question - it tells you what you should be using instead (PreferenceFragments). If you need a code sample, fire up Eclipse and the ADT plugin and make a SettingsActivity via the new Activity Wizard.
And as usual, here is the full JavaDoc for PreferenceActivity.

Related

How does android.support break Javas type safety?

Today i encountered a very strange behavior. I know, I'm using deprecated APIs but nonetheless, this should not be possible from my understanding.
I have a android.preference.PreferenceActivityin which I put the following xml via addPreferenceFromResource:
<PreferenceScreen
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<EditTextPreference
android:id="#+id/et_server_endpoint"
android:key="server_endpoint"
android:hint="http://192.168.100.42:8080"
android:title="Server Endpoint"
android:summary="Sets the Server Endpoint for the search"
android:dialogTitle="Server Endpoint Settings"
android:dialogMessage="Set the Servers endpoint"
/>
<SeekBarPreference
android:id="#+id/sb_phone_threshold"
android:key="match_treshold"
android:title="Matching Threshold"
android:summary="Sets the minimum Score for matches"
android:defaultValue="60"
android:min="40"
android:max="90"
app:adjustable="true"
app:showSeekBarValue="true"/>
</PreferenceScreen>
Note that SeekBarPreference is an android.support.v7.preference.Preference
I have no problem inflating the xml. The Screen shows as expected. The problem comes when I want to get a reference to it:
PreferenceActivity.findPreference(key) is supposed to return an android.preference.Preference class (which the SeekBarPreference is not).
but this code returns a valid Pref:
Preference match_treshold = findPreference("match_treshold");
I'm not allowed to cast it:
if (match_treshold instanceof SeekBarPreference){}
because of
error: incompatible types: Preference cannot be converted to SeekBarPreference
But surprisingly, if I debug the code I get this
It states, that the class is android.preference.SeekbarPreference. If I google that, all I can find is https://developer.android.com/reference/android/support/v7/preference/SeekBarPreference
which states that it's based on android.preference.SeekBarPreference. But I cannot find this specific class.
Beside the - from my point of view - poor design decision, to not inherit support.v7 Preferences from the Android ones: What the hell is going on there?
EDIT:
Due to request I post the Activity class
package com.my.company.domain.namespace;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.preference.Preference;
import android.preference.PreferenceActivity;
import android.preference.PreferenceManager;
import android.support.annotation.Nullable;
import android.support.v7.preference.SeekBarPreference;
import android.util.Log;
public class PrefActivity extends PreferenceActivity {
private SharedPreferences mPrefs;
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mPrefs = PreferenceManager.getDefaultSharedPreferences(this);
addPreferencesFromResource(R.xml.glass_prefs);
Preference matchTreshold = findPreference("match_treshold");
// code doesn't compile
// if (match_treshold instanceof SeekBarPreference){}
Log.d("Pref", "onCreate: SeekBarClass=" + matchTreshold.getClass().getName());
//prints 'android.preference.SeekBarPreference'
//one cannot import android.preference.SeekBarPreference
}
}
you need to add
implementation 'com.android.support:preference-v7:28.0.0'
to the build.gradle deps
The SeekBarPreference object that you end up with in an android.preference.PreferenceActivity is indeed an android.preference.SeekBarPreference. The issue here is that that class is hidden in the SDK (source), so Android Studio will not suggest it for auto-completion, nor will it import it automatically. Since you're using the support libraries in your project, and the support version of SeekBarPreference is publicly available, that will be the class Android Studio tries to use there, thus the conflict.
Unfortunately, PreferenceActivity does not check from where the preference XML is coming, so it will happily create an instance of that platform class whenever it sees a <SeekBarPreference> tag. This is arguably a bug, but I'm not sure they'd consider it so, as that class is nowhere mentioned in the documentation.
You possibly could still use the platform SeekBarPreference, as it should work like any other basic Preference, though it might get a little hairy if you need to manipulate it directly. However, writing your own, as you've mentioned, is certainly a more solid, accessible solution. The platform class (linked above) is a rather simple Preference subclass, so you could even just copy that out into your project, almost as is. The relevant layouts (here and here) are similarly straightforward, and don't rely on anything else hidden from the SDK.

Android. How to change own code programmatically?

I have a simple button
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/button"
android:onClick="trap" />
Initial code
package com.example.a21.ii;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void trap(View view){
//click function
}
}
After clicking it must change to this code
package com.example.a21.ii;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void trap(View view){
//click function
}
private void additionalFunction(){}
}
so how to change the own code? Any suggestion is appreciate and Please let me know if more details are need. Thanks
If you want to add an additional function, you cannot do it by changing the existing code.
The ANdroid APK is read-only. You cannot write to it, so you cannot change the .java files in the APK.
However:
You can create a class that loads the new methods (NOTE Database, shared prefs or files is required) and strips the function of them, and takes appropriate action without writing the methods to the APK.
Essentially, you want to execute the method without writing it to the APK, so you need to design a class that can execute these methods.
OR:
YOu can create an external class(File only) in internal or external storage. Then you write any methods to that class. Refer this SO question to see how you can load and execute code in external .java files.
Please note that this is a workaround. You cannot write to the APK, but you can write .java files to the system and load them and execute them at runtime.
Final note
The first option (Create a class to load methods and execute them internally in the app) is extremely hard. It may even be impossible. The second option (where you create a .java file externally and load it in) is probably the easiest option around. You save a file externally and add any methods you want, and create a new instance of the external class in the class you want these methods in. This is the only way (I know of) you can create files and make them editable.
And I cannot say it enough times:
The APK is read only!
You cannot write to the APK, but you can read from it. For an instance oyu can read assets, but you cannot write to the assets.
The only way to "change" the contents of an APK is to decode the old, add whatever changes you need and create a new apk. But the process of doing this requires root, and adding the entire system to an application that does something else will add a lot of bloat to your app. Further, it will then most likely be signed with a different keystore and may make it incompatible with the store version, which may remove the option for updates in the future.
And from your comments, I apparently have to say it one more time:
You cannot change the APK like changing a text file! The APK is like a zipped file. To change it, you have to unpack it and then edit it. Meaning no matter what programming language you are thinking of, you have to unpack the APK, change it and repack it. Which, as I mentioned above, has many side effects.
And as you mentioned in another comment, if you suddenly are wondering about windows and the function there, that is a whole other topic (and a whole different set of developers who have competence on the topic). Ask another question instead of having two very distinct questions in one

More problems with ViewPager example

I downloaded a ViewPager example from GitLib and, unfortunately, it had a "Sherlock theme" packaged with it that got all sorts of errors. I was advised, on another post to remove the theme, one step of that was to change the code below to extend from FragmentActivity instead of SherlockFragmentActivity. But when I do that I get errors.
setContentView(R.layout.main) errors saying that 'main' is not a field
the R.id.pager errors saying 'pager' is not a field
Since I don't understand how this code works yet, I don't know how to fix the errors.
Any insight would be appreciated.
thanks, Gary
public class ViewPagerFragmentDemoActivity extends SherlockFragmentActivity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
ViewPager pager=(ViewPager)findViewById(R.id.pager);
pager.setAdapter(new SampleAdapter(getSupportFragmentManager()));
}
}
It sounds like your R.java file has not been rebuilt (or you are pointing to the wrong one now).
Look in your imports for an android R file (IIRC it is com.android.R)... if it is there delete it. Then clean your project and Eclipse should then rebuild yours and import it.
Another possibility is that you have an error in an xml file. If the compiler cannot parse the xml file, it will fail to generate a new R.java file. Usually there is a little red flag on the problematic child.

Android - How to use included library projects in your main and call their activities

I've got a few projects Im trying to combine into one and Ive already included all the other projects as library ones through the settings. What Im sort of stuck on is how to use them in my main activity.
Ive messed around and feel like Ive almost got it but Im just stuck. I know I have to declare all the new activities in the main manifest but Im not sure about what to include in the main .java activity inorder to call from the newly included stuff.
Is this something that I could figure out by looking at the android api demos that come with the sdk?
Can some one point me to an open source project somewhere and explain the process used to include the library projects.
Any help would be much appreciated.
Are you using eclipse to manage your settings? It doesnt really matter, but its easier to make sure your library paths are set correctly and are accessible by the calling project.
Assuming that they are accessible, you just access the classes in the library like any other class: Import the package and instantiate the class as you would normally. For an android activity, this means that you would likely create an activity from the library based on some response from your main activity. It doesn't matter if that Activity is local to this project or imported from a library. eg:
// import the activity/package/class from your library
import com.mylibrary.activities.ImportedActivity;
public class LocalActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
// Button Code
button = (ImageView) findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
// create a new intent based on your library activity
Intent myIntent = new Intent(v.getContext(), ImportedActivity.class);
startActivityForResult(myIntent, 0);
}
});
}
note, I have not tried to compile the code above, its just for purposes of demonstration.
If your libraries are correctly referenced in eclipse, this should work. If not you will get errors on either the import of the external libraries (package not found) or build errors when the actual library is needed.

eclipse error with android: id cannot be resolved or is not a field

I just started playing around with android development, and already with just an attempt at making a button, I have encountered a problem.
The error I'm given in the following code is right on "R.id.button1".
It says id cannot be resolved or is not a field.
Do I need to manually reference every single object I make in the layout xml file? I found that this did work, but it does seem to be a bit much for every button I want to make...
package com.example.helloandroid;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
public class HelloAndroid extends Activity {
/** Called when the activity is first created. */
private Button button1;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
button1 = (Button)findViewById(R.id.button1);
button1.setOnClickListener(new OnClickListener()
{
public void onClick(View v)
{
finish();
}
});
}
}
I've been wasting a lot of time (two weeks) because of the same problem until I discovered the problem wasn't mine but Eclipse's.
I guess there's a lot of people with the same problem.
Just try this: Save your project, close Eclipse and then open it again. So simple.
Do I need to manually reference every single object I make in the layout xml file
Yes, otherwise you won't be able to do anything with those views. It's not that bad actually. So, each time you create a view in your XML, and you want to reference it, put an ID:
<View
android:id="#+id/the_id"/>
And then, from your code you can reference it using the R class. You can type, in the example, R.id.the_id and then Ctrl+Shift+O to make Eclipse auto import the needed files.
You can speed up your productivity by using frameworks like Roboguice; I think it's for lazy people, though.
This answer is not applicable to this question (looking at code you have provided). Just adding it if someone else stumbles here and above mentioned answers do not help.
If cleaning (Project --> clean) doesn't helps or saving and restarting eclipse doesn't help either, check for the following incorrect import.
import android.R;
Which Eclipse sometimes add by mistake on auto-import (Ctrl+Shift+O).
Remove that line (import) and it's done :D
Following this EXCELLENT tutorial , I encountered the same problem. After reading Carmello's answer (Sept 17, 2011. 07:23) I simply clicked File->Save All, and voila, 'button0' was automagically defined, and even syntax highlighted.
If "R.id.button1" is not defined, then you'll get a compile error, just as you saw. If you don't define this in the layout, then it won't be defined.
You don't have to specify every object you create in the layout, but you do if you try to reference it from "R.*". You can manually create buttons and other objects that are not specified in the layout.
I ran through the same issues for time being. Plz, do not forget to define as follows:
<View
android:id="#+id/button1" />
if you are using the id in your .java class.
Button b =(Button) findViewById(R.id.button1);
Being said that, the id defined in xml file must match with the id in findViewById().
Go to the 'R.java' file under the 'gen' folder and check whether your 'button1' is present under the class 'id'.If not,then this could be the reason you got that error.When you use the statement " R.id. " make sure that the is present under the appropriate class,in this case under the 'id' class.
R.id is a generated object that assigns int numbers to resources. Try this go to your gen/mypackage/R.java and delete the file. As you can see it is re-generated. This file provides static references where as the context is more of the dynamic state of your app. If you have syntax errors that will prevent automatic re-generation of that R.java file so you will get lots or R. errors. As everyone else has said you can click save all icon or ctl+shift+s on windows. You can clean the project project/clean and that will clean up 95% of those exceptions. Yes eclipse is buggy that way but netbeans does not support android that well. this link may help
Good luck
Do these things,anyone of this will help you
Project -> Clean,
Right click -> Fix Project Properties
Restart Eclipse
make some fake modification in manifest and save
check your console for any error message
check your drawable folder, check the image names satisfy the rules

Categories

Resources