Sharing targeted xamarin forms - xamarin

I use the following command to share a link, but with this command opens a box with apps for me to share. I want when I share it already go straight to facebook, without going through this box
void OnTapped4(object sender, EventArgs args)
{
CrossShare.Current.ShareLink(link, "teste", titulo);
}
Need to do direct shares to facebook, whatsapp, twitter and email
I have this command plus it works only on xamarin android, in xamarin forms it would no work
Intent sendIntent = new Intent();
sendIntent.SetAction(Intent.ActionSend);
sendIntent.PutExtra(Intent.ExtraText,"titulo");
sendIntent.SetType("text/plain");
sendIntent.SetPackage("com.facebook.orca");
StartActivity(sendIntent);

I found the following example where I did on android and it worked, now I want to do this in IOS how can I get it to go to whatsapp
Android
public class ShareService : IShareService
{
public void SharePageLink(string url)
{
var context = Forms.Context;
Activity activity = context as Activity;
Intent share = new Intent(Intent.ActionSend);
share.SetType("text/plain");
share.AddFlags(ActivityFlags.ClearWhenTaskReset);
share.PutExtra(Intent.ExtraSubject, "Brusselslife");
share.SetPackage("com.whatsapp");
share.PutExtra(Intent.ExtraText, url);
activity.StartActivity(Intent.CreateChooser(share, "Share link!"));
}
}
In IOS where to put this 'com.whatsapp'
public class ShareService : IShareService
{
public void SharePageLink(string url)
{
var window = UIApplication.SharedApplication.KeyWindow;
var rootViewController = window.RootViewController;
//SetPackage
var activityViewController = new UIActivityViewController(new NSString[] { new NSString(url) }, null);
activityViewController.ExcludedActivityTypes = new NSString[] {
UIActivityType.AirDrop,
UIActivityType.Print,
UIActivityType.Message,
UIActivityType.AssignToContact,
UIActivityType.SaveToCameraRoll,
UIActivityType.AddToReadingList,
UIActivityType.PostToFlickr,
UIActivityType.PostToVimeo,
UIActivityType.PostToTencentWeibo,
UIActivityType.PostToWeibo
};
rootViewController.PresentViewController(activityViewController, true, null);
}
}

Related

Broadcast Extension with ReplayKit Xamarin iOS not displaying device screen

I created a Xamarin forms project and added Broadcast Upload Extension and Extension UI and reference them into IOS Project also I followed the instructions in the doc here
https://learn.microsoft.com/en-us/xamarin/ios/platform/extensions#container-app-project-requirements
I uses agora for screen sharing but the result is the device share the camera instead of it's screen
I followed this sample
https://github.com/DreamTeamMobile/Xamarin.Agora.Samples/tree/master/ScreenSharing
and added a Dependency service Interface to invoke it from Xamarin forms all is working expect device share it's camera not it's screen
public class AgoraServiceImplementation : IAgoraService
{
private void JoiningCompleted(Foundation.NSString arg1, nuint arg2, nint arg3)
{
_myId = arg2;
_agoraEngine.SetEnableSpeakerphone(true);
JoinChannelSuccess((uint)_myId);
var bundle = NSBundle.MainBundle.GetUrlForResource("ScreenSharingIOSExtension", "appex", "PlugIns");
var frame = new CGRect(100, 100, 60, 60);
var broadcastPicker = new RPSystemBroadcastPickerView(frame);
var bundle2 = new NSBundle(bundle);
broadcastPicker.PreferredExtension = bundle2.BundleIdentifier;
var vc = Platform.GetCurrentUIViewController();
vc.Add(broadcastPicker);
}
public void StartShareScreen(string sessionId, string agoraAPI, string token, VideoAgoraProfile profile = VideoAgoraProfile.Portrait360P, bool swapWidthAndHeight = false, bool webSdkInteroperability = false)
{
_agoraDelegate = new AgoraRtcDelegate(this);
_agoraEngine = AgoraRtcEngineKit.SharedEngineWithAppIdAndDelegate(agoraAPI, _agoraDelegate);
_agoraEngine.EnableWebSdkInteroperability(webSdkInteroperability);
_agoraEngine.SetChannelProfile(ChannelProfile.LiveBroadcasting);
_agoraEngine.SetClientRole(ClientRole.Broadcaster);
//
_agoraEngine.EnableVideo();
if (!string.IsNullOrEmpty(AgoraSettings.Current.EncryptionPhrase))
{
_agoraEngine.SetEncryptionMode(AgoraSettings.Current.EncryptionType.GetModeString());
_agoraEngine.SetEncryptionSecret(helper.AgoraSettings.Current.EncryptionPhrase);
}
_agoraEngine.StartPreview();
Join();
}
private async void Join()
{
var token = await AgoraTokenService.GetRtcToken(helper.AgoraSettings.Current.RoomName);
if (string.IsNullOrEmpty(token))
{
//smth went wrong
}
else
{
_agoraEngine.JoinChannelByToken(token, AgoraSettings.Current.RoomName, null, 0, JoiningCompleted);
}
}
}
any help ?

How to make a call via dialer programmatically in android Pie and above

I use this code to show the number and when pressing it to make a dial.It is working for android versions before Android Pie.
final Button but= findViewById(R.id.buttond);
but.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
String PhNumber = "6998474783";////example number
final CharSequence[] phones = PhNumber.split(" - ");
AlertDialog.Builder builder = new AlertDialog.Builder(CTX);
builder.setTitle("Επιλογή Τηλεφώνου");
builder.setItems(phones, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int item) {
// Do something with the selection
Intent intent = new Intent(Intent.ACTION_CALL, Uri.parse("tel:" + phones[item].toString()));
if (ActivityCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.CALL_PHONE) != PackageManager.PERMISSION_GRANTED) {
return; }
startActivity(intent);
}
});
AlertDialog alert = builder.create();
alert.show();
}
});
What I have to change to work with Pie and above?
It shows the phone number but when I press it nothing happens
Solved using ACTION_DIAL without any checkSelfPermission.
Intent intent = new Intent(Intent.ACTION_DIAL, Uri.parse("tel:" + phones[item].toString()));
startActivity(intent);
If is there any other way, maybe with telecom-Manager please post it.

How do I enable WebGL in Xamarin.Forms WebView on UWP?

I’m new to Xamarin.Forms and tried using WebView on my Windows 10 x64 v1803 machine with UWP but I can’t see how to get it to work with WebGL.
Sites which use WebGL either display a message that “Your video card does not support WebGL or just don’t display and graphical content at all.
Is this a limitation of UWP or WebView itself?
Is it a WebView configuration issue?
WebGL works in all other browsers on this machine.
UWP WebView control is support WebGL. There is similar issue case in msdn you could refer. Please try to use SeparateProcess mode WebView to replace the default one.
public MainPage()
{
this.InitializeComponent();
var MyWebView = new WebView(WebViewExecutionMode.SeparateProcess);
MyWebView.Source = new Uri("http://cycleblob.com/");
this.RootGrid.Children.Add(MyWebView);
}
I had the same problem, but with the newer Xamarin Forms it took a little more poking around to get this took work right. However, I do like that they moved the native WebView resolver back to the responsibility of the UWP/iOS/Android project (as a native XAML object) instead of using code branching with compiler directives in the Shared project.
Start by creating a HybridWebView class in the shared project to use as your WebForm view object:
public class HybridWebView : Xamarin.Forms.WebView
{
Action<string> action;
public static readonly BindableProperty UriProperty = BindableProperty.Create(
propertyName: "Uri",
returnType: typeof(string),
declaringType: typeof(HybridWebView),
defaultValue: default(string));
public string Uri
{
get { return (string)GetValue(UriProperty); }
set { SetValue(UriProperty, value); }
}
public void RegisterAction(Action<string> callback)
{
action = callback;
}
public void Cleanup()
{
action = null;
}
public void InvokeAction(string data)
{
if (action == null || data == null)
{
return;
}
action.Invoke(data);
}
}
Then in the UWP project, create a custom renderer, which will construct the native WebView and relay the events back to the WebForms object in the Shared project:
Put this at the top of the namespace, to link the HybridWebView with the Custom Renderer:
[assembly: ExportRenderer(typeof(HybridWebView), typeof(WebViewRenderer2))]
Then create the renderer class (for the IOS and android projects, if you leave this class out, it defaults to the standard native controls which seem to work fine for me):
public class WebViewRenderer2 : ViewRenderer<Xamarin.Forms.WebView, Windows.UI.Xaml.Controls.WebView>, IWebViewDelegate
{
Windows.UI.Xaml.Controls.WebView _control;
public void LoadHtml(string html, string baseUrl)
{
}
public void LoadUrl(string url)
{
}
protected override void Dispose(bool disposing)
{
}
protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.WebView> e)
{
if (_control == null) {
_control = new Windows.UI.Xaml.Controls.WebView(WebViewExecutionMode.SeparateProcess);
SetNativeControl(_control);
}
}
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
{
var xamWebView = sender as HybridWebView;
switch(e.PropertyName.ToLower())
{
case "source":
var urlSource = xamWebView.Source as Xamarin.Forms.UrlWebViewSource;
_control.Source = new Uri(urlSource.Url);
break;
case "width":
_control.Width = xamWebView.Width;
break;
case "height":
_control.Height = xamWebView.Height;
break;
case "isfocused":
var focused = xamWebView.IsFocused;
if (focused)
_control.Focus(FocusState.Programmatic);
else
_control.Focus(FocusState.Unfocused);
break;
}
}
}
You can also use the Custom Renderer to inject scripts, and you can use it to communicate from the native webview back to the Xamarin App, as seen here: HybridWebView Communication

How to send OnActivityResult To a specific page in xamarin forms

I am using a custom button renderer for google sign In in xamarin forms page its working fine I get the signin resultin MainActivity Now i want to send this data from MainActivity and AppDelegate to the Particular page in Xamarin Forms.
protected override void OnActivityResult(int requestCode, Result resultCode, Intent data)
{
base.OnActivityResult(requestCode, resultCode, data);
if (requestCode == 9001)
{
Utilities.Configuration.UpdateConfigValue(Utilities.Constants.loggedInflag,string.Empty);
GoogleSignInResult result = Android.Gms.Auth.Api.Auth.GoogleSignInApi.GetSignInResultFromIntent(data);
if (result.IsSuccess)
{
GoogleSignInAccount acct = result.SignInAccount;
var token = acct.IdToken;
//I wan to send the 'accnt' to a Page in xamarin forms
}
else
{
//Signin Failure send response to Page in xamarin forms
}
}
}
Xamarin.Forms runs only in one Activity on Android. So if your url request comes out in a different Activity, you have to switch back to the MainActivity before you can use the normal XF navigation.
I do this when a user opens a file associated with my app.
[Activity(Label = "LaunchFileActivity")]
public class LaunchFileActivity : Activity
{
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
if (Intent.Data != null)
{
var uri = Intent.Data;
if (uri != null)
{
Intent i = new Intent(this, typeof(MainActivity));
i.AddFlags(ActivityFlags.ReorderToFront);
i.PutExtra("fileName", uri.Path);
this.StartActivity(i);
}
}
this.FinishActivity(0);
}
}
And in MainActivity:
protected override void OnNewIntent(Intent intent)
{
base.OnNewIntent(intent);
Intent = intent;
}
protected override void OnPostResume()
{
base.OnPostResume();
if (Intent.Extras != null)
{
string fileName = Intent.Extras.GetString("fileName");
if (!string.IsNullOrEmpty(fileName))
{
// do something with fileName
}
Intent.RemoveExtra("fileName");
}
}
Xamarin forms runs on one activity, which is most like your main activity.
There are two sample projects that show you how to communicate between native and form parts of the code, which can be found here
https://github.com/xamarin/xamarin-forms-samples/tree/master/Forms2Native
https://github.com/xamarin/xamarin-forms-samples/tree/master/Native2Forms
However, to answer your question, you would do something like the following
private const int MyRequestCode = 101;
//Start activity for result
var contactPickerIntent = new Intent(Intent.ActionPick, Android.Provider.ContactsContract.Contacts.ContentUri);
context.StartActivityForResult(contactPickerIntent, MyRequestCode);
and then in your main activity (the activity that initializes your xamarin forms application (using global::Xamarin.Forms.Forms.Init(this, bundle);)
protected override void OnActivityResult(int requestCode, Result resultCode, Intent data)
{
if (requestCode == MyRequestCode && resultCode == Result.Ok)
{
}
}

How to resume the application and open a specific page with a push notification in Xamarin.forms

I'm currently working on a Xamarin application working both on iOS and Android, but the problem I'm going to explain only concerns the Android application (this is not yet implemented in the iOS app).
Actually, when I receive a given push notification, I need to open a specific page in my application. It works very well if the application is open when the push notification is received, but the app crashes if my app is closed or run in background.
Well, when I receive the notification, I end up in the method called "OnShouldOpenCommand" :
private void OnShouldOpenCommand(string commandId)
{
NotifyNewCommand(AppResources.AppName, AppResources.CommandNotificationText, commandId);
Device.BeginInvokeOnMainThread(() =>
{
try
{
App.MasterDetailPage.Detail = new NavigationPage(new CommandAcceptancePage(commandId))
{
BarBackgroundColor = Color.FromHex("1e1d1d")
};
App.MasterDetailPage.NavigationStack.Push(((NavigationPage)(App.MasterDetailPage.Detail)).CurrentPage);
}
catch(Exception e)
{
Log.Debug("PushAsync", "Unable to push CommandAcceptancePage : "+ex.Message);
}
});
}
private void NotifyNewCommand(string Title,string Description, string commandId)
{
var intent = new Intent(this, typeof(MainActivity));
if (!String.IsNullOrEmpty(commandId))
{
intent.PutExtra("CommandId", commandId);
}
intent.AddFlags(ActivityFlags.ClearTop);
var pendingIntent = PendingIntent.GetActivity(this, 0, intent, 0);
var notificationBuilder = new Notification.Builder(this)
.SetSmallIcon(Resource.Drawable.icon)
.SetContentTitle("Kluox")
.SetContentText(Description)
.SetAutoCancel(true)
.SetContentIntent(pendingIntent);
Notification notification = notificationBuilder.Build();
var notificationManager = (NotificationManager)GetSystemService(Context.NotificationService);
notificationManager.Notify(0, notification);
}
And the code
App.MasterDetailPage.Detail = new NavigationPage(new CommandAcceptancePage(commandId))
{
BarBackgroundColor = Color.FromHex("1e1d1d")
};
is generating an exception of type :
Java.Lang.IllegalStateException: Can not perform this action after
onSaveInstanceState
So well, I suppose I can't access "App" and redirect to another page if my application is not running in foreground. Well, this is when I receive the push notification an not when I click on it. But well, I do not intend to reopen my app by doing this.
Because afther that, when I click on the push notification called Kluox (and this is supposed to reopen my app), the app crashes and I really don't know why, I don't know where to put breakpoints to be able to debug because Visual Studio just tells me "An unhandled exception occured.".
Could anyone help me ? If you need any piece of code, you can just ask me, I'll edit my message and give you any information you need !
EDIT 1 : Here is the code of my OnCreate method :
protected override void OnCreate(Bundle bundle)
{
TabLayoutResource = Resource.Layout.Tabbar;
ToolbarResource = Resource.Layout.Toolbar;
base.OnCreate(bundle);
var info = Intent.Extras?.GetString("CommandId", "");
global::Xamarin.Forms.Forms.Init(this, bundle);
if (String.IsNullOrEmpty(info))
{
LoadApplication(new App());
}
else
{
LoadApplication(new App(info));
}
if (instance == null)
{
instance = this;
RegisterWithGCM();
}
else
{
instance = this;
}
}
After overriding all the methods of MainActivity, I finally found the cause of the crash : the method OnDestroy was called twice, and threw a IllegalStateException because the activity was already destroyed. I found this workaround :
protected override void OnDestroy()
{
try
{
base.OnDestroy();
}
catch (Java.Lang.IllegalStateException ex)
{
Log.Debug("MainActivity.OnDestroy", ex, "The activity was destroyed twice");
}
}
And the exception is simply logged, the application can open and be used without problems.
I'll edit this answer when the redirection works too.
EDIT : how to redirect to a page
First, we needed to register for the MessagingCenter, in the constructor
public static MyPackage.Model.Command CurrentCommand { get; set; }
public App()
{
InitializeComponent();
MainPage = new ContentPage();
MessagingCenter.Subscribe<object, DataLib.Model.Command>(this, "Command", (sender, arg) => {
try
{
CurrentCommand = arg;
}
catch(Exception ex)
{
CurrentCommand = null;
}
});
}
And send the message when we get the push notification :
private void OnMessage(string serializedCommand)
{
//stuff happens
MessagingCenter.Send<object, MyPackage.Model.Command>(this, "Command", command);
}
Finally, when we get the OnStart() of App.Xaml.cs
if (CurrentCommand != null)
{
App.MasterDetailPage.Detail = new NavigationPage(new CommandAcceptancePage(CurrentCommand, service))
{
BarBackgroundColor = Color.FromHex("1e1d1d")
};
}
For now, it seems to do the trick ! More debugging will follow, but the code seems to work. Thanks a VERY lot to #BraveHeart for their help !
well luckily for you I was there few days ago and lost a lot of hair till I got it working in Android (and still in the strugle for iOS).
When you kill your app and instantiate it again form the icon or from the notification in both cases you will go to the main activity .
If we want to take some information in the main activity from the notification that instantiated it we do it like this in OnCreate():
var info = Intent.Extras?.GetString("info", "");
Now in your case I would add extra information to the notification showing that which View/Page this notification is about, something like the name of it for example)
This extra piece of information you can pass it to the constructor of the App before you load it.
In the constructor of the app you can check if there are extra info or not , if not that means to start the app's mainPage is the default MainPage, otherwise it is a certain page.

Resources