Titanium JIRA Archive
Titanium SDK/CLI (TIMOB)

[TIMOB-26447] Android 8: Unable open PDF on some devices

GitHub Issuen/a
TypeBug
PriorityHigh
StatusClosed
ResolutionFixed
Resolution Date2018-10-24T17:50:09.000+0000
Affected Version/sRelease 7.4.0
Fix Version/sn/a
ComponentsAndroid
Labelsn/a
ReporterShuo Liang
AssigneeGary Mathews
Created2018-10-09T09:19:59.000+0000
Updated2018-10-24T17:50:53.000+0000

Description

Problem

Customer is trying to download the pdf from remote server using URL, save them to external or application directory and then open them in external pdf viewer using intent. Like example in post https://www.appcelerator.com/blog/2015/08/appcelerator-pdf-viewer-demo/. But throwing following error on Android 8.
[ERROR] : TiFileProxy: (KrollRuntimeThread) [9574,75852] IOException encountered 
[ERROR] : TiFileProxy: java.io.FileNotFoundException: /storage/emulated/0/com.edf.mobile/EDF Bill 10 August 2018.pdf (Permission denied) 
[ERROR] : TiFileProxy: at java.io.FileOutputStream.open0(Native Method) 
[ERROR] : TiFileProxy: at java.io.FileOutputStream.open(FileOutputStream.java:287) 
[ERROR] : TiFileProxy: at java.io.FileOutputStream.<init>(FileOutputStream.java:223) 
[ERROR] : TiFileProxy: at org.appcelerator.titanium.io.TiFile.getOutputStream(TiFile.java:304) 
[ERROR] : TiFileProxy: at org.appcelerator.titanium.io.TiFile.open(TiFile.java:368) 
[ERROR] : TiFileProxy: at org.appcelerator.titanium.io.TiFile.write(TiFile.java:414) 
[ERROR] : TiFileProxy: at org.appcelerator.titanium.TiFileProxy.write(TiFileProxy.java:331) 
[ERROR] : TiFileProxy: at org.appcelerator.kroll.runtime.v8.V8Object.nativeCallProperty(Native Method) 
[ERROR] : TiFileProxy: at org.appcelerator.kroll.runtime.v8.V8Object.callProperty(V8Object.java:75) 
[ERROR] : TiFileProxy: at org.appcelerator.kroll.KrollProxy.handleMessage(KrollProxy.java:1208) 
[ERROR] : TiFileProxy: at android.os.Handler.dispatchMessage(Handler.java:101) 
[ERROR] : TiFileProxy: at android.os.Looper.loop(Looper.java:164) 
[ERROR] : TiFileProxy: at org.appcelerator.kroll.KrollRuntime$KrollRuntimeThread.run(KrollRuntime.java:117) 

Note

The strange problem is not happening to all model of devices. For example On Android 7 Seems all devices work well. At least, all the test devices are working well. On Android 8 Moto G device which is on android 8 worked fine. but others, like Google Pixel or Samsung Note 8, will get above error.

Example code

function testPDF() {
	var tempFile = Titanium.Filesystem.getFile(Titanium.Filesystem.isExternalStoragePresent() ? Titanium.Filesystem.externalStorageDirectory : Titanium.Filesystem.applicationDataDirectory, '/' + 'EDF Bill ' + e.source.text + '.pdf'); 
	var appfilepath = tempFile.nativePath; 

	var url = "http://www.mbta.com/uploadedfiles/Documents/Schedules_and_Maps/Rapid%20Transit%20w%20Key%20Bus.pdf";
	var xhr = Ti.Network.createHTTPClient(); 

	xhr.onload = function() { 
		tempFile.write(this.responseData); 
		try{ 
			Ti.Android.currentActivity.startActivity(Ti.Android.createIntent({ 
				action: Ti.Android.ACTION_VIEW, 
				type: 'application/pdf', 
				data: appfilepath 
			})); 
		} catch(e) { 
			Ti.API.info('error trying to launch activity, e = '+e); 
			alert('No PDF apps installed!'); 
		} 
	};
 
	xhr.onerror = function() { 
		alert("Cannot retrieve PDF from web site") ;
	}; 

	xhr.timeout = 10000; 
	xhr.open("GET", url); 
	xhr.send();
}
Please check this asap, very important function for customer's app.

Attachments

FileDateSize
test.js2018-10-11T10:15:42.000+00002370

Comments

  1. Gary Mathews 2018-10-10

    It's correct that they need to add the required storage permissions into the tiapp.xml. But on later Android versions they also need to request storage permissions: For example, they could amend their onload to request storage permissions:
       xhr.onload = function() {
           Ti.Filesystem.requestStoragePermissions(function (e) {
               if (e.success) {
                   tempFile.write(this.responseData);
                   try{
                       Ti.Android.currentActivity.startActivity(Ti.Android.createIntent({
                           action: Ti.Android.ACTION_VIEW,
                           type: 'application/pdf',
                           data: appfilepath
                       }));
                   } catch(e) {
                       Ti.API.info('error trying to launch activity, e = '+e);
                       alert('No PDF apps installed!');
                   }
               } else {
                   Ti.API.error('could not obtain required storage permissions!');
               }
           });
       };
       
  2. Gary Mathews 2018-10-11

    You will want write permissions too:
       Ti.Android.requestPermissions(
           [ 'android.Manifest.permission.READ_EXTERNAL_STORAGE', 'android.permission.WRITE_EXTERNAL_STORAGE' ],
           function (e) {
               if (e.success) {
                   tempFile.write(this.responseData);
                   try{
                       Ti.Android.currentActivity.startActivity(Ti.Android.createIntent({
                           action: Ti.Android.ACTION_VIEW,
                           type: 'application/pdf',
                           data: appfilepath
                       }));
                   } catch(e) {
                       Ti.API.info('error trying to launch activity, e = '+e);
                       alert('No PDF apps installed!');
                   }
               } else {
                   Ti.API.error('could not obtain required storage permissions!');
               }
           }
       );
       

JSON Source