6

I am trying to view a hosted PDF file with the default Android pdf viewer in my App with the following code

            var intent = new Intent(Intent.ActionView);

            intent.SetDataAndType(Uri.Parse("http://sample/url.pdf"), "application/pdf");
            intent.SetFlags(ActivityFlags.ClearTop);
            Android.Content.Context.StartActivity(intent);

I have used this code in a Native project, so I know that it works within an Android activity. For Xamarin Forms, is there a way for me to start an Android activity from a content page, and vice versa?

jcbrowni
  • 321
  • 2
  • 5
  • 13

3 Answers3

14

You can use DependencyService to implement this function:

INativePages in PCL:

 public interface INativePages
{
    void StartActivityInAndroid();
}

Implement the interface in Xamarin.Android:

[assembly: Xamarin.Forms.Dependency(typeof(NativePages))]
namespace PivotView.Droid
{
    public class NativePages : INativePages
    {
        public NativePages()
        {
        }

        public void StartAc()
        {
            var intent = new Intent(Forms.Context, typeof(YourActivity));
            Forms.Context.StartActivity(intent);
        }

    }
}

Start an Android Activity in PCL :

    private void Button_Clicked(object sender, EventArgs e)
    {
        Xamarin.Forms.DependencyService.Register<INativePages>();
        DependencyService.Get<INativePages>().StartAc();
    }
York Shen
  • 9,014
  • 1
  • 16
  • 40
  • I have External storage file path "/storage/emulated/0/Android/data/com.XYZ.projectName/file/Download/sample.pdf". So, How to open file from this URL? – RMR Jul 03 '18 at 04:57
  • 2
    `Forms.Context` is obsolete as of version 2.5. – Ash Feb 13 '19 at 14:55
  • For context use instead `Android.App.Application.Context` – Mohamed Saleh Mar 01 '19 at 18:38
  • 2
    The `[assembly: Xamarin.Forms.Dependency(typeof(NativePages))]` decoration already registers the interface with the dependency service so `Xamarin.Forms.DependencyService.Register();` is not needed explicitly. – CodingLumis Sep 06 '19 at 09:29
2

Forms.Context is obsolete now. The workaround is to instantiate the current context in Main activity class of Android project as under:

public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity 
{
  public static Xamarin.Forms.Platform.Android.FormsAppCompatActivity Instance { get; private set; }

  protected override void OnCreate(Bundle bundle)
  {
        base.OnCreate(savedInstanceState);

        Xamarin.Essentials.Platform.Init(this, savedInstanceState);
        global::Xamarin.Forms.Forms.Init(this, savedInstanceState);

        LoadApplication(new App());
        Instance = this;
  }

And retrieve the local context in your NativePages StartAc() method as under:

public void StartAc()
    {
      var intent = new Intent(MainActivity.Instance, typeof(YourActivity));
      MainActivity.Instance.StartActivity(intent);
    }
adelarsq
  • 3,718
  • 4
  • 37
  • 47
CloudArch
  • 291
  • 2
  • 3
0

Create an class for this function in an android project:

public class PdfLauncher : IPdfLauncher
{
    public void LaunchPdf(string url)
    {
        //implementation
    }
}

Create an interface in a portable project

public interface IPdfLauncher
{
    void LaunchPdf(string url);
}

Add a property to your viewmodel so you can call the function from your portable project

public IPdfLauncher PdfLauncher {get;set;}

Add the interface to your viewmodel constructor and pass in an instance that you create in your android main activity. You can now call android code from your xforms commands and, if you ever add iOS or UWP you can simply implement that interface in those projects and pass them in at runtime. I use an injection framework from MVVM to automate creating these platform specific implementations, and I'd recommend you look into it if you find yourself doing these often.

Slepz
  • 460
  • 3
  • 18