Fuse Community

Need help with my pdf uno module

Hi guys, i need to handle base64 pdf to pdf file in one of my app, so i’m building a uno module to do it.
the code below will describe my integration on both iOS and android.

AndroidImpl.uno file.

using Uno;
using Uno.UX;
using Uno.Collections;
using Uno.Compiler.ExportTargetInterop;
using Fuse;
using Fuse.Triggers;
using Fuse.Controls;
using Fuse.Controls.Native;
using Fuse.Controls.Native.Android;
using Uno.Threading;




namespace PDF
{


	[ForeignInclude(Language.Java, "android.util.Base64", "java.io.FileOutputStream", "java.io.File", "android.content.Context")]
	[Require("AndroidManifest.Permission", "android.permission.WRITE_EXTERNAL_STORAGE")]
	[Require("AndroidManifest.Permission", "android.permission.WRITE_INTERNAL_STORAGE")]
	extern(android)
	class Transform: Promise<string>
	{
		public Transform(string base64String, string filePath)
		{
			Init(base64String, filePath);
		}

		[Foreign(Language.Java)]
	    public void Init(string base64String, string filePath)
	    @{

	    		try{
			    	FileOutputStream fos = new FileOutputStream(filePath);
					fos.write(Base64.decode(base64String, Base64.NO_WRAP));
					fos.close();
	    		}catch(Exception e)
	    		{
	    			@{Transform:Of(_this).Reject(string):Call(e.toString())};
	    		} finally {
	    			@{Transform:Of(_this).Resolve(string):Call("yess file added")};
	    		}

			
	    @}

	        	void Resolve(string message)
		      {
		        base.Resolve(message);
		      }

		      void Reject(string reason)
		      {
		        Reject(new Exception(reason));
		      }

	}









	[ForeignInclude(Language.Java, "com.fuse.Activity", "android.content.Context", "android.content.Intent", "android.net.Uri", "java.io.File")]
	extern(android)
	class LaunchScan: Promise<string>
	{

		public LaunchScan(string path)
		{
			Init(path);
		}


				[Foreign(Language.Java)]
			    public void Init(string path)
			    @{

    			try {
						Uri uri = Uri.parse(path);
						Intent intent = new Intent(Intent.ACTION_VIEW);
						intent.setDataAndType(uri, "application/pdf");
						intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
						if(intent!=null){
							Activity.getRootActivity().startActivity(intent);
						}
					} catch (Exception e) {
						@{LaunchScan:Of(_this).Reject(string):Call(e.toString())};
						e.printStackTrace();
					}
					
			    @}


					void Resolve(string message)
			      {
			        base.Resolve(message);
			      }

			      void Reject(string reason)
			      {
			        Reject(new Exception(reason));
			      }



	}


}

PDFJS.uno

using Uno;
using Uno.UX;
using Uno.Threading;
using Uno.Text;
using Uno.Platform;
using Uno.Compiler.ExportTargetInterop;
using Uno.Collections;
using Fuse;
using Fuse.Scripting;
using Fuse.Reactive;




namespace PDF
{



	[UXGlobalModule]
	public sealed class PDFmodule: NativeModule
	{
		static readonly PDFmodule _instance;



		public PDFmodule()
		{
			if(_instance != null) return;
      		Uno.UX.Resource.SetGlobalKey(_instance = this, "PDF");
      		AddMember(new NativePromise<string, string>("Transform", Transform));
      		AddMember(new NativePromise<string, string>("LaunchScan", LaunchScan));
		}

		    Future<string> Transform(object[] args)
		    {
		    	var base64 = (string)args[0];
		    	var filepath = (string)args[1];
		        return new PDF.Transform(base64, filepath);
		    }


		    	Future<string> LaunchScan(object[] args)
		    {
		    	var path = (string)args[0];

		        return new PDF.LaunchScan(path);
		    }



	}

}

The transform method take a base64 pdf and transform it into a real pdf file before saving it locally. for specifying path i’m using FileSystem.dataDirectory + "/file.pdf"

all seems to work perfectly, but when i try the launch the same file save with my LaunchScan method, the pdf file doesn’t launch and i have this kind of method android.content.ActivityNotFoundException: No Activity found to handle Intent { act=android.intent.action.VIEW dat=/data/user/0/com.apps.pdf/files/file.pdf typ=application/pdf flg=0x4000000 }
anyone can help me on this ?

i’m doin the same with my iOS implementation.

using Uno;
using Uno.UX;
using Uno.Collections;
using Uno.Compiler.ExportTargetInterop;
using Fuse;
using Fuse.Triggers;
using Fuse.Controls;
using Fuse.Controls.Native;
using Fuse.Controls.Native.iOS;
using Uno.Threading;




namespace PDF
{
	extern(iOS)
	class Transform: Promise<string>
	{


	[Foreign(Language.ObjC)]
    public Transform(string base64, string directory)
    @{

    	    @try {
        		NSString *base64Encoded = base64;
		 		NSData *data = [[NSData alloc] initWithBase64EncodedString:base64Encoded options:0];
				NSString *path = directory;
				[data writeToFile:path atomically:YES];
		    }
		    @catch (NSException *exception) {
		        NSLog(@"%@", exception.reason);
		        @{Transform:Of(_this).Reject(string):Call(@"Vous devez etre connecter")};
		    }
		    @finally {
		        @{Transform:Of(_this).Resolve(string):Call(@"ahhh sccesss")};
		  
		    }



    @}


     void Resolve(string message)
      {
        base.Resolve(message);
      }

      void Reject(string reason)
      {
        Reject(new Exception(reason));
      }

	}


	[Require("Source.Include", "WebKit/WebKit.h")]
	extern(iOS)
	class LaunchScan: Promise<string>
	{



	[Foreign(Language.ObjC)]
    public LaunchScan(string path)
    @{

    	   @try {
	    	UIWebView *webView = [[UIWebView alloc] init];
			webView.scalesPageToFit = YES;
			NSURL *targetURL = [NSURL fileURLWithPath:path];
			NSURLRequest *request = [NSURLRequest requestWithURL:targetURL];
			[webView loadRequest:request];
		    }
		    @catch (NSException *exception) {
		        NSLog(@"%@", exception.reason);
		        @{LaunchScan:Of(_this).Reject(string):Call(@"La lecture du fichier a echoué")};
		    }
		    @finally {
		        @{LaunchScan:Of(_this).Resolve(string):Call(@"file open")};
		  
		    }
    @}


	     void Resolve(string message)
	      {
	        base.Resolve(message);
	      }

	      void Reject(string reason)
	      {
	        Reject(new Exception(reason));
	      }

	}



}

Transform method works but i’m not able to launch the webview, for showing the pdf , anyone can show me how to successfully launch the webview here and show the pdf ?

anyone can please help me on this ?

Hello;

Regarding the iOS issue, as far as i know, UiWebView is an UI element on the ObjC side. We allready have a WebView wrapper that might work well. If i were you, i’d check out if you could pass the filename back into JavaScript, and then pop up a Fuse WebView which navigates to your PDF file(I was unable to get it to do this on Android, so milage may vary). If not, you might want to wrap the UiWebView yourself(you can look at this tutorial for guidelines: https://www.fusetools.com/docs/native-interop/native-ux-components)

Otherwise, opening it in the default Web browser might be what you want, but i doubt it. You can read more on that here anyways: https://stackoverflow.com/questions/8755843/how-to-open-iphones-default-browser

On the Android side, this StackOverflow article seems to hint that the error you are getting is due to your phone not having a PDF reader installed: https://stackoverflow.com/questions/25949802/android-no-activity-found-to-handle-intent-act-android-intent-action-view

Androids WebView doesn’t support pdf it would appear from this. However, you could target for lolipop and up and use one of the solutions from here, wrapped as a native UX component(again, check the guide above): https://stackoverflow.com/questions/2456344/render-a-pdf-file-using-java-on-android

So, a TL;DR? On android, firing an intent to open a pdf file requires an app that can open it, which your phone doesn’t seem to have. The fix is probably wrapping androids PdfRenderer(lolipop and up)

on iOS, you might be able to get away with using a Fuse WebView. If not, wrap the native one.

Thank you Liam.
Your answer really helped me here, so yesterday i updated my repository with a new fresh PDF module.

i built a panel for showing the pdf for both iOS and Android.
the iOS part use the built in iOS webview for showing the pdf and the android part use this pdf renderer ==> https://github.com/barteksc/AndroidPdfViewer. (works on Android 3.0 and Higher). both are served with one fuse panel called Native.PDF.

			<NativeViewHost>
				<Native.PDF ux:Name="PDFVIEW"/>
			</NativeViewHost>

Hello people. Can anybody told me if the possibility make zoom(scale) pdf document witch shows in <NativeViewHost> <Native.PDF ux:Name="PDFVIEW"/> </NativeViewHost>
?