I want to do the following:
I want to make a very simple gallery application. So I'd like to select a path for the images and set it as a resource. I set it in String.xml.
So I have another class, which needs the selected path to load all the images from it.
class ImageHolder
{
public ImageHolder()
{
this(R.string.image_dir);
//problem is here - R.string.image_dir returns a unique int, while what I really need is the string. How can I get it...
}
public ImageHolder(String path)
{
.........standart procedure.....
}
}
Use getString(resID) but you'll need a Context Object though.
It's a Function of Context, so within an Activity you can write this.getString(R.string.image_dir); or you can skip this altogether...
Related
So, I have this structure:
typedef struct{
int serialNumber;
char name[100];
float price;
int quantity;
}Products;
And I created an array of structures dynamically.
The task was to 'simulate' a grocery store, with the user able to add and edit the items sold by the store. The following code snippets are for editing structure data.
void overwrite(Products store){
printf("Enter new serial number: ");
scanf("%d", &(store.serialNumber));
getchar();
printf("Enter new product name: ");
fgets(store.name, 100, stdin);
store.name[strlen(store.name)-1]='\0';
printf("Enter new product price: ");
scanf("%f", &(store.price));
printf("Enter new product quantity: ");
scanf("%d", &(store.quantity));
}
void editData(Products *store, int storeCapacity){ //storeCapacity needed to invoke printData(), assume a working code for the function.
int choice;
printData(store, storeCapacity);
printf("Enter slot number of product here: ");
scanf("%d", &choice);
overwrite(store[choice]);
}
Here's the catch, even though this code works, when I try to print the data, the data displays the values which should be overwritten. Have I forgotten to do something? I wish you could help me.
BTW, I code on an Android phone.
void overwrite(Products store){
C is pass by value, you need to pass a pointer to Products (i.e., Products *store) and modify the overwrite call in editData accordingly.
Basically the problem is that in C you pass arguments by value. So when you specify this signature
void overwrite(Products store)
and you invoke it somewhere:
Products myStore;
overwrite(myStore);
what happens is that a copy of myStore is created and placed on the stack, then the value is passed to the function. This means that every modification done to the Products object inside overwrite applies on the passed copy, not on the original object. This copy is then discarded when exiting the scope of overwrite function.
To solve this problem you must pass a pointer to the object, that is passed by value but being an address will point to the exact same myStore object. This is done in this way:
void overwrite(Products* store)
{
..
scanf("%f", &store->price);
..
}
Products myStore;
overwrite(&myStore);
According to Ouah, I passed the structure as the value itself, which did happen in my code.
So what I did is...
void overwrite(Products * store){ //formal parameter changed into a pointer
//codes here
}
And...
overwrite(&(store[choice])); /* actual parameter changed into a pointer by affixing ampersand*/
Further explanations of the codes' misbehavior were explained by Jack. I extend my gratitudes to you. The code now worked as it should be.
I know, there are plenty of questions in regards to saving/retrieving data on here. I was doing find looking things up on my own and really thought I could manage to find my answers without having to "ask a question", but I began to wonder something that I haven't seen an answer for on here.
MY SITUATION:
Naturally, I'm making an app. Upon closing the app, I want to save a simple array of numbers (0 or 1) or boolean values as it were. Upon starting the app, I want to search for that array, if it exists, and retrieve it for use within the app.
I began placing my code into the activity in which the array would be used. But, I started wondering if I would have to copy/paste the overridden onStop() function into all of my activities? Or do I do it in the main activity and somehow link the other activities.
Basically, no matter what state/activity the app is currently on when the app is closed, I want to be able to save the array of int/bool and open it back up when the app is started.
Maybe I didn't know how to search for what I wanted, so explaining it felt like the right thing to do.
I don't mind doing more searching, but if someone would point me in the right direction at the very least, I'd be extremely grateful.
EDIT: If there's a better way to do what I want than what I described (i.e. using a different state instead of onStop(), for instance), please feel free to throw out ideas. This is my first time actually having to deal with the activities' lifecycles and I'm a bit confused even after looking through the android development tutorials. I really think they're poorly done in most cases.
When you application needs to save some persistent data you should always do it in onPause() method and rather than onStop(). Because if android OS kills your process then onStop() and onDestroy() methods are never called. Similarly retrieve data in onResume() method.
Looking at the purpose you want to fulfill, SharedPreferences is all you want.
The documentation states:
"SharePreferences provides a general framework that allows you to save
and retrieve persistent key-value pairs of primitive data types. You
can use SharedPreferences to save any primitive data: booleans,
floats, ints, longs, and strings. This data will persist across user
sessions (even if your application is killed)."
Use SharedPreference to store small amount of data or use SQLite to store large amount of data.
See this link
http://developer.android.com/guide/topics/data/data-storage.html
Serialize an object and pass it around which is more dependable than shared preferences (had lots of trouble with consistency with shared preferences):
public class SharedVariables {
public static <S extends Serializable> void writeObject(
final Context context, String key, S serializableObject) {
ObjectOutputStream objectOut = null;
try {
FileOutputStream fileOut = context.getApplicationContext().openFileOutput(key, Activity.MODE_PRIVATE);
objectOut = new ObjectOutputStream(fileOut);
objectOut.writeObject(serializableObject);
fileOut.getFD().sync();
} catch (IOException e) {
Log.e("SharedVariable", e.getMessage(), e);
} finally {
if (objectOut != null) {
try {
objectOut.close();
} catch (IOException e) {
Log.e("SharedVariable", e.getMessage(), e);
}
}
}
}
Then use a class to use:
public class Timestamps implements Serializable {
private float timestampServer;
public float getTimestampServer() {
return timestampServer;
}
public void setTimestampServer(float timestampServer) {
this.timestampServer = timestampServer;
}
}
Then wherever you want to write to the variable use:
SharedVariables.writeObject(getApplicationContext(), "Timestamps", timestampsData);
Best way to achieve that is:
create a class. Call it MySettings, or whatever suits you
in this class, define the array of ints / booleans you are going to share, as static. Create getter & setter method (property) to access that (also as static methods)
add a static load() method to MySettings that reads from SharedPreferences. When you launch the app (in your first activity or better in a subclass of Application) call MySettings.load(). This load method sets the array
add a static save() method. Public also. Now you can save from anywhere in you app. This save() method reads the array and writes in SharedPreferences
Code sample:
public class MySettings {
private static List<Integer> data;
public static void load() {
data = new ArrayList<Integer>();
// use SharedPreferences to retrieve all your data
}
public static void save() {
// save all contents from data
}
public static List<Integer> getData() {
return data;
}
public static void setData(List<Integer> data) {
MySettings.data = data;
}
}
I want to save my webview to a PDF file. I know that I can print the WebView with WebView.createPrintDocumentAdapter() and PrintManager.print().
But I need a way to save the PDF, that is generated internally by the PrintDocumentAdapter, directly without any user interactions, because I need the file for further processing inside my app.
Any ideas?
I realise this question is quite old now. But I have just realised how this can be sensibly done.
Essentially as per the question you can use the createPrintDocumentAdapter method mentioned above and pass the result to your own "fake" PrintManager implementation which simply overrides the onWrite method to save the output to your own file. The snippet below shows how to take any PrintDocumentAdapter and send the output from it to a file.
public void print(PrintDocumentAdapter printAdapter, final File path, final String fileName) {
printAdapter.onLayout(null, printAttributes, null, new PrintDocumentAdapter.LayoutResultCallback() {
#Override
public void onLayoutFinished(PrintDocumentInfo info, boolean changed) {
printAdapter.onWrite(null, getOutputFile(path, fileName), new CancellationSignal(), new PrintDocumentAdapter.WriteResultCallback() {
#Override
public void onWriteFinished(PageRange[] pages) {
super.onWriteFinished(pages);
}
});
}
}, null);
}
As you can see there's quite a few nulls passed into the adapters methods but I have checked the Chromium source code and these variables are never used so the nulls are ok.
I created a blog post about how to do it here:
http://www.annalytics.co.uk/android/pdf/2017/04/06/Save-PDF-From-An-Android-WebView/
Create a custom WebViewClient (reference) and set it on your WebView.
In this WebViewClient you should override shouldOverrideUrlLoading (WebView view, String url). From here on you can download the PDF manually when it is clicked.
Is it possible to access or use methods from different packages (or package libraries) in an Android project?
You can import other packages, in order to change values you should define set-functions within the package you are going to import.
e.g
public void setString (String sNew) // in case its a string
{
YOURVALUE = sNew; // YOURVALUE should be the value you want to change
}
in order to get the value you should use a get-function
public String getString ()
{
return YOURVALUE;
}
just change the type to the one you need.
after that you are able to call these functions like :
PACKAGENAME.setString("This is the new Value");
System.out.println(PACKAGENAME.getString());
I want to be able to iterate through all of the fields in the generated R file.
Something like:
for(int id : R.id.getAllFields()){
//Do something with id, like create a view for each image
}
I've tried reflection, but I can't seem to load a specific inner class that's contained inside the R class. So, for example, this wouldn't work for me:
Class c = Class.forName("packageName.R.id")
I can reflect on the R class itself, but I need the fields within the id class.
I also tried looking through the Resources class, but couldn't find anything there. In that case, it seems you can take a resourceID and get the string name of that id, or take a string name and get the corresponding resourceID. I couldn't find anything like:
int[] Resources.getAllResourceIDs()
Maybe I'm going about this wrong. Or maybe I shouldn't fight typing them all in by hand, e.g.:
int[] myIds = {R.id.firstResource, R.id.secondResource}
This approach has the downside of not being as flexible when working with my UI designer. Whenever he adds a new resource to the XML file, I'll have to update the code. Obviously not too painful, but it would still be nice to have and it seems like it should be doable.
EDIT:
The answer below about ViewGroup.getChildCount()/ViewGroup.getChildAt() works fine. But, I also had to find a way to instantiate my XML ViewGroup/Layout. To do that, try something like:
LayoutInflater li = MyActivity.getLayoutInflater();
ViewGroup vg = (ViewGroup) li.inflate(R.layout.main, null);
I found that "Class.forName(getPackageName()+".R$string");" can give you access to the string resources and should work for id, drawable, exc as well.
I then use the class found like this:
import java.lang.reflect.Field;
import android.util.Log;
public class ResourceUtil {
/**
* Finds the resource ID for the current application's resources.
* #param Rclass Resource class to find resource in.
* Example: R.string.class, R.layout.class, R.drawable.class
* #param name Name of the resource to search for.
* #return The id of the resource or -1 if not found.
*/
public static int getResourceByName(Class<?> Rclass, String name) {
int id = -1;
try {
if (Rclass != null) {
final Field field = Rclass.getField(name);
if (field != null)
id = field.getInt(null);
}
} catch (final Exception e) {
Log.e("GET_RESOURCE_BY_NAME: ", e.toString());
e.printStackTrace();
}
return id;
}
}
Your reply to my comment helped me get a better idea of what you're trying to do.
You can probably use ViewGroup#getChildAt and ViewGroup#getChildCount to loop through various ViewGroups in your view hierarchy and perform instanceof checks on the returned Views. Then you can do whatever you want depending on the type of the child views and where they are in your hierarchy.
You can use reflection on an inner class, but the syntax is packagename.R$id. Note that reflection can be very slow and you should REALLY avoid using it.