How can i save files in the phone accessible by several apps? - file

I try to develop several WP8 apps using the same credentials for all(same user and password).So if the user choose to change his credentials he does only once in one app and it will change for all.
Until now i used Isolatedstorage to save the credentials(as shown below) but im wondering if the files would be accessible by all the apps...i guess they would not.
So what solution do you have ?
thanks for your help
public static void SaveToFile(byte[] Encryptedfile, string FileName)
{
using (var SaveApplicationFile = IsolatedStorageFile.GetUserStoreForApplication())
{
SaveApplicationFile.DeleteFile(FileName);
using (IsolatedStorageFileStream fileAsStream = new IsolatedStorageFileStream(FileName, System.IO.FileMode.Create, FileAccess.Write, SaveApplicationFile))
{
using (Stream writer = new StreamWriter(fileAsStream).BaseStream)
{
writer.Write(Encryptedfile, 0, Encryptedfile.Length);
}
}
}
}

You can't access IsolatedStorage of other App.
Nor you can't save on SD card.
Maybe consider using Skydrive or other exteral storage.
Another idea, I'm thinking about - maybe you can use MediaLibrary and Save Picture there. And use this picture as a container for some data - maybe using Steganography ;)

Related

Copy/Cache Azure database locally for offline use.

I have a piece of software that connects to an Azure database to gather formulas for several varieties of colors to allow the user to follow a recipe to create their own product.
Basically there is just one big database pull when the application launches, that pulls down all the formulas, and from there the user can simply use, modify, or even delete the formulas as they wish.
The problem is that where this software is used, there are seldom constant internet connections, and the application so far is simply designed to shutdown if there isn't one present.
I am looking for a solution for being able to allow the application to BOTH connect to the database on application startup(If a connection is present) and save a copy locally, or if no connection is present, check for a locally saved copy to work with.
I have looked everywhere, but have been unable to find any methods to "programmatically" retrieve the pertinent(or all, if necessary) data, and either export it to a local file, or cache it somehow for offline use.
Any suggestions?
You don't mention what kind of technology you're using on the client side, and if you require access to a database on the client or just the data - but regardless there are several ways to do this.
Azure Mobile apps have a quickstart which will implements an Azure SQL <-> SQL Lite (mobile) database sync framework (table controllers on the server side). This lets you use libraries on the mobile side to use the local db for getting its data, and when you know you're online you can sync to/from the server. This is quite sophisticated and probably gives you more than just the caching that you're looking for.
I've used two other strategies for caching - one for HTML/javascript based applications (phonegap/cordova) and the other for Xamarin c# apps on iOS and Android. I'm assuming if it's a standard windows desktop app you know how to persist data so you can use whatever kind of cache/file system/db you like.
JavaScript/html - use the html5 localStorage functions to store the JSON output of the web server calls you're making. This is really easy then to abstract, where your app before is making an ajax call to the server to get some data, instead move that to a "liveorcache" class, which can determine whether to go to the server or just use the local storage. Code snippet for saving/loading json in localstorage below:
$scope.saveFixtures = function () {
localStorage["fixtures"] = JSON.stringify($scope.fixtures);
};
$scope.loadFixtures = function () {
if (localStorage["fixtures"] != undefined) {
$scope.fixtures = JSON.parse(localStorage["fixtures"]);
}
};
If you're writing your app in Xamarin you can do the same kind of thing, but using a PCL library - I used "PCLStorage" which works on Android and iOS. Same strategy though, in my code I just write the JSON data to a file with an appropriate filename, but usually wrap the object in another object that contains the cache write date/time. You then serialise the object to the file - something like below.
public class CacheProvider
{
public static async Task<CacheModel> ReadCache<T>(string filename)
{
IFolder rootFolder = FileSystem.Current.LocalStorage;
IFolder cache = await rootFolder.CreateFolderAsync("sportenzaCache", CreationCollisionOption.OpenIfExists);
try
{
IFile file = await cache.GetFileAsync(filename);
var data = await file.ReadAllTextAsync();
return JsonConvert.DeserializeObject<T>(data) as CacheModel;
}
catch(FileNotFoundException ex)
{
return null;
}
}
public static async void WriteCache<T>(string filename, CacheModel data)
{
IFolder rootFolder = FileSystem.Current.LocalStorage;
IFolder cache = await rootFolder.CreateFolderAsync("sportenzaCache", CreationCollisionOption.OpenIfExists);
IFile file = await cache.CreateFileAsync(filename, CreationCollisionOption.ReplaceExisting);
if (file != null)
{
data.CacheCreated = DateTime.Now;
string json = JsonConvert.SerializeObject(data);
await file.WriteAllTextAsync(json);
}
}
public static async void DeleteCache(string filename)
{
IFolder rootFolder = FileSystem.Current.LocalStorage;
IFolder cache = await rootFolder.CreateFolderAsync("sportenzaCache", CreationCollisionOption.OpenIfExists);
IFile file = await cache.GetFileAsync(filename);
if (file != null)
await file.DeleteAsync();
}
}

Data storing in a mobile application(windows 8)

I need to store some data to use for a windows8 based mobile application. Data needed to be reuse. For an example need to store 4 phone numbers to send messages and another one to send calls. How can I store data in here. I have heard about isolated storage. Is it the way or can I connect it to a database. Will it application be too heavy if it is connected to a database?
Not sure what you mean by connect to a database.
In Windows Phone 8, Isolated Storage refers to storage each app has on the phone, and I don't think (I am not sure actually) other apps can access it. Basically if you need to save something it would look like that.
The following code is to save something:
IsolatedStorageFile myIsolatedStorage = IsolatedStorageFile.GetUserStoreForApplication();
//create new file
using (StreamWriter writeFile = new StreamWriter(new IsolatedStorageFileStream("myFile.txt", FileMode.Create, FileAccess.Write, myIsolatedStorage)))
{
string someTextData = "This is some text data to be saved in a new text file in the IsolatedStorage!";
writeFile.WriteLine(someTextData);
writeFile.Close();
}
To access that file at anytime you would just do this:
IsolatedStorageFile myIsolatedStorage = IsolatedStorageFile.GetUserStoreForApplication();
IsolatedStorageFileStream fileStream = myIsolatedStorage.OpenFile("myFile.txt", FileMode.Open, FileAccess.Read);
using (StreamReader reader = new StreamReader(fileStream))
{ //Visualize the text data in a TextBlock text
this.text.Text = reader.ReadLine();
}
Here is the link. http://www.geekchamp.com/tips/all-about-wp7-isolated-storage-read-and-save-text-files
Isolated Storage would allow you to permenately store files there and retrieve it even when the user quits their application.

Silverlight: Business Application Needs Access To Files To Print and Move

I have the following requirement for a business application:
(All of this could be on local or server)
Allow user to select folder location
Show contents of folder
Print selected items from folder (*.pdf)
Display which files have been printed
Potentially move printed files to new location (sub-folder of printed)
How can I make this happen in Silverlight?
Kind regards,
ribald
First of all, all but the last item can be done (the way you expect). Due to security protocols, silverlight cannot access the user's drive and manipulate it. The closest you can get is accessing silverlight's application storage which will be of no help to you whatsoever in this case. I will highlight how to do the first 4 items.
Allow user to select folder location & Show contents of folder
public void OnSelectPDF(object sender)
{
//create the open file dialog
OpenFileDialog ofg = new OpenFileDialog();
//filter to show only pdf files
ofg.Filter = "PDF Files|*.pdf";
ofg.ShowDialog();
byte[] _import_file = new byte[0];
//once a file is selected proceed
if (!object.ReferenceEquals(ofg.File, null))
{
try
{
fs = ofg.File.OpenRead();
_import_file = new byte[fs.Length];
fs.Read(_import_file, 0, (int)fs.Length);
}
catch (Exception ex)
{
}
finally
{
if (!object.ReferenceEquals(fs, null))
fs.Close();
}
//do stuff with file - such as upload the file to the server
};
}
If you noticed, in my example, once the file is retrieved, i suggest uploading it to a webserver or somewhere with temporary public access. I would recommend doing this via a web service. E.g
//configure the system file (customn class)
TSystemFile objFile = new TNetworkFile().Initialize();
//get the file description from the Open File Dialog (ofg)
objFile.Description = ofg.File.Extension.Contains(".") ? ofg.File.Extension : "." + ofg.File.Extension;
objFile.FileData = _import_file;
objFile.FileName = ofg.File.Name;
//upload the file
MasterService.ToolingInterface.UploadTemporaryFileAsync(objFile);
Once this file is uploaded, on the async result, most likely returning the temporary file name and upload location, I would foward the call to some javascript method in the browser for it to use the generic "download.aspx?fileName=givenFileName" technique to force a download on the users system which would take care of both saving to a new location and printing. Which is what your are seeking.
Example of the javascript technique (remember to include System.Windows.Browser):
public void OnInvokeDownload(string _destination)
{
//call the browser method/jquery method
//(I use constants to centralize the names of the respective browser methods)
try
{
HtmlWindow window = HtmlPage.Window;
//where BM_INVOKE_DOWNLOAD is something like "invokeDownload"
window.Invoke(Constants.TBrowserMethods.BM_INVOKE_DOWNLOAD, new object[] { _destination});
}
catch (Exception ex) { System.Diagnostics.Debug.WriteLine(ex.ToString()); }
}
Ensure you have the javascript method existing either in an included javaScript file or in the same hosting page as your silverlight app. E.g:
function invokeDownload(_destination) {
//some fancy jquery or just the traditional document.location change here
//open a popup window to http://www.myurl.com/downloads/download.aspx? fileName=_destination
}
The code for download.aspx is outside the scope of my answer, as it varies per need and would just lengthen this post (A LOT MORE). But from what I've given, it will "work" for what you're looking for, but maybe not in exactly the way you expected. However, remember that this is primarily due to silverlight restrictions. What this approach does is rather than forcing you to need a pluging to view pdf files in your app, it allows the user computer to play it's part by using the existing adobe pdf reader. In silverlight, most printing, at least to my knowledge is done my using what you call and "ImageVisual" which is a UIElement. To print a pdf directly from silverlight, you need to either be viewing that PDF in a silverlight control, or ask a web service to render the PDF as an image and then place that image in a control. Only then could you print directly. I presented this approach as a lot more clean and direct approach.
One note - with the temp directory, i would recommend doing a clean up by some timespan of the files on the server side everytime a file is being added. Saves you the work of running some task periodically to check the folder and remove old files. ;)

Tombstoning the last visited page the user was on

I want to tombstone the last page that the user was on and to retrieve it when the user comes back to the app. All of the tombstoning examples on the Internet deal with saving some data or the state of the page that the user has edited somehow (i.e inputed text in the textbox). In my app I don't have anything for the user to modify/edit so I just want to save the last visited page that the user was on. I tried to use some online examples that used PhoneApplicationService.Current.State but with no success.
Thank you to anyone who would like to help me out resolving this issue!
To locally store persistent data (data that should remain even when the user closes the app), you can use Isolated Storage.
So, in your app's Deactivated event, you can write the page's name to Isolated Storage like this:
//You get the Isolated Storage for your app (other apps can't access it)
IsolatedStorageFile isf = IsolatedStorageFile.GetUserStoreForApplication();
//if the file already exists, delete it (since we're going to write a new one)
if (isf.FileExists("lastpage.txt")) isf.DeleteFile("lastpage.txt");
using (var isoFileStream = new IsolatedStorageFileStream("lastpage.txt", FileMode.OpenOrCreate, isf))
{
//open a StreamWriter to write the file
using (var sw = new StreamWriter(isoFileStream))
{
//NavigationService.CurrentSource returns the current page
//we can write this to the file
sw.WriteLine((Application.Current.RootVisual as PhoneApplicationFrame).CurrentSource.ToString());
}
}
This will write the current page's name to the Isolated Storage. Then, in your OnNavigatedto method of your main page (the page that first opens normally) you can read the file name and navigate to it:
protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
{
IsolatedStorageFile isf = IsolatedStorageFile.GetUserStoreForApplication();
string lastpage = string.Empty;
if (isf.FileExists("lastpage.txt"))
{
using (var isoFileStream = new IsolatedStorageFileStream("lastpage.txt", FileMode.Open, isf))
{
//read the file using a StreamReader
using (var sr = new StreamReader(isoFileStream))
{
//get the uri we wrote and then convert it from a String to a Uri
lastpage = sr.ReadLine().Replace("file:///", "");
}
}
(Application.Current.RootVisual as PhoneApplicationFrame).Navigate(new Uri(lastpage, UriKind.Relative));
}
base.OnNavigatedTo(e);
}
This should read in the file you saved and then convert the string into an actual URI that you can pass to the NavigationService.
You can then delete the text file after it's been read so that it doesn't always keep jumping to that page.
In addition you can use this for getting the page name ,string PageName = (Application.Current.RootVisual as PhoneApplicationPage).Name; for getting the current page name
While I agree all the above options are possible, they are not really the correct way of doing something within a WP7.
It's better to construct a navigation page at the start of your app for properly controlling navigation, it also helps with managing back key events while using the app and prevents hiccups.
See Here for one example of implementing this:
Properly Exiting Silverlight-based WP7
With this done use the advice on storing values in isolated storage / application settings to then just store the "Current Page" state value (e.g. value of Page.GamePage) then the app navigation will direct you accordingly.
BUT beware when just storing the current page itself as you also need to save the correct state of any values or User entered data on that page when it tombstones as well, this the above advice should lead you in the right direction.
Hope this helps

Provide a database packaged with the .APK file or host it separately on a website?

Here is some background about my app:
I am developing an Android app that will display a random quote or verse to the user. For this I am using an SQLite database. The size of the DB would be approximately 5K to 10K records, possibly increasing to upto 1M in later versions as new quotes and verses are added. Thus the user would need to update the DB as and when newer versions are of the app or DB are released.
After reading through some forums online, there seem to be two feasible ways I could provide the DB:
1. Bundle it along with the .APK file of the app, or
2. Upload it to my app's website from where users will have to download it
I want to know which method would be better (if there is yet another approach other than these, please do let me know).
After pondering this problem for some time, I have these thoughts regarding the above approaches:
Approach 1:
Users will obtain the DB along with the app, and won't have to download it separately. Installation would thereby be easier. But, users will have to reinstall the app every time there is a new version of the DB. Also, if the DB is large, it will make the installable too cumbersome.
Approach 2:
Users will have to download the full DB from the website (although I can provide a small, sample version of the DB via Approach 1). But, the installer will be simpler and smaller in size. Also, I would be able to provide future versions of the DB easily for those who might not want newer versions of the app.
Could you please tell me from a technical and an administrative standpoint which approach would be the better one and why?
If there is a third or fourth approach better than either of these, please let me know.
Thank you!
Andruid
I built a similar app for Android which gets periodic updates with data from a government agency. It's fairly easy to build an Android compatible db off the device using perl or similar and download it to the phone from a website; and this works rather well, plus the user gets current data whenever they download the app. It's also supposed to be possible to throw the data onto the sdcard if you want to avoid using primary data storage space, which is a bigger concern for my app which has a ~6Mb database.
In order to make Android happy with the DB, I believe you have to do the following (I build my DB using perl).
$st = $db->prepare( "CREATE TABLE \"android_metadata\" (\"locale\" TEXT DEFAULT 'en_US')");
$st->execute();
$st = $db->prepare( "INSERT INTO \"android_metadata\" VALUES ('en_US')");
$st->execute();
I have an update activity which checks weather updates are available and if so presents an "update now" screen. The download process looks like this and lives in a DatabaseHelperClass.
public void downloadUpdate(final Handler handler, final UpdateActivity updateActivity) {
URL url;
try {
close();
File f = new File(getDatabasePath());
if (f.exists()) {
f.delete();
}
getReadableDatabase();
close();
url = new URL("http://yourserver.com/" + currentDbVersion + ".sqlite");
URLConnection urlconn = url.openConnection();
final int contentLength = urlconn.getContentLength();
Log.i(TAG, String.format("Download size %d", contentLength));
handler.post(new Runnable() {
public void run() {
updateActivity.setProgressMax(contentLength);
}
});
InputStream is = urlconn.getInputStream();
// Open the empty db as the output stream
OutputStream os = new FileOutputStream(f);
// transfer bytes from the inputfile to the outputfile
byte[] buffer = new byte[1024 * 1000];
int written = 0;
int length = 0;
while (written < contentLength) {
length = is.read(buffer);
os.write(buffer, 0, length);
written += length;
final int currentprogress = written;
handler.post(new Runnable() {
public void run() {
Log.i(TAG, String.format("progress %d", currentprogress));
updateActivity.setCurrentProgress(currentprogress);
}
});
}
// Close the streams
os.flush();
os.close();
is.close();
Log.i(TAG, "Download complete");
openDatabase();
} catch (Exception e) {
Log.e(TAG, "bad things", e);
}
handler.post(new Runnable() {
public void run() {
updateActivity.refreshState(true);
}
});
}
Also note that I keep a version number in the filename of the db files, and a pointer to the current one in a text file on the server.
It sounds like your app and your db are tightly bound -- that is, the db is useless without the database and the database is useless without the app, so I'd say go ahead and put them both in the same .apk.
That being said, if you expect the db to change very slowly over time, but the app to change quicker, and you don't want your users to have to download the db with each new app revision, then you might want to unbundle them. To make this work, you can do one of two things:
Install them as separate applications, but make sure they share the same userID using the sharedUserId tag in the AndroidManifest.xml file.
Install them as separate applications, and create a ContentProvider for the database. This way other apps could make use of your database as well (if that is useful).
If you are going to store the db on your website then I would recommend that you just make rpc calls to your webserver and get data that way, so the device will never have to deal with a local database. Using a cache manager to avoid multiple lookups will help as well so pages will not have to lookup data each time a page reloads. Also if you need to update the data you do not have to send out a new app every time. Using HttpClient is pretty straight forward, if you need any examples please let me know

Resources