How to share file(pdf,docx) throught xamarin form - xamarin.forms

i am using CrossShareFile.Current.ShareRemoteFile to share file. Its working fine in IOS but not in android. When i click on share button its giving me this error
Plugin.ShareFile: ShareLocalFile Exception: Android.OS.FileUriExposedException: file:///storage/emulated/0/test.pdf exposed beyond app through ClipData.Item.getUri()
i have tried many things, but couldnt succeed on this
async void Handle_Clicked(object sender, System.EventArgs e)
{
await CrossShareFile.Current.ShareRemoteFile("http://onlinekih.somee.com/Documents/8.pdf","test.pdf");
}

Hi Use Xamarin Essentials: using Xamarin.Essentials;
public class ShareTest
{
public async Task ShareText(string text)
{
await Share.RequestAsync(new ShareTextRequest
{
Text = text,
Title = "Share Text"
});
}
public async Task ShareUri(string uri)
{
await Share.RequestAsync(new ShareTextRequest
{
Uri = uri,
Title = "Share Web Link"
});
}
}strong text

Related

Proactive Dialog Bot Framework - Cannot continue the waterfall Dialog

Here I am trying to invoke a dialog and push it on the existing dialog stack, idea is to proactively call a Dialog and continue the waterfall structure of the dialog.
Issue : I can start the dialog, and prompt user with Hero card to select Yes or No choices
but the Answer given by user does not stay in the same Dialog context.
Error : Failed to continue dialog. A dialog with continueConversationDialog id could not be found.
Below is the sample code snippet used for invoking the Dialog from controller
public class ProactiveMessageController : Controller
{
private readonly BotFrameworkHttpAdapter _adapter;
private readonly ConversationState _conversationState;
private readonly IBot _bot;
private readonly BotSettings _settings;
private readonly ILastMessageSent _lastmessagesent;
private readonly ContinueConversationDialog _dialog;
public ProactiveMessageController (BotFrameworkHttpAdapter adapter, ConversationState conversationState, IBot bot, BotSettings settings, ILastMessageSent lastmessagesent, ContinueConversationDialog dialog)
{
_adapter = adapter;
_conversationState = conversationState;
_bot = bot;
_settings = settings;
_dialog = dialog;
}
[HttpGet]
public async Task<IActionResult> Index()
{
try
{
await _adapter.ContinueConversationAsync(
_settings.MicrosoftAppId,
item.conversationReference,
async (ITurnContext TurnContext, CancellationToken cancellationToken) =>
{
var conversationStateAccessors = _conversationState.CreateProperty<DialogState>(nameof(DialogState));
var dialogSet = new DialogSet(conversationStateAccessors);
dialogSet.Add(_dialog);
var dialogContext = await dialogSet.CreateContextAsync(TurnContext, cancellationToken);
await dialogContext.BeginDialogAsync(_dialog.Id);
await _conversationState.SaveChangesAsync(TurnContext,false,cancellationToken);
},
default(CancellationToken)
);
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
}
Sample waterfall Dialog code snippet, is as follows
public class ContinueConversationDialog : ComponentDialog
{
private readonly BotServices _services;
private readonly LocaleTemplateManager _templateManager;
private readonly IStatePropertyAccessor<UserProfileState> _accessor;
private readonly IUserManagement _userManagement;
public ContinueConversationDialog(
IServiceProvider serviceProvider, IUserManagement userManagement)
: base(nameof(ContinueConversationDialog))
{
_templateManager = serviceProvider.GetService<LocaleTemplateManager>();
var userState = serviceProvider.GetService<UserState>();
_accessor = userState.CreateProperty<UserProfileState>(nameof(UserProfileState));
_services = serviceProvider.GetService<BotServices>();
var ContinueConversation = new WaterfallStep[]
{
PromptToContinueConversation,
FinishDialogAsync,
};
AddDialog(new WaterfallDialog(nameof(ContinueConversation), ContinueConversation));
AddDialog(new ConfirmPrompt(nameof(ConfirmPrompt)));
_userManagement = userManagement;
}
public async Task<DialogTurnResult> PromptToContinueConversation(WaterfallStepContext sc, CancellationToken cancellationToken)
{
return await sc.PromptAsync(nameof(ConfirmPrompt), new PromptOptions
{
Prompt = _templateManager.GenerateActivityForLocale("ConfirmPrompt"),
RetryPrompt = _templateManager.GenerateActivityForLocale("InvalidOptionPrompt"),
Style = ListStyle.HeroCard
}, cancellationToken);
}
public async Task<DialogTurnResult> FinishDialogAsync(WaterfallStepContext sc, CancellationToken cancellationToken)
{
bool ContinueConversationresponse = (bool)sc.Result;
if (ContinueConversationresponse)
{
//Continue the conversation on main dialog
Console.Write("Selected Yes");
return null;
}
else
{
//Ask for feedback and close the conversation
return null;
}
}
}
Part 1 where user is prompted with chocie works well, dialog is invoked without any issue
But when user submits the response I am not able to get it in same context.
I apply debugger and breakpoints in dialog to confirm the flow reaching the second step but it never does.
Can you please suggest how can we continue the conversation in same context after dialog is pushed on the current stack.
FYI: I am saving the current dialog state as well but no luck continuing; Dialog classes are registered as Transient, I have tried making it Singleton but does not make a differnce.

Run a Task without killing

I'm trying to implement a functionality where user can simply click on download button and can go on any page that he/she wishes while download is still running, and it should not stop.
I'm using xamarin form.
Is there any way to do this, please suggest or any reference, since i couldn't find the same.
Since the class App always exists in memory when the application is running , we can place the Task in App.
Simple Task
//App
public async void DoSomething()
{
await Task.Delay(30000);
}
// in specific page
string result = await (App.Current as App).DoSomething();
Task with return values
//App
public async Task<string> DoSomething()
{
await Task.Delay(30000);
return "123";
}
// in specific page
string result = await (App.Current as App).DoSomething();
If you don't want to put the code into App , we can create a extra class in App to handle this .
//App
private MyTask _myTask;
public MyTask myTask
{
get
{
return _myTask ?? new MyTask();
}
}
//MyTask
public class MyTask
{
public async Task<string> DoSomething()
{
await Task.Delay(30000);
return "123";
}
}
//in specific page
string result = await (App.Current as App).myTask.DoSomething();

Await method before app starts in the same UI thread

I'm trying to check which page should load my app at the beginning, first of all I check a database table if I find the login information stored I want to push the once named StartPage(), as I'm working with the database the method includes an await if there isn't any data stored I want to push the LoginPage(). I have tried following this example Xamarin.Forms Async Task On Startup . My code is :
public App()
{
int result;
InitializeComponent();
ThreadHelper.Init(SynchronizationContext.Current);
ThreadHelper.RunOnUIThread(async () => {
MainPage = new ActivityIndicatorPage();
result = await InitializeAppAsync();
if (result == 0)
{
PushLoginPage();
}
else
{
PushStartPage();
}
});
}
public void PushStartPage()
{
NavigationPage nav = new NavigationPage(new StartPage());
nav.SetValue(NavigationPage.BarBackgroundColorProperty, Color.FromHex("#D60000"));
MainPage = nav;
}
public void PushLoginPage()
{
MainPage = new Login();
}
public void PushLoginPage(string email, string password)
{
MainPage = new Login(email, password);
}
private async Task<int> InitializeAppAsync()
{
if (ViewModel == null)
ViewModel = new MainViewModel(this);
return await ViewModel.LoginViewModel.PushInitialPage();
}
But throws the following exception and as the author of the article says, is not recommended to do it.
Exception
Another option tried was overriding the OnStart() method but didn't work either.
protected override async void OnStart()
{
Task.Run(async ()=> { await InitializeAppAsync(); });
}
The PushInitialPage method:
public async Task PushInitialPage()
{
if (_app.Properties.ContainsKey("isLogged"))
{
var user = await UserDataBase.GetUserDataAsync();
var result = await Login(user.Email, user.Password);
if (result.StatusCode != 200)
{
return 0;
///PushLoginPage();
}
else
{
return 1;
//PushStartPage();
}
}
else
{
return 0;
}
}
When the OS asks your app to show a page, it must show a page. It can't say "hold on a minute or two while I talk to this remote server over an iffy network connection." It has to show a page Right Now.
So, I recommend bringing up a splash page - your company or app logo, for example. When the splash page shows, then call InitializeAppAsync, and based on the result, switch to the login or start page or nice user-friendly offline error page.
In Xamarin.Forms we have properties called 'Application.Current.Properties'. By using this we can able to save the any data type. So once user login in to the application you can set one flag and set it is true. Then after every time when user login in to the application you can check this flag and navigate your respective page.
Sample Code :
App.cs :
public App()
{
if (Current.Properties.ContainsKey("isLogged"))
{
if((bool)Application.Current.Properties["isLogged"])
{
// navigate to your required page.
}
else
{
// naviate to login page.
}
}
else
{
// naviate to login page.
}
}
At first time application open it checks the 'isLogged' property is presented or not, if not it will move to the login page. When user login into the application by using his credentials, we need to create 'isLoggin' property and set as true. Then after if user try to login it checks the condition and navigates to the respective page.
Saving Property SampleCode :
Application.Current.Properties["isLogged"] = true;
await Application.Current.SavePropertiesAsync();
write above code for after login into the application. If a user log out from the app you need to set 'isLogged' flag is false.

Change Cefsharp Locale at runtime

You can't Cef.Shutdown() and reinitialize, you can't initialize multiple times so it seems you can't change the browser locale without completeley restarting your application.
The goal is to switch language of Cefsharp according to our application user language defined at login. E.g. Login with user German Cefsharp is in German, logout with User English Cefsharp should be in English but is still language of initialization.
This Github issue about this topic exists and it is in state Closed. The issue says something about partially implemented and testing and is from the year 2015. I didn't find anything how to do this in C# code.
Just adding to Mohammad Dimas answer.
ChromiumWebBrowser has a IsBrowserInitializedChanged event where you can obtain a RequestContext.
browser.IsBrowserInitializedChanged += Browser_IsBrowserInitializedChanged;
private void Browser_IsBrowserInitializedChanged(object sender, IsBrowserInitializedChangedEventArgs e)
{
var browserHost = browser.GetBrowser().GetHost();
var requestContext = browserHost.RequestContext;
string errorMessage = "";
requestContext.SetPreference("intl.accept_languages", languageCode, out error);
}
EDIT:
Ok can you try this one? It will change the local language (navigator.languages) but not sure it will include that pdf viewer.
public static void SetLanguage(string languageCode)
{
Cef.UIThreadTaskFactory.StartNew(() =>
{
using (var context = Cef.GetGlobalRequestContext())
SetLanguage(languageCode, context);
});
}
public static void SetLanguage(string languageCode, IRequestContext context)
{
string error = null;
var success = context.SetPreference("intl.accept_languages", languageCode, out error);
if (!string.IsNullOrEmpty(error))
Log.WriteAsync(LogLevel.Error, string.Format("Error changing language: {0}", error));
}

Public method not firing in SignalR

I have a simple application, like a chat, integrated with SignalR. I added a new method on my Hub and a new function on client side, like you can see below.
The problem is, my method called SendMessageChat isn't firing, because occurs the following error
TypeError: chat2.server.SendMessageChat is not a function
but the method chat2.server.send works fine, and I don't know why my second method doesn't work. Can someone help me ?
JavaScript
$(function () {
var chat2 = $.connection.redirectTask;
chat2.client.broadcastMessage = function (name, message) {
// Do something here
};
chat2.client.sendMessage = function (name, message) {
// Do something here
};
//$.connection.hub.logging = true;
$.connection.hub.start().done(function () {
/* BUTTON CLICK IN ANOTHER PAGE */
$('#btnFinish').click(function () {
chat2.server.send($.cookie("User"), $("#lista :selected").text());
});
/* CASE HIT ENTER INSIDE THE TEXT FIELD IN CHAT */
$(document).on("keypress", "#txtChat", function (e) {
var code = (e.keyCode ? e.keyCode : e.which);
if (code == 13) {
var message = $(this).val();
$(this).val("");
chat2.server.SendMessageChat($.cookie("User"), message);
}
});
});
});
SERVER SIDE
public class RedirectTask : Hub
{
public void Send(string nome, string message)
{
Clients.All.broadcastMessage(name, message);
}
public void SendMessageChat(string nome, string message)
{
Clients.All.sendMessage(name, message);
}
}
Reference
Need to change to
chat2.server.sendMessageChat($.cookie("User"), message);
Camel-casing of method names in JavaScript clients
By default, JavaScript clients refer to Hub methods by using a camel-cased version of the method name. SignalR automatically makes this change so that JavaScript code can conform to JavaScript conventions.
Server
public void NewContosoChatMessage(string userName, string message)
JavaScript client using generated proxy
contosoChatHubProxy.server.newContosoChatMessage(userName, message);
If you want to specify a different name for clients to use, add the HubMethodName attribute.
Server
[HubMethodName("PascalCaseNewContosoChatMessage")]
public void NewContosoChatMessage(string userName, string message)
JavaScript client using generated proxy
contosoChatHubProxy.server.PascalCaseNewContosoChatMessage(userName, message);

Resources