How to detect the IsolatedStorage Used Space in Windows Phone - windows-phone

As per the title, how can I determine the used IsolatedStorage space in a Windows Phone Application?

You can know available free space and the used space.
try
{
using (var store = IsolatedStorageFile.GetUserStoreForApplication())
{
Int64 curAvail = store.AvailableFreeSpace;
var used = store.Quota - curAvail;
}
}
catch (IsolatedStorageException)
{
// TODO: Handle that store could not be accessed.
}

Related

Read the SMS activation code automatically in Xamarin Forms instead of manually typing it by user

I wrote a project with Xamarin Forms. When every user has signed up, I send him/her an activation Code to confirm it and the user has to insert it to enter the app. But I am looking for a plugin or a way that the user does not need to insert the activation Code.
I want the activation Code to be read automatically without the need to enter it manually.
First add the required permissions in AndroidManifest:
<uses-permission android:name="android.permission.RECEIVE_SMS" />
<uses-permission android:name="android.permission.READ_SMS" />
Here is SmsReceiver class in Android project:
using System.Linq;
using System.Text.RegularExpressions;
using Android.App;
using Android.Content;
using Android.Runtime;
using Android.Telephony;
using Java.Lang;
using Xamarin.Forms;
namespace MyProject.Android
{
[BroadcastReceiver(Enabled = true, Label = "SMS Receiver")]
[IntentFilter(new string[] { "android.provider.Telephony.SMS_RECEIVED", Intent.CategoryDefault })]
public class SmsReceiver : BroadcastReceiver
{
private const string IntentAction = "android.provider.Telephony.SMS_RECEIVED";
private static readonly string Sender = "SMS Sender number here";
private static readonly string[] OtpMessageBodyKeywordSet = {"Keyword1", "Keyword2"}; //You must define your own Keywords
public override void OnReceive(Context context, Intent intent)
{
try
{
if (intent.Action != IntentAction) return;
var bundle = intent.Extras;
if (bundle == null) return;
var pdus = bundle.Get("pdus");
// var castedPdus = JNIEnv.GetArray(pdus.Handle);
var castedPdus = JNIEnv.GetArray<Object>(pdus.Handle);
var msgs = new SmsMessage[castedPdus.Length];
var sb = new StringBuilder();
string sender = null;
for (var i = 0; i < msgs.Length; i++)
{
var bytes = new byte[JNIEnv.GetArrayLength(castedPdus[i].Handle)];
JNIEnv.CopyArray(castedPdus[i].Handle, bytes);
string format = bundle.GetString("format");
msgs[i] = SmsMessage.CreateFromPdu(bytes, format);
if (sender == null)
sender = msgs[i].OriginatingAddress;
sb.Append(string.Format("SMS From: {0}{1}Body: {2}{1}", msgs[i].OriginatingAddress,
System.Environment.NewLine, msgs[i].MessageBody));
//Toast.MakeText(context, sb.ToString(), ToastLength.Long).Show();
//Log.Error("Vahid", sb.ToString());
var msgBody = msgs[i].MessageBody;
if(!sender.Contains(Sender)) return;
bool foundKeyword = OtpMessageBodyKeywordSet.Any(k => msgBody.Contains(k));
if (!foundKeyword) return;
var code = ExtractNumber(msgBody);
MessagingCenter.Send<RegisterSecondPageModel, string>(new RegisterSecondPageModel(), "OtpReceived", code);
}
}
catch (System.Exception ex)
{
//Toast.MakeText(context, ex.Message, ToastLength.Long).Show();
}
}
private static string ExtractNumber(string text)
{
if (string.IsNullOrEmpty(text)) return "";
var regPattern = #"\d+";
var number = Regex.Match(text, regPattern).Value;
return number;
}
}
}
Note: In order to filter out the coming SMSes and detect only our own SMS we can apply these two filters:
1- Ignoring all SMSes that their sender numbers are not our SMS sender number.
2- Sometimes our SMS sender might send different SMSes to our clients, for example one SMS to send an activation code, and another to inform and confirm user's successfully registration in system. That said, we gotta distinguish them. For that we can search message body in order to find some pre-defined keywords. Of course our SMS server has to stick to a defined body format. "Activation", "Code", "Activation code" could be some example keywords in English language. Of course keywords should be defined in each language accordingly.
Here is RegisterSecondPageModel inside PCL project:
public class RegisterSecondPageModel
{
public RegisterSecondPageModel()
{
SubscribeToOtpReceiving();
}
private void SubscribeToOtpReceiving()
{
MessagingCenter.Subscribe<RegisterSecondPageModel, string>(this, "OtpReceived", (sender, code) =>
{
ActivationCode = code;
});
}
}
Another note is that as Jason already said, iOS doesn't allow apps to read SMSes.
If you're already sure about your clients having a SIM card in their device, then you can create a token and authenticate backwards, sending an SMS containing your token to from clients' device to your number.
Pros:
No blocked numbers: Sending messages from client is not blocked even if you're on their blacklist or they're blocking advertisements and unknown senders.
No costs on your side for authentication.
This works also in iOS which you can't read but can send messages.
Cons:
Client may be using another number in another device. This can be overcome by creating easy-to-type tokens which expire fast enough not to attract brute force attacks.
Client may not be able to send an SMS to your number due to several reasons including but not limited to not having enough account charge.

How can I get a list of variables and assignments / default values?

We have a collection of Microsoft Windows Workflows (.xaml files) that I need to go through and inventory the variables. The workflows are complicated with variables scoped at many levels so I can't simply open up the Workflow xaml and look at the Variables tab at the top level; I need to dig through each level, sequence, etc. to find all possible variable definitions.
Can I automate this process? Can Visual Studio aid in this process?
One solution, I could write some code to read the workflow file, look for variables, grab any default values, and check if the variable is assigned, thus overriding the default. Technically, this is possible from C#. But is this solution really necessary to get the information?
You can use a recursive function like this:
List<Variable> Variables;
private void GetVariables(DynamicActivity act)
{
Variables = new List<Variable>();
InspectActivity(act);
}
private void InspectActivity(Activity root)
{
IEnumerator<Activity> activities = WorkflowInspectionServices.GetActivities(root).GetEnumerator();
while (activities.MoveNext())
{
PropertyInfo propVars = activities.Current.GetType().GetProperties().FirstOrDefault(p => p.Name == "Variables" && p.PropertyType == typeof(Collection<Variable>));
if (propVars != null)
{
try
{
Collection<Variable> variables = (Collection<Variable>)propVars.GetValue(activities.Current, null);
variables.ToList().ForEach(v =>
{
Variables.Add(v);
});
}
catch
{
}
}
InspectActivity(activities.Current);
}
}
And should be called like this:
using (MemoryStream stream = new MemoryStream(Encoding.UTF8.GetBytes(xamlData)))
{
XamlXmlReaderSettings readerSettings = new XamlXmlReaderSettings()
{
LocalAssembly = Assembly.GetExecutingAssembly()
};
var xamlReader = new XamlXmlReader(stream, readerSettings);
Activity activity = ActivityXamlServices.Load(xamlReader);
DynamicActivity root = activity as DynamicActivity;
GetVariables(root);
}
Credit to: https://stackoverflow.com/a/11429284/593609

Identifying file changes in StorageFolder

I'm trying to keep a database in sync with the Windows 8 music library and I'm yet to find an efficient solution for doing so. I know that .NET has a FileSystemWatcher that's not available to Windows 8 apps. Currently, my idea is to compare the list of files returned by GetFilesAsync against my database and check if something was modified, deleted or added. I know this is not ideal but I can't find any other useful thing in Windows.Storage. My problem is that I want to make these updates automatically once there is a modification to the music library. Checking the ModifiedDate of the folders is useless when the changes happen in subfolders. Does anybody know if there is a way to tell when has a StorageFolder been modified?
If you are able to get ContentsChanged to fire reliably, then the code below may help you determine what changed.
Note, it isn't fast. GetBasicPropertiesAsync appears to take ~5ms/file... so ~10 seconds to diff a set of 1000 files.
(I cannot get ContentsChanged to fire reliably, and, after hours of googling, it appears many others have the same problem)
private class DiffSet
{
public IReadOnlyList<StorageFile> Added { get; set; }
public IReadOnlyList<StorageFile> Deleted { get; set; }
public IReadOnlyList<StorageFile> Changed { get; set; }
}
private static async Task<DiffSet> Diff(IEnumerable<StorageFile> oldSet, IEnumerable<StorageFile> newSet)
{
var newAsDict = newSet.ToDictionary(sf => sf.Path);
var added = new List<StorageFile>();
var deleted = new List<StorageFile>();
var changed = new List<StorageFile>();
var fromOldSet = new HashSet<string>();
foreach (var oldFile in oldSet)
{
if (!newAsDict.ContainsKey(oldFile.Path))
{
deleted.Add(oldFile);
continue;
}
var oldBasicProperties = await oldFile.GetBasicPropertiesAsync();
var newBasicProperties = await newAsDict[oldFile.Path].GetBasicPropertiesAsync();
var oldDateModified = oldBasicProperties.DateModified;
var newDateModified = newBasicProperties.DateModified;
if (oldDateModified != newDateModified)
{
changed.Add(oldFile);
}
fromOldSet.Add(oldFile.Path);
}
foreach (var newFile in newSet)
{
if (!fromOldSet.Contains(newFile.Path))
added.Add(newFile);
}
return new DiffSet
{
Added = added,
Deleted = deleted,
Changed = changed
};
}
I don't think you can get that info from your Windows 8 app. Your best bet is to query the folders and files asynchronously and compare the info to that stored in the database. See one example of enumerating folders and files here. I know this is not very efficient for what you are trying to do. If you find any other better ways, please share.
You can use the StorageFileQueryResult and its ContentsChanged event to be notified on changes on a folder and its subfolders. However the event does not contain any information about what actually changed, so you need to re-parse the folder and check if anything you're interested in has been modified.
This works for me:
public async void ListenAsync() {
query = storageFolder.CreateFileQuery();
query.ContentsChanged += query_ContentsChanged;
var files = await query.GetFilesAsync();
}
void query_ContentsChanged(IStorageQueryResultBase sender, object args) {
// args has no info about what changed. check manually
}

How to get a deep link of my application from the Windows Phone Marketplace using .NET code?

How do I get a deep link of my application programmatically from the Windows Phone Marketplace, so that I can use it in my code?
Getting the AppDeeplink is quite useful for example in ShareStatusTask and ShareLinkTask.
It is possible, however you have to use some non-trivial code for getting the real AppID from within your app Manifest file. Here's what I do:
First save somewhere in resources the string for Windows Phone app deeplinks, this is simple:
"http://windowsphone.com/s?appId={0}"
Then you have to find the real AppId by opening the App Manifest file and finding the proper tag, I use this code inside my MarketplaceHelper for doing so:
static MarketplaceHelper()
{
try
{
// load product details from WMAppManifest.xml
XElement app = XElement.Load("WMAppManifest.xml").Descendants("App").Single();
Title = GetValue(app, "Title");
Version = new Version(GetValue(app, "Version"));
Author = GetValue(app, "Author");
Publisher = GetValue(app, "Publisher");
Description = GetValue(app, "Description");
// remove the surrounding braces
string productID = GetValue(app, "ProductID");
ProductID = Regex.Match(productID, "(?<={).*(?=})").Value;
}
catch (Exception e)
{
// should not happen, every application has this field and should containt the ProductID and Version
}
}
private static string GetValue(XElement app, string attrName)
{
XAttribute at = app.Attribute(attrName);
return at != null ? at.Value : null;
}
If the Manifest is there and is properly formatted, and it should be, otherwise the app won't work, you can get this way any data you want.
Now you can construct the deeplink like this:
string deeplink = string.Format(AppResources.DeepLinkFormat, MarketplaceHelper.ProductID);

Windows 8 Metro App MediaElement.SetSource (can not change the volume during playback)

I am making Windows 8 Metro style app.
I want to be able to run different sounds at the same time and manage them. For this goals I have created MediaPlayService which should contain methods which allow me to do that.
I found one issue that after "_mediaElement.SetSource()" I can not change volume. I am calling SetVolume and nothing happen.
Initialize(sound);
SetVolume(100);
Play(); --- this sequence works
Initialize(sound);
Play();
SetVolume(100); --- does not work (I can not change the volume during playback)
public void SetVolume(int volume)
{
//_m ediaElement.Volume = Math.Round((double)((double)volume / 100), 2);
double dvolume = Math.Round((double)((double)volume / 100), 2);
_mediaElement.SetValue(MediaElement.VolumeProperty, dvolume);
}
string _mediaPath;
public void Initialize(Sound sound)
{
_mediaElement = new MediaElement();
_mediaPath = sound.FilePath;
_mediaElement.AudioCategory = Windows.UI.Xaml.Media.AudioCategory.Communications;
_mediaElement.IsLooping = true;
_mediaElement.MediaFailed += _mediaElement_MediaFailed;
_mediaElement.RealTimePlayback = true;
}
public async void Play()
{
var pack = Windows.ApplicationModel.Package.Current;
var installedLoction = pack.InstalledLocation;
var storageFile = await installedLoction.GetFileAsync(_mediaPath);
if (storageFile != null)
{
var stream = await storageFile.OpenAsync(Windows.Storage.FileAccessMode.Read);
_mediaElement.SetSource(stream, storageFile.ContentType);
_mediaElement.Play();
}
}
Your MediaElement isn't part of the VisualTree of your page. As consequence you have to deal with those strange behaviors like setting the volume or position won't work correctly.
As solution you might create the MediaElement in your XAML file or add it from your code-behind to the VisualTree (something like contentGrid.Children.Add( _mediaElement ). In the latter case you probably have to remove it before navigating to another page else it might happen that it won't play the next time you are navigating back.