I am using VS 2017 to create a cross platform (UWP, Android, iOS) Xamarin app. I am trying to show all images from a folder on device as thumbnails (similar to gallery app, sample screenshot attached).
I have looked into WrapLayout sample code provided on Xamarin website (Link), but it's loading all images from internet using JSON
protected override async void OnAppearing()
{
base.OnAppearing();
var images = await GetImageListAsync();
foreach (var photo in images.Photos)
{
var image = new Image
{
Source = ImageSource.FromUri(new Uri(photo + string.Format("?width={0}&height={0}&mode=max", Device.OnPlatform(240, 240, 120))))
};
wrapLayout.Children.Add(image);
}
}
async Task<ImageList> GetImageListAsync()
{
var requestUri = "https://docs.xamarin.com/demo/stock.json";
using (var client = new HttpClient())
{
var result = await client.GetStringAsync(requestUri);
return JsonConvert.DeserializeObject<ImageList>(result);
}
}
I have also looked into Xamarin Media Plugin (Link), but it shows only one image at a time. Sample code -
await CrossMedia.Current.Initialize();
var file = await CrossMedia.Current.PickPhotoAsync();
if (file == null)
return;
MainImage.Source = ImageSource.FromStream(() =>
{
var stream = file.GetStream();
file.Dispose();
return stream;
});
But I am unable to find a way to implement these two (or any other methods) in such a way that I can create my own gallery section in my app.
You need to create an Activity in your specific platform. This activity will be launched as an intent throught your PCL project using, for instance, Dependency Services.
In this custom Activity you should have a GridView which fills its source from the current directory if the file fits your restrictions, such a specific extension, size, etc.
Finally, to get the selected image you just send the image path or whatever you need to the PCL project with DependencyService.
I am creating a Cortana skill on the Cortana canvas, I have a button.
I wanted to know if it possible to have an 'imback' type of button to open a webpage.
Ye, for example
var message = context.MakeMessage() as IMessageActivity;
message.ChannelData = JObject.FromObject(new
{
action = new { type = "LaunchUri", uri = "skype:echo123?call" }
});
await context.PostAsync(message);
this code will start a call with echo123 user on skype
Reference: https://learn.microsoft.com/en-us/cortana/tutorials/bot-skills/bot-entity-channel-data
You can supply an openUrl to a card action, or even use ChannelData to send a LaunchUri command, deep linking to an application. (I haven't tried this, but I assume 'http://websitename.com' will launch in the Cortana host platform's default browser.)
activity.ChannelData = new {
action = new { type = "LaunchUri", uri = "http://websitename.com"}
};
i'm trying to open app store application programmatically in my app.
what i'm trying to do is that i'm calling a service to check at the current app version and if it needs update i should open app store application to let the user update the my app.
note: the app not published yet to the store, i'm still in coding phase.
i tried to use the following code in ViewDidLoad method, but it's not working (nothing happened):
var nsurl = new NSUrl("itms://itunes.apple.com");
UIApplication.SharedApplication.OpenUrl(nsurl);
A direct link via itms: will only work in an actual device, if you are testing on a simulator, use https://itunes.apple.com/us/genre/ios/id36?mt=8 instead.
I would recommend using itms:// link on the actual device as it prevents the redirects that user sees when using a https:// link to open iTunes.
bool isSimulator = Runtime.Arch == Arch.SIMULATOR;
NSUrl itunesLink;
if (isSimulator)
{
itunesLink = new NSUrl("https://itunes.apple.com/us/genre/ios/id36?mt=8");
}
else
{
itunesLink = new NSUrl("itms://itunes.apple.com");
}
UIApplication.SharedApplication.OpenUrl(itunesLink, new NSDictionary() { }, null);
Instead of opening the external Store app on the device, you might want to consider keeping the user inside of your app by using a SKStoreProductViewController:
bool isSimulator = Runtime.Arch == Arch.SIMULATOR;
if (!isSimulator)
{
var storeViewController = new SKStoreProductViewController();
storeViewController.Delegate = this;
var id = SKStoreProductParameterKey.ITunesItemIdentifier;
var productDictionaryKeys = new NSDictionary("SKStoreProductParameterITunesItemIdentifier", 123456789);
var parameters = new StoreProductParameters(productDictionaryKeys);
storeViewController.LoadProduct(parameters, (bool loaded, NSError error) =>
{
if ((error == null) && loaded)
{
this.PresentViewController(storeViewController, true, () =>
{
Console.WriteLine("SKStoreProductViewController Completed");
});
}
if (error != null)
{
throw new NSErrorException(error);
}
});
}
else
{
var itunesLink = new NSUrl("https://itunes.apple.com/us/genre/ios/id36?mt=8");
UIApplication.SharedApplication.OpenUrl(itunesLink, new NSDictionary() { }, null);
}
NSBundle.MainBundle.InfoDictionary["CFBundleVersion"]
Returns you the current app version.
To open the Apple Appstore just let the user navigate to the appstore link, Apple will automaticly detect that the user is using an iPhone and will open the Appstore for them.
Test yourself:
Open the following link in safari: Whatsapp in the Appstore
It will automatically open the appstore.
When you create app on iTunesConnect you can get url to your future app in AppStore even if you didn't release it yet. You can find it under App Information tab:
In your app you can just open it:
var nsurl = new NSUrl("https://itunes.apple.com/us/app/mygreatapp/id123456789");
UIApplication.SharedApplication.OpenUrl(nsurl);
In my company, we want to distribute an android app for only internal users.
We have one Google apps account (admin account) with our own company's domain name (xyz#sample.com).
We have other employee's email id with the company domain name(xyz#sample.com) and these are not under the Google apps.
Do we need the same Google apps account for all the employees under Google apps admin? As we need to make the app downloadable to all the internal employees too.
OR
Is it possible to make the android app downloadable with our own server's created email ids.
For Google APP account, do we need to pay Rs.150/employee/month?
EDIT:
I do not want to publish my android app on other play store where Google can not interfere.Is there any store? I have searched and found that there are many stores available but which is trustworthy.
All you need is your app available on the web for a common download. After in android, you need to download the apk and notify the user to update.
Below is the code I use to download the .apk and install it.
public void UpdateApk(){
String nameapk = "youapp.apk";
String urlDownload = "http://youserver/" + nameapk;
HttpURLConnection conn = (HttpURLConnection) new URL(urlDownload).openConnection();
conn.setDoInput(true);
conn.setConnectTimeout(20000);
conn.connect();
InputStream is = conn.getInputStream();
String PATH = Environment.getExternalStorageDirectory() + "/download/";
File file = new File(PATH);
file.mkdirs();
File outputFile = new File(file, nameapk);
FileOutputStream fos = new FileOutputStream(outputFile);
byte[] buffer = new byte[1024];
int len1 = 0;
while ((len1 = is.read(buffer)) != -1) {
fos.write(buffer, 0, len1);
}
fos.close();
is.close();
// till here, it works fine - .apk is download to
// sdcard in download file
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.fromFile(new File(Environment.getExternalStorageDirectory() + "/download/" + nameapk)), "application/vnd.android.package-archive");
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
youcontext.startActivity(intent);
}
To check the version of the app, see this answer:
https://stackoverflow.com/a/14313280/185022
Is there a way to detect if a particular file that is being downloaded is a Gmail attachment?
I am looking for a way to write a Greasemonkey script which would help me organize the downloads, based on their download sources, say Gmail email attachments would have a different behavior from other stuff.
So far, I've found out that attachments redirect to https://mail-attachment.googleusercontent.com/attachment/u/0/ , which I guess is not sufficient.
EDIT
Since an add-on would be more powerful than a userscript, I've decided to pursue the Add On idea. However, the problem of detection remains unsolved.
This is too complicated for just one question; it has at least these major parts:
Do you want to redirect downloads when the user clicks, or automatically download select files? Clarify the question.
Your GM script must identify the appropriate download links, and on which pages, and for which views? For gMail, this is not a trivial task, and the question needs to be clearer. It's worthy of a whole question just on this issue given the variety of views and AJAX involved.
Once identified, the script probably needs to intercept clicks on those links. (Depends on your goal (clarify!) and what the Firefox extension can do.)
Greasemonkey needs to interact with an extension that either intercepts the user-initiated download, or allows for an automatic download. I've detailed the auto-download approach, below.
Once your script has identified the appropriate file URLs and/or links (Open a new question for more help with that, and include pictures of the types of pages and links you want.), it can interface with a Firefox add-on, like the one below, to automatically save those files.
Automatically saving files from Greasemonkey with the help of an additional Add-on:
WARNING: The following is a working proof of concept for education only. It has no security features, and if you use it as-is, for actual surfing, some webpage or script writer or extension writer will use it to completely pwn your computer.
If you use the Add-on builder or SDK to install or "Test" the DANGER. DANGER. DANGER. File download utility,
Then you can use a Greasemonkey script, like this, to automatically save files:
// ==UserScript==
// #name _Call our File download add-on to trigger a file download.
// #include https://mail.google.com/mail/*
// #include https://stackoverflow.com/questions/14440362/*
// #require http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js
// #grant GM_addStyle
// ==/UserScript==
/*- The #grant directive is needed to work around a design change
introduced in GM 1.0. It restores the sandbox.
*/
var fileURL = "http://userscripts.org/scripts/source/29222.user.js";
var savePath = "D:\\temp\\";
var extensionLoaded = false;
window.addEventListener ("ImAlivefromExtension", function (zEvent) {
console.log ("The test extension appears to be loaded!", zEvent.detail);
extensionLoaded = true;
} );
window.addEventListener ("ReplyToDownloadRequest", function (zEvent) {
//var xxxx = JSON.parse (zEvent.detail);
console.log ("Extension replied: ", zEvent.detail);
} );
$("body").prepend ('<button id="gmFileDownloadBtn">Click to File download request.</button>');
$("#gmFileDownloadBtn").click ( function () {
if (extensionLoaded) {
detailVal = JSON.stringify (
{targFileURL: fileURL, targSavePath: savePath}
);
var zEvent = new CustomEvent (
"SuicidalDownloadRequestToAddOn",
{"detail": detailVal }
);
window.dispatchEvent (zEvent);
}
else {
alert ("The file download extension is not loaded!");
}
} );
You can test the script on this SO question page.
Note that any other extension, userscript, web page, or plugin can listen to or send spoof events, the only security, so far, is to limit which pages the extension runs on.
For reference, the extension source files are below. The rest is supplied by Firefox's Add-on SDK.
The content script:
var zEvent = new CustomEvent ("ImAlivefromExtension",
{"detail": "GM, DANGER, DANGER, DANGER, File download utility" }
);
window.dispatchEvent (zEvent)
window.addEventListener ("SuicidalDownloadRequestToAddOn", function (zEvent) {
console.log ("Extension received download request: ", zEvent.detail);
//-- Relay request to extension main.js
self.port.emit ("SuicidalDownloadRequestRelayed", zEvent.detail);
//-- Reply back to GM, or whoever is pretending to be GM.
var zEvent = new CustomEvent ("ReplyToDownloadRequest",
{"detail": "Your funeral!" }
);
window.dispatchEvent (zEvent)
} );
The background JS:
//--- For security, MAKE THESE AS RESTRICTIVE AS POSSIBLE!
const includePattern = [
'https://mail.google.com/mail/*',
'https://stackoverflow.com/questions/14440362/*'
];
let {Cc, Cu, Ci} = require ("chrome");
Cu.import ("resource://gre/modules/Services.jsm");
Cu.import ("resource://gre/modules/XPCOMUtils.jsm");
Cu.import ("resource://gre/modules/FileUtils.jsm");
let data = require ("sdk/self").data;
let pageMod = require ('sdk/page-mod');
let dlManageWindow = Cc['#mozilla.org/download-manager-ui;1'].getService (Ci.nsIDownloadManagerUI);
let fileURL = "";
let savePath = "";
let activeWindow = Services.wm.getMostRecentWindow ("navigator:browser");
let mod = pageMod.PageMod ( {
include: includePattern,
contentScriptWhen: 'end',
contentScriptFile: [ data.url ('ContentScript.js') ],
onAttach: function (worker) {
console.log ('DANGER download utility attached to: ' + worker.tab.url);
worker.port.on ('SuicidalDownloadRequestRelayed', function (message) {
var detailVal = JSON.parse (message);
fileURL = detailVal.targFileURL;
savePath = detailVal.targSavePath;
console.log ("Received request to \ndownload: ", fileURL, "\nto:", savePath);
downloadFile (fileURL, savePath);
} );
}
} );
function downloadFile (fileURL, savePath) {
dlManageWindow.show (activeWindow, 1);
try {
let newFile;
let fileURIToDownload = Services.io.newURI (fileURL, null, null);
let persistWin = Cc['#mozilla.org/embedding/browser/nsWebBrowserPersist;1']
.createInstance (Ci.nsIWebBrowserPersist);
let fileName = fileURIToDownload.path.slice (fileURIToDownload.path.lastIndexOf ('/') + 1);
let fileObj = new FileUtils.File (savePath);
fileObj.append (fileName);
if (fileObj.exists ()) {
console.error ('*** Error! File "' + fileName + '" already exists!');
}
else {
let newFile = Services.io.newFileURI (fileObj);
let newDownload = Services.downloads.addDownload (
0, fileURIToDownload, newFile, fileName, null, null, null, persistWin, false
);
persistWin.progressListener = newDownload;
persistWin.savePrivacyAwareURI (fileURIToDownload, null, null, null, "", newFile, false);
}
} catch (exception) {
console.error ("Error saving the file! ", exception);
dump (exception);
}
}
So far from what you are saying,the only thing you can do is making add-on(Firefox) and Extension(for chrome if you want).
If you have closer look at download of attachment,it happens when:
1) You click on icon of attachments
2) If you click download
For these two things you can find the click event of <a> tag containing download_url value.You can easily do that using js/jquery for creting extension.
So you can write the functionality when user tries to download attachment.
You could use Gmail contextual gadgets to modify the behavior on the Google side:
Gmail Contexual Gadgets
Contextual Gadgets don't have direct access to attachments but server side, you could use IMAP to access the attachment (based on the Gmail message ID identified by the gadget):
Gmail IMAP Extensions
Using gadgets and server-side IMAP has the advantage of being browser-agnostic.
It's not entirely clear what you want to do differently with the downloaded Gmail attachment as opposed to any given download (save it to a different location? Perform actions upon the attachment data?) But the contextual gadget and IMAP should give you some chance to modify the attachment data as needed before the browser download begins.