I've been working on developing a library for my company for the past couple months and have been annoyed by the fact that filestreams seem to need a context whenever I store or load data to the internal storage.
I have designed the library to work like this :
A singleton class is made for providing and handling a keychain(containing app key and device id) and authinfo(user and password)
Whenever a request to call to a web service is made the calling class will attempt to get an instance of the singleton class and get the keychain and auth info through it like such :
SingletonClass.getInstance().getCredentials(Context ctx);
The result of this is that I need to constantly provide the context of the calling activity as most of my library revolves around calling an API with credentials and device id as parameters.
I am specifically referring to these lines :
....
FileOutputStream fos = ctx.openFileOutput(filename,
Context.MODE_PRIVATE);
fos.write(buf);
fos.close();
....
I am confused as to why the specific context of the activity calling is needed. Any help is greatly appreciated. Is there another way of solving this design issue ?
The application context should work for this - you could consider using this method: Using Application context everywhere? so you can easily get the application context without having to pass it around.
The file storage API is provided by the Context class.
So you need it.
Related
I'm getting an weird error so I'm trying to eliminate the possibilities.
Does the context passed to PreferenceManager.getDefaultSharedPreferences() changes the result?
I mean, when i'm writting setting to my app i never pay attention which context i pass to this method since it is a valid context...
Sometimes i put the Activity, sometimes the Appliaction whatever context i've on hands
Is it wrong? I've noticed that i'm getting wrong preferences values at some point, and i dont know if there is a bug in my code or if this be
It doesn't matter whether you provide an Application or an Activity as the Context parameter for PreferenceManager.getDefaultSharedPreferences().
If you look at the source for getDefaultSharedPreferences():
return context.getSharedPreferences(getDefaultSharedPreferencesName(context),
getDefaultSharedPreferencesMode());
Looking further, into getDefaultSharedPreferencesName(context):
return context.getPackageName() + "_preferences";
This means that for any Context of your application, you'll get the same SharedPreferences back, as your application ID does not change based on Activity or Application.
The only time you could run into a potential issue is if you are manually creating a Context for another package (e.g. using Context.createPackageContext()).
SharedPreferences data stores all have a name, and as long as you use the same name you'll always get the same data store.
Hat tip to #kcoppock who has pointed out that in the particular case of PreferenceManager.getDefaultSharedPreferences(), the only thing the generated name is dependent on is the Context's package. Since any Application or Activity instance you pass is exceedingly likely to have the same package name, in your case you should always get the same data store.
There are other ways to retrieve SharedPreferences stores, though. Activity.getPreferences() will generate the name based on the Activity's class name, so calling getPreferences() from inside two different activities will give you two different data stores.
You can also call Context.getSharedPreferences() directly (both PreferenceManager and Activity just call through to this) and pass a data store name explicitly. There's no requirement for how the name should look; as long as you use the same name you'll always get the same data store.
https://developer.android.com/reference/android/content/Context#getSharedPreferences(java.lang.String,%20int)
User can define at Data Usage screen a limite and/or a warning limit for mobile data usage. So how can I get this information by code?
Screen of Data Usage configuration of native OS.
I wanna the limit value and warning value.
I've already tried this but not work and always return NULL to both:
final Long recommendedBytes = DownloadManager.getRecommendedMaxBytesOverMobile( this.context );
final Long maximumBytes = DownloadManager.getMaxBytesOverMobile( this.context );
// recommendedBytes and maximumBytes are NULL
And TrafficStats class just have a data transferred not the limits.
After days searching and research about this problem I couldn't find a answer for that. Bellow I will lift every attempt that I did.
1. Download Manager
With this class you can start download over any network or device
state and it will handle all states e.g. network loss, device reboot,
etc...
There are two methods called getMaxBytesOverMobile and
getRecommendedMaxBytesOverMobile, they was a pretty candidate
to solve this problem at first time. But after code tests and
Download Manager implementantion research I'd found that there is
no way to get thoose values by DownloadManager.
Reason
Thoose methods call Settings.Secure.getLong with they
respective labels
Settings.Secure.DOWNLOAD_MAX_BYTES_OVER_MOBILE and
Settings.Secure.DOWNLOAD_RECOMMENDED_MAX_BYTES_OVER_MOBILE in
the turn makes a call to a lazy String map inside inside a
inner class called NameValueCache.
Ok so far but none of inner classes or Settings implementation it
self use DOWNLOAD_MAX_BYTES_OVER_MOBILE or
DOWNLOAD_RECOMMENDED_MAX_BYTES_OVER_MOBILE inside.
I considered the lazy map was populate by a third entity, what
actually happens, so I found the NameValueTable Settings
inner class that handle the new values to lazy map. The
putString is a protected method call by Settings.Secure
and Settings.System inner classes (calls of Secure and
System).
So I could conclude that if the OS implementantion do not put thoose String values I can't get them.
2. TrafficStats
Just a quick look on official reference I could notice that it will
not help me because this class just provide the amount of bytes and
packages that was trafficked since last device boot.
http://developer.android.com/reference/android/net/TrafficStats.html
3. NetworkPolicyManager and NetworkPolicy
As #bina posted here the both classes are hidden and could not
be use by normal apps e.g. that will be published in Google Play.
https://stackoverflow.com/a/24445424/575643
4. ConnectivityManager
In short, you just can get the NetworkInfo that not provide
much information about user preferences (really none!). Just provide
informations about network and e.g. mobile network provider.
http://developer.android.com/reference/android/net/ConnectivityManager.html
After all I assume that no way to get this information nowadays. Please if you read it and found a way post here!
Thanks for all.
PS.: Sorry by english mistakes.
Do you want to get limit value(5GB) and warnning value(2GB) in this example?
If so, you can get limitBytes and warningBytes by the following code, if you can use android.permission.MANAGE_NETWORK_POLICY and android.permission.READ_PHONE_STATE.
However, android.permission.MANAGE_NETWORK_POLICY protectionLevel is signature.
NetworkPolicyManager manager = (NetworkPolicyManager) getSystemService("netpolicy");
NetworkPolicy[] networkPolicies = manager.getNetworkPolicies();
Log.d("NetworkPolicy", "limitBytes is " + networkPolicies[0].limitBytes);
Log.d("NetworkPolicy", "warningBytes is " + networkPolicies[0].warningBytes);
(NetworkPolicyManager and NetworkPolicy classes are hidden)
I am developing an Android application. The content for the application is taken from the webserver using webservice. I am taking the data from webserver and store in mobile db and accessing across the application and its works fine but now problem is while taking more records from mobile db it tooks some time and it application hangs.
Is it possible to maintain the java collection such as hashmap or hashtable to maintain throughout the application until user logout the application and user can add or update the data in collection. If so please guide me.
you should use Application class that ships with Android API .
See this link..
http://www.xoriant.com/blog/mobile-application-development/android-application-class.html
First of all it's better to user db for storing purpose. you should look for optimizing you db querys and the they way you are using it. But anyways you can create a static hashmap or arraylist of your object in your first activity. Then you can use this collection object anywhere you wanted and perform any opration, it will be intect untill and unless you logout of application or any exception occures while working on the collection.
class MylunchedActivity extends Activty{
public static HashMap map = new HashMap();
}
MylunchedActivity should be your first activity. Then by using MylunchedActivity.map, you can work on you map.
i hope this will help.
Regards,
Ravi
use a standalone class or static class to maintain run time static data you need to store.
Created a global singleton in the Application class and was able to access it from the activities I used.
You can pass data around in a Global Singleton if it is going to be used a lot.
public class YourApplication extends Application {
public SomeDataClass data = new SomeDataClass();
// Your JAVA collections...
}
Then call it in any activity by:
YourApplication appState = ((YourApplication)this.getApplication());
appState.data.UseAGetterOrSetterHere(); // Do whatever you need to with the data here.
For more info look at Android Application Class
Here are few possible solutions :
How to store hashmap so that it can be retained it value after a device reboot?
Saving a hash map into Shared Preferences
One is serialize/deserialize and other is using sharedpreference, as your requirement is to save/edit data until user logout.
File Access in Android SDK.
I am trying ( and have been for a while ) to find a way to access any files within my android application. By file i mean: Random Access, Input, Output, Shared, Private, whatever kind of file.
There are no working examples online ( other than what the android sdk site claims to work ), and any attempt to try examples on Android SDK or any other website fail.
Can someone please give sample code from beginning to end showing a class which uses files in their android application. something that can write data as simple as an integer ( i don't care what it writes )
Somehow I forgot that all example code from the Android examples has to be written in the Activity itself ( yes it does ).
In order to use the openFileInput method outside of the main Activity you must have a reference to the Activity Context which can be used in other classes with the import using:
import android.content.Context;
you must pass the Activity Context to another Context defined in that other class such as...
Context context;
public void passContext( Context cont ) {
context = cont;
}
and then you can use context from the new class ( which referes to the resources available to the main Activity ) to access files and other resources.
HaHa hope this help anyone else.
I have an application which has some static variables.
These variables are stored in an independent Class named DataContext.
These variables are initialized from raw files at the application start (a method named DataContext.initConstant() is called in the onCreate() of MyApplication which extends Application).
(EDIT : the initConstant method use an AsyncTask to load this data from files).
When my application comes to the background for a certain time or when my application used to much memory, these static variables become null.
How can it be prevented?
If not what should I do with my static variables?
I have other data which are stored in static variables to be used across different activities, but I clear them or pass them to null in the onLowMemory() of MyApplication.
What is the best way to keep some data accessible between activities if these data are too big to be serialized in an Intent, a database can't be used (for whatever reason), and can't be stored in files through serialization either?
You can't. Android needs to free up memory from time to time. Imagine if all applications had a ton of static data that is supposed to be resident forever - how would you fit that in memory? It's a mobile phone. It doesn't have virtual memory.
(and 3): Anything that is intended to be persistent needs to be stored, either via SharedPreferences, a Sqlite database, or a file.
Most likely the issue is that your application is being killed while it is in the background, and then recreated when you come back to it. Check out the Activity Lifecycle documentation on when this might occur for a single activity. You need to make sure that you move anything stored in memory to more permanent storage at the correct point in time to avoid losing that information if the app gets killed.
I'm not sure what exactly you are storing, but it sounds like using Shared Preferences might work well. This page on Data Storage explains a number of different ways of more permanently storing data, including Shared Preferences.
If you weren't using raw files, I'd advise initializing when the class is loaded.
For instance,
public static Map<?,?> myStaticMap = new HashMap<?,?>();
static { //fill myStaticMap }
You do have some bigger concerns to worry about if you are loading files that way. For instance, what about I/O errors, or latency issues? You will get warnings in gingerbread (if you enable them) for doing I/O in your main thread. Perhaps you should have an object to retrieve these values instead of a class with static fields. (perhaps with a static cache, although you should synchronize on it before checking/changing it)
I assume this is a data cache problem.
Storing data in static class is not guaranteed to work when user swap apps often. Android system will reclaim any background activity when memory is low. Static class is definitely among this category.
The proper way to do it is to use sharedPreference to persist cache data.
You can create your own getter and setter of the data you want and wrap it around sharedPreference object. When you access using getter, you should always check if the value is empty or expired. You can store an update_time when using setter.
For activity specific data, you can just use getPreference(permission), if you want to share data across activities and other applications components, you can use getSharedPreference(name, permission).
Normally, the permission will be MODE_PRIVATE such that the data can only be accessed within your application.
You should group data and store in difference sharedPreference object. This is good practice because when you want to invalidate that group of data, it is just a matter of one liner.
editor.clear(); editor.commit()
If you want to cache complex object, you should serialize it. I prefer JSON format. So you need some conversion mechanism in place. To do this, I will create my data object class extending JSONable class. JSONable class will have toJSON() method and readFromJSON(). This is convenient when restore and serialize data.
I store a User object and a Client object in my static scope. I have noticed from time to time the reference becomes null. So now in my getters I check to see if this value is null and if so I restart the app.
Intent i = context.getPackageManager().getLaunchIntentForPackage(context.getPackageName());
i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
context.startActivity(i);
I could have also chosen to reload the Client because I store the Access Token in prefs however I do so much initialization that I decided restarting the app would the best idea.
In your onResume() method you could query the static data to see if it is present and if not, load it back in again.
Instead of using the static variable u can use the shared preference for storing the value.
Note: for shared preference also you should not give heavy load.
I have solved this problem by having the super class with getter and setter function for storing and retrieving shared preference variable.
All class in my application extended the super class instead of activity.