I have developed a Import / Export feature for my app so uses can export the database and shared preferences to be used in another phone. This has worked fine up until I got myself a S3 and tried to do it.
After some work I got the database import / export to work (duel SCdards issue) but the shared preferences is still causing me trouble.
On a new install the import fails because there is no shared preferences file on the phone. Once I update an option the File is created (added in a check to see if the file on the phone exists)
This to create it
this.sharedprefs = context.getSharedPreferences("sharedprefres.xml", Activity.MODE_PRIVATE);
This to check file is there
File sharedPrefencesFileOnPhone = new File(/data/data/PACKAGE_NAME/shared_prefs/, "sharedprefres.xml");
if (sharedPrefencesFileOnPhone.exists())
Log.d(DEBUG_TAG, "SP : Running Copy");
The Copy then seems to go though but none of the options are updated.
This all works on the emulator with no issues
The check only works once I have updated a option and the file is created which is given me to belive the shared preferences are saved.
Does the S3 hide the shared preferences somewhere else and if so is there some code for me to track it down that would work on multi phones
Thanks for your time
Try
/dbdata/databases/package.name/shared_prefs/package.name_preferences.xml (if it exists use it)
otherwise
new File(getFilesDir(), "../shared_prefs");
or
/data/data/package.name/shared_prefs/package.name_preferences.xml
Related
I wrote the following code to create two shared preference files:
SETTINGS_NAME for normal business, and OAUTH_NAME
to hide oauth consumer keys, secrets, and access tokens.
[I've read many times on stackOverflow this is the best, though not great, way to hide them.]
protected void onStart() {
super.onStart();
sharedPreferences = getSharedPreferences(Constants.SETTINGS_NAME, Context.MODE_PRIVATE);
sharedPreferences.registerOnSharedPreferenceChangeListener(sharedPreferenceChangeListener);
sharedPreferenceChangeListener.onSharedPreferenceChanged(null, null);
sharedPreferencesOauth = getSharedPreferences(Constants.OAUTH_NAME, Context.MODE_PRIVATE);
}
But file OAUTH_NAME is not at all private!
It may be true that it can't be programmatically read by other apps,
but on a rooted device it can be opened and examined in ES File Explorer;
It's in /data/data/{packageName}/share_prefs/SHARED_PREFS_OAUTH_NAME.xml .
Certainly not much of a challenge for a hacker.
File SETTINGS_NAME, on the other hand, does seem to be more private in that
it is NOT in folder /data/data/{packageName}/share_prefs/ .
My question: why is file SETTINGS_NAME not in folder .../shared_prefs while file OAUTH_NAME -- also created MODE_PRIVATE -- is in folder .../shared_prefs?
Private settings are saved in an application's private directory.
On a rooted device nothing is private. It's like leaving your house's door wide open and wondering how can you be safe against a thief.
Saving a file in a more hidden location doesn't give much security, because anyone can dump .apk, decompile it and find where that file was saved. The only way you can save secure data on a rooted phone is to use encryption without storing a password.
You are running on Rooted-device right ?
Once rooted, everything can be accessed even the system file. so MODE_PRIVATE is working in this case.
You can access them via any explorer app. Can't protect your file now !!!
is there a way to retain some of my data after uninstalling the app and than again installing it on the device. I need to check if my app had been installed on one's device previously or not.
Yeah it's possible if you save App Data in External Storage of your device because that data is not deleted even if your app is uninstalled.
Upon reinstalling the app, you can read the file data to determine was the app previously installed or it is a fresh install in case that file doesn't exists.
Note:- Data in External Directory would be visible to user so it might be a case that user may delete the data from file manager.
You can use shared preferences to store this data.
Create the sharedreferences with MODE_WORLD_READABLE.
You can set a flag as true when the app is run, and can extract this value on each installation to find out whether this value exists.
Something like below:
When the app is run(Write this code in the launch code for your app-which is triggered first):
SharedPreferences sharedpreferences = context.getSharedPreferences("test", Context.MODE_WORLD_READABLE);
SharedPreferences.Editor editor = sharedpreferences.edit();
editor.putString("app_already_installed", "true");
editor.commit();
Checking whether the app was already installed(Write this where you want to check for earlier installations):
SharedPreferences sharedpreferences = context.getSharedPreferences("test", Context.MODE_WORLD_READABLE);
String is_app_already_installed= sharedpreferences.getString("app_already_installed", "false");
if(is_app_already_installed.equals("true"){
//do-something
}
else{
//do-something
}
Part of my app functionalities is allowing user to multi select photos from gallery and then upload them. Before uploading, user is free to add/delete their photos.
What I'm doing is I create and store these temporary image files in Titanium.Filesystem.tempDirectory, with an intention that these will be deleted eventually on app restart or shutdown.
Though, when I use Finder to track these files, they're still there and do not get deleted after I close and reopen the app/reboot ios simulator.
So do I have to explicitly delete these files? Does the actual ios device behave any differently?
Thank you
Simply the codes where these img files get created:
var f = Titanium.Filesystem.getFile(Titanium.Filesystem.tempDirectory, fileName);
if (f.write(imageBlob) === false) {
console.log("Image writing failed");
}
You can just leave the files there. On a device they will be cleaned up when the device needs space.
When creating a new version of my Unity3D app, I tested sideloading the new version on top of a from-the-store install. The sideloaded app was no longer able to find the files saved from the from-the-store version.
It seems as though the issue is that Application.persistentDataPath differs between the two app versions.
Under BuildSettings:
Install Location: Prefer External
Write Access: Internal Only
The AndroidManifest.xml seems to have no information about the install location/write access location.
I wouldn't mind changing the Install Location to Force Internal, if that helps with this update and/or in the future. But I am unsure what that setting does.
I'm saving XML files using C#'s XMLSerializer and then writing them to a FileStream using Application.persistentDataPath.
XmlSerializer serializer = new XmlSerializer(typeof([CLASS]));
FileStream stream = new FileStream( Application.persistentDataPath + "/[FILENAME].xml", FileMode.Create);
serializer.Serialize( stream, [OBJECT]);
stream.Close();
You can try saving the XML string in the PlayerPrefs like so:
PlayerPrefs.SetString("SaveGameName", yourXML);
and get it like so:
myxml = PlayerPrefs.GetString("SaveGameName");
In the past the PlayerPrefs class worked well for me for persistent data. I know for a fact this data persists even if you install new versions from the app store.
http://docs.unity3d.com/ScriptReference/PlayerPrefs.html here is the docs on it.
Im working on an app (flex 4.12 sdk, using flashbuilder 4.5, creating an app for ios and android, testing on an android htc one primarily)... and am using the camera to capture a file... Im then saving that image to the application storage directory, and I want to open the image in the default web browser or trigger a native dialog (android users) to choose the web browser of their choice... how it opens isnt really important right now -- Im mainly trying to just 'access' it with the device and 'load' it outside my air app...
heres the code I have:
var fs2 : FileStream = new FileStream();
fs2.addEventListener(Event.CLOSE, fileCompleteHandler);
var targetFile : File = File.applicationStorageDirectory.resolvePath("test.jpg");
fs2.openAsync(targetFile, FileMode.WRITE);
fs2.writeBytes(myBMDByteArray,0,myBMDByteArray.length);
fs2.close();
and for the event listener that detects the close of the newly created file:
function fileCompleteHandler(e:Event):void {
trace('File saved.');
trace('exists? ' + targetFile.exists);
trace('the url: ' + targetFile.url);
trace('path: ' + targetFile.nativePath);
navigateToURL(new URLRequest(targetFile.url));
}
I get the following info back from this listener
File saved.
exists? true
the url: app-storage:/test.jpg
path: /data/data/air.com.xxxxx.apptesting.debug/com.xxxxx.apptesting.debug/Local Store/test.jpg
... and problem is that navigateToURL cant access the location where the file is stored (the protocol shows in browser as file:///data/data/air.com/xxx... )
how can I use navigateToURL to get access to this newly created file in the web browser or whatever native application the device associates with the file (its a .JPG file)? I also have had success in adding the newly created image to the camera roll but couldnt figure out how to then open that newly saved image in the native camera roll or whatever app the device chooses or presents to the user for the .jpg format.
I can show the user the image INSIDE my app by referencing the bitmap data fine, I just want to give the user access to the physical file that Im creating on their device.
I even have had success in posting (via urlLoader) the bitmap data as base64 encoding and then creating a file on the server side and loading that url but the encoding and trip to and from the server to give the user the image adds a lot of overhead and it takes a little too long and I'd like to avoid that elongated process.
Thanks for any help anyone can provide - let me know if I need to be more specific in any of this.
Solved the issue... I was able to store / write my file in the documentsDirectory using:
var targetFile : File = File.documentsDirectory.resolvePath('test.jpg');
and then
navigateToURL(new URLRequest(targetFile.url));
And this works fine now. Hopefully it helps someone else! Seems that the storage directory SHOULD work but up until now I've only written to and read files stored there... maybe to open the files one HAS to copy it to a 'safe' location in the filesystem (i.e. sd card?)... will move on to test in ios Now - hope all works well in that OS. Thanks all who chimed in on this.
My first hunch is that you need to specify the proper user-permissions in your application descriptor so you can use the openWith functionality with content from your application.
Remember that you need to specify this for IOS and Android specifically.
On your application.xml you need this permissions set inside android > manifestAdditions > manifest:
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
With this permissions you can save files to applicationStorageDirectory:
const FILE_LOADER:URLLoader = new URLLoader();
FILE_LOADER.addEventListener(Event.COMPLETE, onTempFileComplete);
FILE_LOADER.dataFormat = URLLoaderDataFormat.BINARY;
FILE_LOADER.load(new URLRequest(BASE_URL + filePath));
The applicationStorageDirectory can only be accessed by the application it belongs too when using Android or iOS. navigateToURL() hands over your request to the default browser, which cannot access said directory.
documentsDirectory is a public directory in Android, but not in iOS. So it cannot be used for both platforms. Unfortunately none of the pre-compiled file paths File has point to a public directory in iOS. You can find a table explaining all the pre-compiled paths here