How to show byte array(byte[]) as file(pdf/doc) in codenameone? - arrays

I am getting response from service as byte array(byte[]). in my app i want to show the file(pdf/doc) in app itself. is it possible? is there any way to save and view the file in codenameone?

Please try this code
String newString = String(byte[] bytes);
For PDF you need to create a file and open it using the native viewer:
FileSystemStorage fs = FileSystemStorage.getInstance();
String fileName = fs.getAppHomePath() + "myPDF.pdf";
try(OutputStream os = fs.openOutputStream(fileName)) {
os.write(myByteArrayData);
}
Display.getInstance().execute(fileName);

Related

UWP how to get access to file in folder

Help me please, I can't get access to file which I choose by FileOpenPicker.
FileOpenPicker openPicker = new FileOpenPicker();
openPicker.ViewMode = PickerViewMode.Thumbnail;
openPicker.SuggestedStartLocation = PickerLocationId.Desktop;
openPicker.CommitButtonText = "Открыть";
openPicker.FileTypeFilter.Add(".xlsx");
var file = await openPicker.PickSingleFileAsync();
using (FileStream fs = new FileStream(file.Path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
{
}
What is wrong?
Because of how UWP sandboxes access to the filesystem, you can't construct a FileStream directly from a StorageFile's path. Instead, you have a few options, in order from simplest to most complex:
1) If your file is small enough, you can just use the helpers in the FileIO static class to read it all at once:
string text = await FileIO.ReadTextAsync(file); // or ReadLinesAsync or ReadBufferAsync, depending on what you need
2) Use the OpenAsync() method on StorageFile:
using (IRandomAccessStream stream = await file.OpenAsync(FileAccessMode.Read, StorageOpenOptions.AllowReadersAndWriters))
{
// your reading code here
}
If you need to, you can convert between IRandomAccessStream and .NET Streams with the AsStream(), AsStreamForRead() and AsStreamForWrite() extension methods on IRandomAccessStream, the docs for which are here.
3) If you want complete control, you can get a SafeFileHandle to the underlying file using CreateSafeFileHandle(), like so:
SafeFileHandle fileHandle = file.CreateSafeFileHandle(FileAccess.Read, FileShare.ReadWrite);
You can then use this file handle to create a standard FileStream:
using (FileStream fs = new FileStream(fileHandle, FileAccess.Read))
{
// Read stuff here
}
This is the only way to reliably use a FileStream on a UWP StorageFile, and should be used with some caution. The official docs have more details on the implications of doing this.
FileOpenPicker gives you a StorageFile which wraps the opened files and gives you permission to it. This doesn't give you access to the file in general - e.g. you cannot use its Path only to open it with a FileStream. Instead, you need to use the respective Windows.Storage APIs to do this. I usually use the OpenStreamForReadAsync extension method. Add using System.IO to the file header and then:
var stream = await file.OpenStreamForReadAsync();
This method returns a System.IO.Stream which you can use with classic System.IO-enabled APIs.
Please avoid use file Path to access file stream in UWP platform, if you have get the file with FileOpenPicker. You could get the file stream with following.
FileOpenPicker openPicker = new FileOpenPicker();
openPicker.ViewMode = PickerViewMode.Thumbnail;
openPicker.SuggestedStartLocation = PickerLocationId.Desktop;
openPicker.CommitButtonText = "Открыть";
openPicker.FileTypeFilter.Add(".xlsx");
var file = await openPicker.PickSingleFileAsync();
if (file != null)
{
var stream = await file.OpenAsync(Windows.Storage.FileAccessMode.Read);
}
And if you need use stream in System.IO namespace. please call AsStream method for IRandomAccessStream object.
var stream = await file.OpenAsync(Windows.Storage.FileAccessMode.Read);
System.IO.Stream iostream = stream.AsStream();
For more detail please refer this official document.

Save file to device with memorystream

I was wondering if it is possible with xamarin.forms to download any type of file to the device.. de files are stored on Azure, i get a Memorystream of the file, its very important for my app. my question excists of 2 parts actually,
how to download de file to the device of the user?,
and how to show the file of Any type in a default application of the type ( like pdf reader)
this is what i tried
MemoryStream memoryStream = AzureDownloader.DownloadFromAzureBlobStorage(null, doc.azure_container, doc.file_path, ref filen, true);
string documentsPath = Environment.GetFolderPath(Environment.SpecialFolder.Personal);
string localFilename = doc.filename;
string localPath = Path.Combine(documentsPath, localFilename);
File.WriteAllBytes(localPath, memoryStream.ToArray()); // this is a try to save to local storage
any help appreciated
how to download the file to the device of the user?
Use PCLStorage as its cross-platform and would work for iOS and Android:
public async Task CreateRealFileAsync()
{
// get hold of the file system
IFolder rootFolder = FileSystem.Current.LocalStorage;
// create a folder, if one does not exist already
IFolder folder = await rootFolder.CreateFolderAsync("MySubFolder", CreationCollisionOption.OpenIfExists);
// create a file, overwriting any existing file
IFile file = await folder.CreateFileAsync("MyFile.txt", CreationCollisionOption.ReplaceExisting);
// populate the file with some text
await file.WriteAllTextAsync("Sample Text...");
}
how to show the file of Any type in a default application of the type
( like pdf reader)
this is too broad and could have several solutions depending on what exactly you want to achieve.
Hope this helps

Writing from persistent data path to streaming asset

I'm trying to get bytes from Application.persistentDataPath to streaming asset and save it as an mp4 file but my code doesnt work.
Here it is :
IEnumerator streamit(){
string filePath ="file:///"+ Path.Combine(Application.persistentDataPath, "Locomotive Part 1.mp4");
Uri uri = new Uri(filePath);
string converted = uri.AbsoluteUri;
WWW www = new WWW(converted);
Debug.Log (www.error);
yield return www;
using (FileStream fs = new FileStream(Application.persistentDataPath+"/example.mp4", FileMode.Append))
foreach(byte data in www.bytes){
fs.WriteByte (data);
}
}
So what am I doing wrong ? Its not working on both IOS and Mac
Oh, I found my problem.
Everything that doesn't work because of empty spaces on the source path. In IOS, you have to change empty spaces with "%20" whenever you are sending a path.
Thanks Anyway !

How to test Android toast messages in Appium ( selenium Java)

I am using Selenium with Java to run scripts on android (thru Appium server).
I see that it is not possible to locate a toast by using selenium's
driver.findElement(By.LinkText("User not logged in")
in Appium
But can be used in Selendroid to capture toast messages.
I there a way I can use both Selendroid and Appium in the same script?
Finally, we are able to read the toast message without the need of taking screenshots and performing OCR.
I have tested this on Appium 1.15.1.
Toast messages comes under com.package.system.
Normally, Xpath for this will be "/hierarchy/android.widget.Toast".
And, Class Name will be "android.widget.settings"
You can confirm this by refreshing element inspector screen when toast message is displayed.
WebDriverWait waitForToast = new WebDriverWait(driver.25);
waitForToast.until(ExpectedConditions.presenceOfElementLoacted(By.xpath("/hierarchy/android.widget.Toast")));
String toastMessage = driver.findElement((By.xpath("/hierarchy/android.widget.Toast")).getText();
System.out.println(toastMessage);
Method 1: from Appium version 1.6.4 supports toast messages, for that you need to use automationName:'uiautomator2'.
toast = driver.find_element(:xpath, "//android.widget.Toast[1]")
if toast.text == "Hello"
But i don't recommend this because uiautomator2 is not stable yet.
Method 2:
Trigger text message on the screen
Capture screenshots
Convert image to text file
def assettoast(string)
sname = (0...8).map { (65 + rand(26)).chr }.join
$driver.driver.save_screenshot("#{sname}")
# Make sure tesseract is installed in the system. If not you can install using "brew install tesseract" in mac
system ("tesseract #{sname} #{sname}")
text_file="#{sname}.txt"
var= get_string_from_file(string, text_file)
raise if var != true
end
Check whether toast message is there in text file
def get_string_from_file(word, filename)
File.readlines(filename).each do |line|
return true if line.include?(word)
end
end
Looks like you can't switch driver type within same session.
If you trying to switch to Selendroid only for toast verification - you could use OSR image recognition engine.
Check this answer w/ Ruby bindings
Idea is quite simple:
make toast message to appear
take few screenshots
iterate over taken screenshots and look for required text
Here is nice and simple example of OCR usage in Java: tess4j example (make sure that Tesseract engine installed)
Step 1:
File scrFile=null;
String path1 = null;
BufferedImage originalImage=null;
BufferedImage resizedImage=null;
System.out.println("Starting\n\n\n\n");
scrFile = ((TakesScreenshot) appiumDriver).getScreenshotAs(OutputType.FILE);
System.out.println("after scrfile\n\n\n\n");
originalImage = ImageIO.read(scrFile);
System.out.println("after originalFile\n\n\n");
BufferedImage.TYPE_INT_ARGB : originalImage.getType();
resizedImage = CommonUtilities.resizeImage(originalImage, IMG_HEIGHT, IMG_WIDTH);
ImageIO.write(resizedImage, "jpg", new File(path + "/"+ testCaseId + "/img/" + index + ".jpg"));
Image jpeg = Image.getInstance(path + "/" + testCaseId + "/img/"+ index + ".jpg");
Step 2:
BufferedImage pathforToast= original image;
Step 3:
System.setProperty("jna.library.path","C:/Users/Dell/workspace/MOBILEFRAMEWORK/dlls/x64/");
Tesseract instance = Tesseract.getInstance();
`enter code here`ImageIO.scanForPlugins();
String result=null;
result = instance.doOCR(pathforToast);`enter code here`
System.out.println(result);`enter code here`
Appium 1.6.4#beta latest version supports toast messages
Take screen shot of Toast Message page and try to convert the image file in to Text and verify the text using the below code.
public void imageconversion(String filePath) throws IOException,
{
ITesseract instance = new Tesseract();
//file path is the image which you need to convert to text
File imageFile = new File(filePath);
BufferedImage img = null;
img = ImageIO.read(imageFile);
BufferedImage blackNWhite = new BufferedImage(img.getWidth(),img.getHeight(), BufferedImage.TYPE_BYTE_BINARY);
Graphics2D graphics = blackNWhite.createGraphics();
graphics.drawImage(img, 0, 0, null);
//path where your downloaded tessdata exists
instance.setDatapath("E://ocr//data");
//What language you required to convert,( e.g. English)
instance.setLanguage("eng");
String result = instance.doOCR(blackNWhite);
System.out.println(result);
}
Appium Directly does not give any API to read toast message we need to do it using tess4j jar. First we need to take screen shot and then we need to read the text from screen shot using tess4j API.
static String scrShotDir = "screenshots";
File scrFile;
static File scrShotDirPath = new java.io.File("./"+ scrShotDir+ "//");
String destFile;
static AndroidDriver driver = null;
public String readToastMessage() throws TesseractException {
String imgName = takeScreenShot();
String result = null;
File imageFile = new File(scrShotDirPath, imgName);
System.out.println("Image name is :" + imageFile.toString());
ITesseract instance = new Tesseract();
File tessDataFolder = LoadLibs.extractTessResources("tessdata"); // Extracts
// Tessdata
// folder
// from
// referenced
// tess4j
// jar
// for
// language
// support
instance.setDatapath(tessDataFolder.getAbsolutePath()); // sets tessData
// path
result = instance.doOCR(imageFile);
System.out.println(result);
return result;
}
/**
* Takes screenshot of active screen
*
* #return ImageFileName
*/
public String takeScreenShot() {
File scrFile = ((TakesScreenshot) driver).getScreenshotAs(OutputType.FILE);
SimpleDateFormat dateFormat = new SimpleDateFormat("dd-MMM-yyyy__hh_mm_ssaa");
new File(scrShotDir).mkdirs(); // Create folder under project with name
// "screenshots" if doesn't exist
destFile = dateFormat.format(new Date()) + ".png"; // Set file name
// using current
// date time.
try {
FileUtils.copyFile(scrFile, new File(scrShotDir + "/" + destFile)); // Copy
// paste
// file
// at
// destination
// folder
// location
} catch (IOException e) {
System.out.println("Image not transfered to screenshot folder");
e.printStackTrace();
}
return destFile;
}
For more details Refer this video - https://www.youtube.com/watch?v=lM6-ZFXiSls
I found three ways to capture a Toast message and verify them.
To get the page source and verify the toast message from it.
public void verifyToastMessageUsingPageSource(String toastmsg) throws InterruptedException {
boolean found = false;
for(int i =0 ; i <8; i++){
if(getDriver().getPageSource().contains("class=\"android.widget.Toast\" text=\""+toastmsg+"\"")){
found = true;
break;
}
Thread.sleep(300);
}
Assert.assertTrue(found,"toast message "+toastmsg+" is present");
}
Similar can be found using Xpath: //android.widget.Toast[1]
Using the grep command, wait for a toast message in uiautomator events.
run the command before clicking and toast message will be varified.
adb shell uiautomator events | grep "ToastMessgae"
This is tricky and needs more code to run.
start capturing screenshots thread.
perform click action
stop screen capturing thread.
extract text from the captured images using OCR and verify the toast message is present in the captured images.
I prefer the 1st and 2nd option, it provides validation in less time with less code.
comment if you need code for 2nd and 3rd point.
Appium with version number>=1.6.4 supports toast notification with UiAutomator2.
In Javascript with webdriver you can do like this
let toast=await driver1.elements("xpath","/hierarchy/android.widget.Toast");
let data=await toast[0].text();
console.log(data)

how to download an attachment in browser?

I'm using the Gmail API in browser and want to allow the user to download email attachments. I see https://developers.google.com/gmail/api/v1/reference/users/messages/attachments/get but it returns JSON and base64 data. I don't think I can get that data in memory then trigger a "download" to save the file locally. Even if I could I don't think it would be efficient - it would probably download the file in memory vs. streaming it to a file. I think I need a direct link to a file that returns the correct file name and raw binary data (not base64). Is there a way to do this? Right now the only way I see is to proxy requests.
You can get the data from the base64 and save it to file locally.
If you are getting the attachment in Java, you can use the FileOutputStream class (or f.write() in Python) to write the bytes to file and save it locally with a path.
You can try with the following sample code from Google Developer page:
public static void getAttachments(Gmail service, String userId, String messageId)
throws IOException {
Message message = service.users().messages().get(userId, messageId).execute();
List<MessagePart> parts = message.getPayload().getParts();
for (MessagePart part : parts) {
if (part.getFilename() != null && part.getFilename().length() > 0) {
String filename = part.getFilename();
String attId = part.getBody().getAttachmentId();
MessagePartBody attachPart = service.users().messages().attachment().
get(userId, messageId, attId).execute();
byte[] fileByteArray = Base64.decodeBase64(attachPart.getData());
FileOutputStream fileOutFile =
new FileOutputStream("directory_to_store_attachments" + filename);
fileOutFile.write(fileByteArray);
fileOutFile.close();
}
}
}

Resources