Share Common AppResource Strings With Android Accessibility Service - xamarin

I share translations for my iOS and Android apps through a common PCL that has AppResources.resx files. I access my resource strings in C# code like AppResources.MyString.
This has worked well up until now, when I have introduced an accessibility service into my android app.
With the accessibility service, I need to provide a description. The only documentation I can find always shows this description being set in the accessibilityservice.xml file such as:
<?xml version="1.0" encoding="utf-8" ?>
<accessibility-service xmlns:android="http://schemas.android.com/apk/res/android"
android:accessibilityEventTypes="typeWindowStateChanged|typeWindowContentChanged"
android:accessibilityFeedbackType="feedbackSpoken"
android:accessibilityFlags="flagDefault"
android:notificationTimeout="100"
android:canRetrieveWindowContent="true"
android:description="#string/accessibility_service_description" />
Which is bound to the service like:
[Service(Permission = "android.permission.BIND_ACCESSIBILITY_SERVICE", Label = "MyApp")]
[IntentFilter(new string[] { "android.accessibilityservice.AccessibilityService" })]
[MetaData("android.accessibilityservice", Resource = "#xml/accessibilityservice")]
public class AutofillService : AccessibilityService
{
...
}
Obviously I cannot access AppResources.MyAccessibilityDescString from the accessibilityservice.xml file, so how do I provide my translatable AppResources string to the accessibility service description?
I would hate to have to manage other android specific strings in the android project only instead of having a common place my translators can set all strings for the app (AppResources.resx).

You can not get the AppResources.resx content in xml file. And unfortunately the Description property of AccessibilityServiceInfo is read only. So you can not set the value by SetServiceInfo method.
The only option I can think of is to add the description string in the String.xmlfile.

Related

Logging via TraceSource in Xamarin (UWP)

I just want to log to console and to a log file, using a standard TraceSource, in my Xamarin app that will run on UWP, Mac OS X, iOS and Android. I'm developing/debugging on UWP.
TraceSource, TraceListener, and TextWriterTraceListener are indeed all available in .Net Standard library, so perhaps I'm setting it up incorrectly? Most places on the Internet insist on setting up trace listeners in an app.config file, but this is not applicable nor possible for Xamarin apps. So here is my logging initialization code, mostly based on an example in Microsoft docs:
private void SetupLogging()
{
Trace.Listeners.Add(new TextWriterTraceListener(Console.Out, "consoleTraceListener"));
string logFilePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), "Application.log");
if (!File.Exists(logFilePath)) File.Create(logFilePath);
var logFileTraceListener = new TextWriterTraceListener(logFilePath, "logFileTraceListener");
Trace.Listeners.Add(logFileTraceListener);
Trace.Write("Test");
Trace.TraceInformation("Logging Initialized. Log file location: " + logFilePath);
Trace.Flush();
}
When I run this in a Xamarin UWP app, a file is created but nothing is written to it, nor can I find anything in the Output of the program (there is no ConsoleTraceListener so I'm trying to write a TextWriterTraceListener to Console.Out). Can someone provide a working example for Xamarin? (I haven't tried the Android or iOS apps yet; want to get UWP on the local machine working first.)
The problem is that you passed wrong string parameter to TextWriterTraceListener method. Please try to pass Stream parameter. You could use following code directly. by the way, you'd better use LocalApplicationData SpecialFolder that could be accessed successfully within uwp.
private void SetupLogging()
{
Trace.Listeners.Add(new TextWriterTraceListener(Console.Out, "consoleTraceListener"));
string logFilePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "Application.log");
if (!File.Exists(logFilePath))
{
File.Create(logFilePath);
}
var logFileTraceListener = new TextWriterTraceListener(File.Open(logFilePath,FileMode.Open), "logFileTraceListener");
Trace.Listeners.Add(logFileTraceListener);
Trace.Write("Test");
Trace.TraceInformation("Logging Initialized. Log file location: " + logFilePath);
Trace.Flush();
}

Xamarin Forms - Image doesn't show up on Lumia

I implemented a Xamarin App with UWP Platform as target.
I added 4 images in the Assets of PCL and set Build Action = Embedded Resource on each. No image has been added on UWP project.
If I run the app on my laptop everything works great, instead when I run the same app on my Lumia no image shows up. I don't understand why, since the app is the same with the only difference of Target Platform, x64/x86 for my laptop and ARM for my Lumia.
I have also tried to set Copy to output Directory = Copy Always for each image, but without success.
Have you tried in another plaftorm (Droid, iOs?)
Like mentionned in the documentation: https://developer.xamarin.com/guides/xamarin-forms/user-interface/images/, you need to:
1) Use a custom MarkupExtension to load image from EmbeddedResource:
[ContentProperty ("Source")]
public class ImageResourceExtension : IMarkupExtension
{
public string Source { get; set; }
public object ProvideValue (IServiceProvider serviceProvider)
{
if (Source == null)
{
return null;
}
// Do your translation lookup here, using whatever method you require
var imageSource = ImageSource.FromResource(Source);
return imageSource;
}
}
2) Use this Custom Markup Extension and provide the fully qualified name of your image (namespace + name)
<Image Source="{local:ImageResource MyProject.Assets.Images.beach.jpg}" />
Just found the solution, disable "Compile with .NET Native tool chain".
https://stackoverflow.com/a/37352400/2297037
Do you know something about possible side effects?

How can I get Android and iPhone IMEI number using Xamarin.forms

I am developing an Xamarin.forms application, I need to catch the imei number of mobile that is using the application. I am aware of how it is done in Android. But how can I do the same in Xamarin.forms. Please educate me.
There is no 'Forms-way' of doing this. If you know how on Android you can make use of the DependencyService. Which means in your shared project create an interface like:
public interface IImeiService
{
string GetImei();
}
Now in your Android project implement this interface, so it would be something like:
public class ImeiService : IImeiService
{
public string GetImei()
{
// ... Implement your Android code here
}
}
Register your Android code with an attribute on the class above the namespace
[assembly: Xamarin.Forms.Dependency (typeof (ImeiService))]
namespace ImeiApp.Droid {
You can now access it, back in your shared code, with:
var imei = DependencyService.Get<IImeiService>().GetImei();
If you would have an iOS implementation you could repeat the same steps, although you can, of course, use the same interface and call in shared code, so you will only need a iOS specific implementation.
However, since iOS 7 Apple disallows access to this kind of information programmatically, so you cannot get the IMEI number. And if you can, you will use code that will not be allowed through the App Store review process.

How to pass data when calling another Windows-Phone App?

I am starting in WP development but I already got the following situation.
I have my app and I need other apps to call it passing data/parameters that I will specify.
For example:
App X will call and open my app, passing parameters like id, name and age.
Is there any way to do it?
Define a URI association for your app.
To do so add content like this to the app's manifest file:
<Extensions>
<Protocol Name="myapp" NavUriFragment="encodedLaunchUri=%s" TaskID="_default" />
</Extensions>
Define a class that derives from UriMapperBase to handle incoming URIs and register right after the call to RootFrame.Navigated + = /*...*/ by doing this:
RootFrame.UriMapper = new MyPersonalUriMapper();
Other apps can open your app by doing something like this:
Windows.System.Launcher.LaunchUriAsync(new System.Uri("myapp:4711/Luciano/24"));
You can parse this URI in your UriMapper to open the page you wanted with ID=4711, Name=Luciano and Age=24.

Windows Phone: Navigate between apps

I have an app that needs to include a links to a second app in the same phone.
If the app is not installed the link should point to the windows store to install it (that part is working fine).
But if the app is already installed the link should go straight to the app and open it. How can I do that?
The app has two versions one form WP7 and other from WP8. if the solution is different for them please point the difference.
Thanks for the help...
I believe a URI Association is what you want. You should be able to create a different association in your WP7 app and in your WP8 app, and handle them accordingly.
A URI association allows your app to automatically launch when another app launches a special URI.
Also note:
If you are interested only in launching your own apps, consider using
APIs from the Windows.Phone.Management.Deployment namespace. You can
use this API to check for other apps that you’ve published, and then
launch them if they’re installed.
You basically just need to update the WMAppManifest.xml file to include the URI Association and then listen for that URI. Example:
<Extensions>
<Protocol Name="contoso" NavUriFragment="encodedLaunchUri=%s" TaskID="_default" />
</Extensions>
Then you can use a custom URI Mapper to handle your association (full example in top link above):
public override Uri MapUri(Uri uri)
{
tempUri = System.Net.HttpUtility.UrlDecode(uri.ToString());
// URI association launch for contoso.
if (tempUri.Contains("contoso:ShowProducts?CategoryID="))
{
// Get the category ID (after "CategoryID=").
int categoryIdIndex = tempUri.IndexOf("CategoryID=") + 11;
string categoryId = tempUri.Substring(categoryIdIndex);
// Map the show products request to ShowProducts.xaml
return new Uri("/ShowProducts.xaml?CategoryID=" + categoryId, UriKind.Relative);
}
// Otherwise perform normal launch.
return uri;
}
Hope this helps!
Is the secondary app one that you have created? If so, do something like this:
IEnumerable<Package> packages = InstallationManager.FindPackagesForCurrentPublisher();
foreach (Package package in packages)
{
if (package.Id.ProductId.ToString().ToLower() == "product id of secondary app")
{
//Launch the app
package.Launch();
}
}
Make sure that your publisher ids match in the WMAppManifest for both apps.
If this secondary app was published by someone else, you'll need to use a custom Uri schema. The app needs to have this feature added by the developer, you can't just launch any app.

Resources