Xamarin/Android - Issue reading locally stored photo from camera - no read access - c#

I'm trying to create a simple test app to take photos in Android, using Xamarin. When I get this app working (or so I hope), i'll use the code in a real app that I'm working on. I'm using the following recipe from Xamarin as my basis:
http://docs.xamarin.com/recipes/android/other_ux/camera_intent/take_a_picture_and_save_using_camera_app/
The major difference is that I need to store images locally, and not on the SD card. I'm able to successfully take a picture (with the Android simulator). I can see the file in the file structure using ADB and can successfully copy and open the file on my PC. However, I'm unsuccessfull in accessing the file in the app, probably due to user rights.
Please note that I was successfull in creating my own .txt files, and reading them back using either System.IO and Java.IO.
Please review the following code. My app crashes when using "System.IO.File.ReadAllText" and gives me "Access to the path "/data/data/CameraAppDemo.CameraAppDemo/files/photo.jpg" is denied.". And whatever I try (absolute, relative paths, uri's), objBitmap is always null.
ADB says that "photo.jpg" has -rwxrwx--- rights, and though I'm not entirely sure, I think that should be more than sufficient
On the other hand, maybe the intent still has a lock on "photo.jpg"? Or something else is going on...
And one final note, I'm using System.IO.File.ReadAllText just for testing purposes. I experimented with stream readers as well, but with the same result. Also, though I believe this step is unnecessary, I enabled "WriteExternalStore" in the Manifest
namespace CameraAppDemo
{
using System;
using System.Collections.Generic;
using Android.App;
using Android.Content;
using Android.Content.PM;
using Android.Graphics;
using Android.OS;
using Android.Provider;
using Android.Widget;
using Java.IO;
using Environment = Android.OS.Environment;
using Uri = Android.Net.Uri;
[Activity(Label = "Camera App Demo", MainLauncher = true)]
public class MainActivity : Activity
{
private File _file;
private string _basePath;
private ImageView _imageView;
protected override void OnActivityResult(int requestCode, Result resultCode, Intent data)
{
base.OnActivityResult(requestCode, resultCode, data);
var objBitmap = BitmapFactory.DecodeFile(_file.AbsolutePath) ;
Console.WriteLine ("objBitmap = null : " + (objBitmap == null).ToString ());
var strOutput = System.IO.File.ReadAllText (FileManager.BasePath + "/photo.jpg");
Console.WriteLine (strOutput);
}
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
SetContentView(Resource.Layout.Main);
FileManager.SetupFolderStructure();
if (IsThereAnAppToTakePictures())
{
Button button = FindViewById<Button>(Resource.Id.myButton);
_imageView = FindViewById<ImageView>(Resource.Id.imageView1);
button.Click += TakeAPicture;
}
}
private bool IsThereAnAppToTakePictures()
{
Intent intent = new Intent(MediaStore.ActionImageCapture);
IList<ResolveInfo> availableActivities = PackageManager.QueryIntentActivities(intent, PackageInfoFlags.MatchDefaultOnly);
return availableActivities != null && availableActivities.Count > 0;
}
private void TakeAPicture(object sender, EventArgs eventArgs)
{
System.IO.Directory.Delete (FileManager.BasePath, true);
_basePath = FileManager.BasePath;
_file = new Java.IO.File (_basePath, "photo.jpg");
Intent intent = new Intent(MediaStore.ActionImageCapture);
intent.PutExtra(MediaStore.ExtraOutput, Uri.FromFile(_file));
StartActivityForResult(intent, 0);
}
}
}
//Part of the FileManager class:
using System;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using Android.Graphics;
namespace CameraAppDemo
{
public class FileManager
{
public static string BasePath {
get {
var libraryPath = Environment.GetFolderPath (Environment.SpecialFolder.Personal);
if (Directory.Exists (libraryPath) == false) {
Directory.CreateDirectory (libraryPath);
}
return libraryPath;
}
}
}
}
==== Edit ====
It seems that I'm simply not able to read the file. As an ex-webdeveloper, I'm fairly new to programming for mobile, let alone the combo of C# and Java and I'm still learning a lot.
Anyway, I added the following lines:
Console.WriteLine("Setting file :" + _file.SetReadable (true));
Console.WriteLine("Can read :" + _file.CanRead());
Both cases return False. I can't read the file, and I am unable to give read access.
So, any ideas? Is this by design? Can I tell the Intent for taking images to give me read access, or is there another workaround?
If everything fails, I'm hoping to workaround the problem by saving to the SD card first and then copying the file to the local filesystem. But that's something I rather would not do; I can't guarantee that the end users have an SD card, and the pictures should not be deleted by accident.

Related

Selenium C# NUnit how to take and save screenshot of failed test into the folder

I am new at Selenium and came up with an issue - how to take and save screenshot into the specific folder. I am using Selenium+C#+NUnit bond.
Have read many information on this but most of them is on - how to capture screenshot and add it to html file. But this is not what I need.
I need the screenshot file to be save into a folder so when I'm running Pipeline in AzureDevOps the "Tests results" block contain this screenshot as well and display it.
I was using this part of the code. The test runs and fails, but no screenshot was make
[OneTimeTearDown]
public void OneTimeTearDown()
{
if (TestContext.CurrentContext.Result.Outcome != ResultState.Failure)
{
var screenshot = ((ITakesScreenshot)driver).GetScreenshot();
var filePath = "pathToTheFolder\\Screenshots\\";
screenshot.SaveAsFile(filePath, Png);
}
}
Maybe someone can help on this and maybe share the knowledge and the code as well)
Thank you all!
Try
using System.Drawing; //add this using statement
[OneTimeTearDown]
public void OneTimeTearDown()
{
if (TestContext.CurrentContext.Result.Outcome != ResultState.Failure)
{
var screenshot = ((ITakesScreenshot)driver).GetScreenshot();
var filePath = "pathToTheFolder\\Screenshots\\";
screenshot.SaveAsFile(filePath + System.Drawing.Imaging.ImageFormat.Png);
}
}
This tutorial looks like what you need
Found a way how to reach out my goal - to save screenshots for failed tests in a bin folder of the project and attach them to the Pipeline "Test Result" section in further.
This is the final workable code. I have removed it from [OneTimeTearDown] and set it to [TearDown]. And also have added attachment with the last row, that allows to sent screenshots to Pipelines "Test result" block.
This is my Base.cs file where I am locating IWebDriver, all Setup and TearDown methods
using E2E_Tests.TestData;
using OpenQA.Selenium.Firefox;
using OpenQA.Selenium;
using WebDriverManager.DriverConfigs.Impl;
using OpenQA.Selenium.Chrome;
using System.Configuration;
using NUnit.Framework.Interfaces;
[TearDown]
public void TearDown()
{
TakeScreenshotDefaultImageFormat();
driver.Close();
}
public void TakeScreenshotDefaultImageFormat()
{
if (TestContext.CurrentContext.Result.Outcome == ResultState.Error)
{
var screenshot = ((ITakesScreenshot)driver).GetScreenshot();
var screenshotDirectoryPath = Path.Combine(TestContext.CurrentContext.TestDirectory, "Screenshots\\");
if (!Directory.Exists(screenshotDirectoryPath))
{
Directory.CreateDirectory(screenshotDirectoryPath);
}
var currentDate = DateTime.Now;
var filePath = $"{screenshotDirectoryPath}{TestContext.CurrentContext.Test.Name}_{currentDate.ToString("yyyy.MM.dd-HH.mm.ss")}.png";
screenshot.SaveAsFile(filePath);
TestContext.AddTestAttachment(filePath);
}
}

UWP SharpCompress Access Exception On Local Drives, Why?

I'm trying to use SharpCompress to read .rar files from my UWP application. It works fine on network shares from which I can read the archive no problem, but I get System.UnauthorizedAccessException on files anywhere on the local system including for instance USB drives. I have access to the files by other methods e.g. StorageFile. It makes no difference whether BroadFileSystemAccess is on or off. I've tried in both C# and Vb.net Here's the code of my test app in C#. The exception occurs at ArchiveFactory.Open.
I can also read Zip files no problem using the .net Compression methods but they can't do rar files, hence needing SharpCompress.
using System;
using System.IO;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using SharpCompress;
using Windows.Storage.Pickers;
using Windows.Storage;
using SharpCompress.Archives;
namespace TestRAR
{
public sealed partial class MainPage : Page
{
public MainPage()
{
this.InitializeComponent();
OpenRAR.Click += OpenRAR_Clicked;
}
public async void OpenRAR_Clicked(object sender, RoutedEventArgs e)
{
FileOpenPicker picker = new FileOpenPicker();
picker.FileTypeFilter.Add(".rar");
picker.FileTypeFilter.Add(".cbr");
picker.FileTypeFilter.Add(".cbz");
picker.FileTypeFilter.Add(".zip");
StorageFile pickfile = await picker.PickSingleFileAsync();
if (pickfile == null) { return; }
string pth = pickfile.Path;
FileInfo pickInfo = new FileInfo(pth);
try
{
ListRARs.Items.Clear();
using (var Arch = ArchiveFactory.Open(pickInfo))
{
foreach (IArchiveEntry a in Arch.Entries)
{
string thisKey = a.Key;
ListRARs.Items.Add(thisKey);
}
}
}
catch{ }
}
}
}
This is the first time I've used SharpCompress and I'm completely stumped. Any ideas anyone?

Revit IExternal Application Error- doesn't seems to run at all

Should we have something with the External application to properly register the event?
I also tried putting two breakpoints one inside the start module and other inside the Export module.
the first responded and waited for me to continue and the next didn't respond(hope did not run the line)
Also,I had manually tried coping the addin file to the addin location to avoid any post build event error but still doesnt seem to work.
could you tell me what I am I doing wrong here.
Here is the code :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Autodesk.Revit.DB;
using Autodesk.Revit.UI;
using Autodesk.Revit.ApplicationServices;
using Autodesk.Revit.Attributes;
using Autodesk.Revit.UI.Events;
using Autodesk.Revit.DB.Events;
using System.IO;
namespace UserDataSheet
{
[Transaction(TransactionMode.Manual)]
[Regeneration(RegenerationOption.Manual)]
public class UserDataSheetclass : IExternalApplication
{
public Result OnShutdown(UIControlledApplication application)
{
return Result.Succeeded;
}
public Result OnStartup(UIControlledApplication application)
{
try
{
// Register event.
application.ControlledApplication.DocumentOpened += new EventHandler<Autodesk.Revit.DB.Events.DocumentOpenedEventArgs>(ExportLog);
return Result.Succeeded;
}
catch (Exception)
{
return Result.Failed;
}
}
public void ExportLog(object sender, DocumentOpenedEventArgs args)
{
var doc = sender as Document;
var isFamilyDoc = doc.IsFamilyDocument;
// variables to use
string RevitUserName = "";
DateTime OpenTime = new DateTime();
string localUserName = "";
string filename = "";
string filepath = "";
string content = "";
if (isFamilyDoc == false)
{
var IsloggedIn = Autodesk.Revit.ApplicationServices.Application.IsLoggedIn;
if (IsloggedIn == true )//&& doc.IsModelInCloud == true)
{
// use variables
filepath = doc.PathName;
filename = doc.Title;
RevitUserName = doc.Application.Username;
OpenTime = DateTime.Now;
localUserName = System.Environment.MachineName;
}
content = string.Format("Date and time : {0} \n Revit UserName : {1} \n Local PC UserName : {2} \n FileName : {3} \n FilePath : {4} "
, OpenTime.ToString(), RevitUserName, localUserName, filename, filepath);
TaskDialog.Show("Model Open Writer info", "user and file details : \n " + content);
}
var writefilepath = Path.GetTempPath();
var Writefile = writefilepath + "//records.txt";
FileStream fs = new FileStream(Writefile, FileMode.Append);
StreamWriter writer = new StreamWriter(fs);
writer.Write(content);
writer.Close();
File.OpenRead(Writefile);
}
}
}
First of all, you can completely remove the TransactionMode and RegenerationOption. The latter is completely obsolete and does nothing at all anywhere whatsoever. The former is only useful when declaring an external command. It is useless and ignored in the context of an external application.
Secondly, to address your question: you can set a breakpoint in the beginning of OnStartup. If the breakpoint is not hit, your add-in is not being loaded at all. Probably something is wrong with your add-in registration, e.g., in the add-in manifest *.addin file.
Go back to square one, i.e., work through the getting started material and the developer guide instructions on registering and loading a Revit add-in.
If the breakpoint in OnStartup is hit, then your add-in is loading correctly, which means that the add-in manifest *addin file is OK. So, you do not need to worry about that. The VisibilityMode tag is not used for external applications, by the way.
Thanks, Jeremy It worked
Firstly I apologies for adding this as answer( I don't know how to add codes in comment)
It worked when I deleted my Addin file and recreated it may be I had made some mistake in it.
meanwhile I have copied the following code from examples and used it,honestly I did't understand this line of the code.
"public void ExportLog(object sender, DocumentOpenedEventArgs args)"
can you point to a right source that explains this part. I have three questions here :
what object type is sender and args are they of type application?
How do I add a 3rd parameter to this method say I want the user to input a string to name the file the data is copied to.
Can I do this
var newEvent = new EventHandler<Autodesk.Revit.DB.Events.DocumentOpenedEventArgs>(ExportLog);
instead of
application.ControlledApplication.DocumentOpened += new EventHandler<Autodesk.Revit.DB.Events.DocumentOpenedEventArgs>(ExportLog);
why does all example use += is this to register the event every time a new instance of Revit is opened?
Thanks for your help.
You can see the class of sender yourself by setting a breakpoint at the beginning of ExportLog and looking in the debugger.
No, you cannot modify the signature of the event handler. It is predetermined by the Revit API.
Yes.
It sounds to me as if you might save some time and effort for yourself by learning a bit more about the basics of C# and .NET programming in general before continuing to tackle this task.

External Storage for Xamarin on visual studio

I'm currently working on Xamarin using Visual Studio to try and build and create an app that reads a bar code and saves the integer it gets from it in a .txt file. I have managed to make the code both read the bar code and save it however i was wondering if there is a way i could save it in a more accessible file, as right now its saving in internal storage and the only way i can reach it is through adb console.
Is there a way for me to perhaps save the integers on a .txt file on my laptop? I'm currently testing it on my physical phone and its connected to my laptop via a USB cable.
Here is my code:
using Android.App;
using Android.Widget;
using Android.OS;
using System;
using Android.Content;
using ZXing.Mobile;
using System.IO;
namespace Scanner
{
[Activity(Label = "Scanner", MainLauncher = true, Icon = "#drawable/icon")]
public class MainActivity : Activity
{
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
// Set our view from the "main" layout resource
SetContentView (Resource.Layout.Main);
Button buttonScan = FindViewById<Button>(Resource.Id.buttonScan);
TextView scanText = FindViewById<TextView>(Resource.Id.scanText);
var documents = System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal);
var BarcodesFile = Path.Combine(documents, "Barcodes.txt");
buttonScan.Click += async (sender, e) =>
{
MobileBarcodeScanner.Initialize(Application);
var scanner = new ZXing.Mobile.MobileBarcodeScanner();
var result = await scanner.Scan();
if (result != null)
File.AppendAllText(BarcodesFile, "Scanned Barcode: " + result.Text);
scanText.Text = File.ReadAllText(BarcodesFile);
};
}
}
}
So if api is an idea. I have not used any api yet for those requirements but when I think about txt I immediately thought about pastebin.
https://pastebin.com/api enter code here
That might be usefull to check out. Goodluck!;)

C# Project in Visual Studio 2010 for Windows Phone Notefunction

Im trying to get my notefunction to post the current city you are in by using your gps coordinates when saving a note. Right now it's only showing "unknown location". Im kinda lost right now and i have worked so long with this code to try and get it to work so please could anyone tell me what i have done wrong?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using Microsoft.Phone.Controls;
using System.Device.Location;
using System.Text;
using System.IO.IsolatedStorage;
using System.IO;
using Secret.myTerraService;
namespace Secret
{
public partial class AddNotePage : PhoneApplicationPage
{
private IsolatedStorageSettings settings = IsolatedStorageSettings.ApplicationSettings;
private string location = "";
#region Hämtar din geografiska position
public AddNotePage()
{
InitializeComponent();
GeoCoordinateWatcher watcher;
watcher = new GeoCoordinateWatcher(GeoPositionAccuracy.Default)
{
MovementThreshold = 20
};
watcher.PositionChanged += this.watcher_PositionChanged;
watcher.StatusChanged += this.watcher_StatusChanged;
watcher.Start();
}
private void watcher_StatusChanged(object sender, GeoPositionStatusChangedEventArgs e)
{
switch (e.Status)
{
case GeoPositionStatus.Disabled:
// location is unsupported on this device
break;
case GeoPositionStatus.NoData:
// data unavailable
break;
}
}
private void watcher_PositionChanged(object sender, GeoPositionChangedEventArgs<GeoCoordinate> e)
{
var epl = e.Position.Location;
// Access the position information thusly:
epl.Latitude.ToString("0.000");
epl.Longitude.ToString("0.000");
epl.Altitude.ToString();
epl.HorizontalAccuracy.ToString();
epl.VerticalAccuracy.ToString();
epl.Course.ToString();
epl.Speed.ToString();
e.Position.Timestamp.LocalDateTime.ToString();
}
void client_ConvertLonLatPtToNearestPlaceCompleted(object sender, myTerraService.ConvertLonLatPtToNearestPlaceCompletedEventArgs e)
{
location = e.Result;
//throw new NotImplementedException();
}
#endregion
#region Knappfunktioner
private void AppBar_Cancel_Click(object sender, EventArgs e)
{
navigateBack();
}
private void AppBar_Save_Click(object sender, EventArgs e)
{ // spara en ny anteckning
if (location.Trim().Length == 0)
{
location = "Okänd Plats";
}
// skapa namnet på filen
StringBuilder sb = new StringBuilder();
sb.Append(DateTime.Now.Year);
sb.Append("_");
sb.Append(String.Format("{0:00}", DateTime.Now.Month));
sb.Append("_");
sb.Append(String.Format("{0:00}", DateTime.Now.Day));
sb.Append("_");
sb.Append(String.Format("{0:00}", DateTime.Now.Hour));
sb.Append("_");
sb.Append(String.Format("{0:00}", DateTime.Now.Minute));
sb.Append("_");
sb.Append(String.Format("{0:00}", DateTime.Now.Second));
sb.Append("_");
location = location.Replace(" ", "-");
location = location.Replace(", ", "_");
sb.Append(location);
sb.Append(".txt");
//spara filen i Isolated Storage
var appStorage = IsolatedStorageFile.GetUserStoreForApplication();
try
{
using (var fileStream = appStorage.OpenFile(sb.ToString(), System.IO.FileMode.Create))
{
using (StreamWriter sw = new StreamWriter(fileStream))
{
sw.WriteLine(editTextBox.Text);
}
}
}
catch
{
// åtgärda vid senare tillfälle..
}
//Klart Navigera tillbaka till NoteMainPage
navigateBack();
}
When testing this, I can see a few points where your code could break. You should debug with breakpoints to actually confirm that your app is getting GPS location data. If not, use the Windows Phone emulator and run a GPS simulation (and then confirm again).
Next, once you know that your GPS data is coming in and formatted correctly for your Terra Web Service, confirm that the data is actually being sent to the Terra Web Service and that data is being returned from the web service call. If your Terra Web Service is returning "Unknown Location" still, try again but this time plot the GPS location near a major city to increase the odds of the web service knowing what city you are close to. If you are still returning "Unknown Location" then you can be fairly certain that the issue resides with the web service provider.
In my experience with the Windows Phone location services (I've only used dev phones with WiFi access (i.e. no sim)), location data sometimes takes a few seconds or minutes to pickup. If you're testing this on a physical dev phone in a basement or an area with limited access for the GPS to find you, odds are the data isn't being generated. Also, because the Windows Phone location data isn't necessarily instant, you can't always call it on the fly and expect it to have location data ready. In my experience I have had the user opt in to location services (per the Windows Phone Marketplace submission requirements) and then have a background agent pull location data while the user is using the app. That way location data is likely to be ready by the time user would need it (like your example when the user saves the note).
Here's a working example I made for you in C# that will work for your Windows Phone app. The sample is a console app for the sake of simplicity and time. If you can't figure it out still, I'll code it up for Windows Phone. With this though you really have everything you need to make it work, just plug in the lat and long variables. Download Working Source Code (Visual Studio 2010)
C# Source code snippet
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using TerraServiceExample.com.msrmaps; // add the service using statement
// http://msrmaps.com/terraservice2.asmx
namespace TerraServiceExample
{
class Program
{
/// <summary> The main entry point for the application. </summary>
static void Main(string[] args)
{
// Create the GPS point from your location services data
LonLatPt location = new LonLatPt();
// Modify Lat and Lon based on your needs
// This example uses the GPS Coordinates for "Eau Claire, Wisconsin, United States"
location.Lat = 44.811349;
location.Lon = -91.498494;
// Create a new TerraService object
TerraService ts = new TerraService();
// Output the nearest location from the TerraService
Console.WriteLine(ts.ConvertLonLatPtToNearestPlace(location));
// For console app to stay open/close easily
Console.WriteLine("Press any key to close window...");
Console.ReadKey();
// Lastly, appreciate the Microsoft folks that made this available for free
// They are all interesting individuals but you should read about Jim Gray via Wikipedia to
// understand some history behind this cool web service.
}
}
}

Categories

Resources