I installed this library to view pdf from a url inside my application but when I click on the file to open it gives me the following error:
I tried looking into ContentResolver but no luck
This is the logcat:
07-26 15:35:45.638 8725-8725/com.focuson.iapp.firstapp E/PDFView: load pdf error
java.io.FileNotFoundException: No content provider: http://pub.mylaravel.eu/assets/user_files/3/file_no_1.pdf
at android.content.ContentResolver.openTypedAssetFileDescriptor(ContentResolver.java:1093)
at android.content.ContentResolver.openAssetFileDescriptor(ContentResolver.java:944)
at android.content.ContentResolver.openFileDescriptor(ContentResolver.java:797)
at android.content.ContentResolver.openFileDescriptor(ContentResolver.java:751)
at com.github.barteksc.pdfviewer.DecodingAsyncTask.getSeekableFileDescriptor(DecodingAsyncTask.java:82)
at com.github.barteksc.pdfviewer.DecodingAsyncTask.doInBackground(DecodingAsyncTask.java:61)
at com.github.barteksc.pdfviewer.DecodingAsyncTask.doInBackground(DecodingAsyncTask.java:30)
at android.os.AsyncTask$2.call(AsyncTask.java:295)
at java.util.concurrent.FutureTask.run(FutureTask.java:237)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588)
at java.lang.Thread.run(Thread.java:818)
My activity is:
public class pdfActivity extends AppCompatActivity {
PDFView pdfView;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_pdf);
pdfView= (PDFView) findViewById(R.id.pdfView);
String url=getIntent().getStringExtra("url");
Log.i("URI-URL",String.valueOf(Uri.parse(url)) );
pdfView.fromUri(Uri.parse(url))
.enableSwipe(true)
.enableDoubletap(true)
.swipeVertical(false)
.defaultPage(1)
.showMinimap(false)
.onLoad(new OnLoadCompleteListener() {
#Override
public void loadComplete(int nbPages) {
}
})
.onPageChange(new OnPageChangeListener() {
#Override
public void onPageChanged(int page, int pageCount) {
}
})
.enableAnnotationRendering(false)
.password(null)
.load();}}
My xml is:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.focuson.iapp.firstapp.page_types.Login.pdfActivity">
<com.github.barteksc.pdfviewer.PDFView
android:id="#+id/pdfView"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</RelativeLayout>
Seems that this library fails to download files from the internet. Download the file to a temp directory and open it:
if (ActivityCompat.checkSelfPermission(WebViewActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED
&& ActivityCompat.checkSelfPermission(WebViewActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(WebViewActivity.this,
new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
MY_PERMISSIONS_REQUEST_WRITE_EXTERNAL_STORAGE);
} else {
downloadFile();
}
#Override
public void onRequestPermissionsResult(int requestCode,
String permissions[], int[] grantResults) {
switch (requestCode) {
case MY_PERMISSIONS_REQUEST_WRITE_EXTERNAL_STORAGE:
downloadFile();
break;
}
}
private void downloadFile() {
progressBar.setVisibility(View.VISIBLE);
DownloadFileTask task = new DownloadFileTask(
WebViewActivity.this,
mURL,
"/download/pdf_file.pdf");
task.startTask();
}
#Override
public void onFileDownloaded() {
progressBar.setVisibility(View.GONE);
File file = new File(Environment.getExternalStorageDirectory()
.getAbsolutePath()
+ "/download/pdf_file.pdf");
if (file.exists()) {
pdfView.fromFile(file)
//.pages(0, 2, 1, 3, 3, 3) // all pages are displayed by default
.enableSwipe(true)
.swipeHorizontal(true)
.enableDoubletap(true)
.defaultPage(0)
.enableAnnotationRendering(true)
.password(null)
.scrollHandle(null)
.onLoad(new OnLoadCompleteListener() {
#Override
public void loadComplete(int nbPages) {
pdfView.setMinZoom(1f);
pdfView.setMidZoom(5f);
pdfView.setMaxZoom(10f);
pdfView.zoomTo(2f);
pdfView.scrollTo(100,0);
pdfView.moveTo(0f,0f);
}
})
.load();
}
}
public class DownloadFileTask {
public static final String TAG = "DownloadFileTask";
private BaseActivity context;
private GetTask contentTask;
private String url;
private String fileName;
public DownloadFileTask(BaseActivity context, String url, String fileName) {
this.context = context;
this.url = url;
this.fileName = fileName;
}
public void startTask() {
doRequest();
}
private void doRequest() {
contentTask = new GetTask();
contentTask.execute();
}
private class GetTask extends AsyncTask<String, Integer, String> {
#Override
protected String doInBackground(String... arg0) {
int count;
try {
Log.d(TAG, "url = " + url);
URL _url = new URL(url);
URLConnection conection = _url.openConnection();
conection.connect();
InputStream input = new BufferedInputStream(_url.openStream(),
8192);
OutputStream output = new FileOutputStream(
Environment.getExternalStorageDirectory() + fileName);
byte data[] = new byte[1024];
while ((count = input.read(data)) != -1) {
output.write(data, 0, count);
}
output.flush();
output.close();
input.close();
} catch (Exception e) {
Log.e("Error: ", e.getMessage());
}
return null;
}
protected void onPostExecute(String data) {
context.onFileDownloaded();
}
}
}
Uri is not like URL :here
You must download first the *.pdf file and save to SD and finaly you can open it with Pdfview.
No content provider: http://...
It's not clear where you read that the library can download and display a PDF from a network request. A URI can mean many things, and in this case, it is trying to use a ContentProvider to load a raw PDF file from disk.
You can look at the Github repo for that library for sample usage of the URI.
Related
So I am trying to store a PDF file on the user's android device by creating a Folder and then storing it. I am using getExternalStorageDir() but this has been deprecated under API29. The problem is Andriod guidelines say to opt-out out of scoped storage I have to put this in Manifest File
<manifest xmlns:android="http://schemas.android.com/apk/res/android
....
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<application
android:requestLegacyExternalStorage="true"
....
</application>
This is not working anymore. I can download on Devices with andriod M but Not able to in recent 9/10 devices.
public class FinalActivity extends AppCompatActivity implements EasyPermissions.PermissionCallbacks {
private static final int WRITE_REQUEST_CODE = 300;
private static final String TAG = MainActivity.class.getSimpleName();
private String url;
SessionManagement sessionManagement;
String userID;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_final);
sessionManagement = new SessionManagement(this);
HashMap<String, String> user = sessionManagement.getUserDetail();
userID = user.get(sessionManagement.ID);
TextView submit = findViewById(R.id.download);
submit.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (EasyPermissions.hasPermissions(FinalActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
//Get the URL entered
url = F.url1 + userID + "/FPO.pdf";
new DownloadFile().execute(url.replaceAll(" ", "%20"));
} else {
//If permission is not present request for the same.
EasyPermissions.requestPermissions(FinalActivity.this, "This app needs access to your file storage so that it can write files.", WRITE_REQUEST_CODE, Manifest.permission.READ_EXTERNAL_STORAGE);
}
}
});
}
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, FinalActivity.this);
}
#Override
public void onPermissionsGranted(int requestCode, List<String> perms) {
//Download the file once permission is granted
url = F.url1 + userID + "/FPO.pdf";
new DownloadFile().execute(url.replaceAll(" ", "%20"));
}
#Override
public void onPermissionsDenied(int requestCode, List<String> perms) {
Log.d(TAG, "Permission has been denied");
}
private class DownloadFile extends AsyncTask<String, String, String> {
private ProgressDialog progressDialog;
private String fileName;
private String folder;
private boolean isDownloaded;
#Override
protected void onPreExecute() {
super.onPreExecute();
this.progressDialog = new ProgressDialog(FinalActivity.this);
this.progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
this.progressDialog.setCancelable(false);
this.progressDialog.show();
}
#Override
protected String doInBackground(String... f_url) {
int count;
try {
URL url = new URL(f_url[0]);
URLConnection connection = url.openConnection();
connection.connect();
// getting file length
int lengthOfFile = connection.getContentLength();
// input stream to read file - with 8k buffer
InputStream input = new BufferedInputStream(url.openStream(), 8192);
String timestamp = new SimpleDateFormat("yyyy.MM.dd.HH.mm.ss").format(new Date());
//Extract file name from URL
fileName = f_url[0].substring(f_url[0].lastIndexOf('/') + 1, f_url[0].length());
//External directory path to save fileb n
folder = Environment.getExternalStorageDirectory() + File.separator + "FPO/";
//Create LSK folder if it does not exist
File directory = new File(folder);
if (!directory.exists()) {
directory.mkdirs();
}
// Output stream to write file
OutputStream output = new FileOutputStream(folder + fileName.replaceAll("%20", " "));
byte data[] = new byte[1024];
long total = 0;
while ((count = input.read(data)) != -1) {
total += count;
// publishing the progress....
// After this onProgressUpdate will be called
publishProgress("" + (int) ((total * 100) / lengthOfFile));
Log.d(TAG, "Progress: " + (int) ((total * 100) / lengthOfFile));
// writing data to file
output.write(data, 0, count);
}
// flushing output
output.flush();
// closing streams
output.close();
input.close();
return "Downloaded at: " + folder + fileName.replaceAll("%20", " ");
} catch (Exception e) {
Log.e("Error: ", e.getMessage());
Log.i("error123", e.getMessage());
return e.getMessage();
}
// return "Something went wrong";
}
protected void onProgressUpdate(String... progress) {
// setting progress percentage
progressDialog.setProgress(Integer.parseInt(progress[0]));
}
#Override
protected void onPostExecute(String message) {
// dismiss the dialog after the file was downloaded
this.progressDialog.dismiss();
Intent intent = new Intent(FinalActivity.this, Welcome_screen1.class);
startActivity(intent);
// Display File path after downloading
Toast.makeText(getApplicationContext(), message, Toast.LENGTH_LONG).show();
}
}
}
"Use getExternalFilesDir(), getExternalCacheDir(), or getExternalMediaDirs() (methods on Context) instead of Environment.getExternalStorageDirectory()."
Check this;
https://stackoverflow.com/a/57116787/5924743
After a bit of analysis. Here is my suggestion
//External directory path to save fileb n
folder = Environment.getExternalStoragePublicDirectory("FPO")+File.separator;// Deprecated I know but it works
//Create LSK folder if it does not exist
File file = new File(folder + fileName.replaceAll("%20"," "));// create file in particular path with name and extension
if (!file.exists()) {
file.createNewFile(); //creates file for writing
}
// Output stream to write file
OutputStream output = new FileOutputStream(file);
First create a File before starting to write using OutputStream. Don't just create directory.
Hope helpful!
I am using chat application. Upto Android 28sdk its worked fine but after i refract to androidx am facing this problem please check my code below and error screenshot.
Error Code Image 1
Error Code Image 2
private void compressAndUpload(final Context context, final String child, final File file) {
compressionTask = new AsyncTask<File, Void, String>() {
#Override
protected String doInBackground(File... files) {
String filePathCompressed = null;
Uri originalFileUri = Uri.fromFile(files[0]);
File tempFile = new File(context.getCacheDir(), originalFileUri.getLastPathSegment());
//tempFile = File.createTempFile(originalFileUri.getLastPathSegment(), null, context.getCacheDir());
if (child.equals("images")) {
filePathCompressed = SiliCompressor.with(context).compress(originalFileUri.toString(), tempFile);
} else {
try {
filePathCompressed = SiliCompressor.with(context).compressVideo(files[0].getPath(), context.getCacheDir().getPath());
} catch (URISyntaxException e) {
e.printStackTrace();
}
}
if (filePathCompressed == null)
filePathCompressed = "";
return filePathCompressed;
}
#Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
File compressed = new File(s);
fileUri = Uri.fromFile(compressed.length() > 0 ? compressed : file);
FirebaseStorage storage = FirebaseStorage.getInstance();
if (uploadRef == null)
uploadRef = storage.getReference().child(child).child(fileUri.getLastPathSegment());
if (replace) {
upload();
} else {
checkIfExists();
}
}
};
compressionTask.execute(file);
}
I've made an app for downloading a pdf file from direct link to internal storage. When I try to download a direct link of google drive link it works fine, if the file is less than 3MB. But if the file is more than 3MB, it is not downloaded. Here is my code below:
public class MainActivity extends AppCompatActivity {
private final String Pdf_LINK =
("https://drive.google.com/uc?export=download&id=13mE9gCyTGmLrFOZqu6Lz-yz0mcfjGoJc");
private final String My_PDF ="my100.pdf";
private AppCompatSeekBar seekBar;
private PDFView pdfView;
private TextView txtView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
pdfView = findViewById(R.id.pdfView);
txtView = findViewById(R.id.txtView);
initSeekar();
downloadpdf(My_PDF);
}
private void initSeekar(){
seekBar = findViewById(R.id.seeBar);
seekBar.getProgressDrawable().setColorFilter(Color.RED, PorterDuff.Mode.SRC_IN);
seekBar.getThumb().setColorFilter(Color.RED,PorterDuff.Mode.SRC_IN);
seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
#Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
int val = (progress * (seekBar.getWidth() - 3 * seekBar.getThumbOffset())) / seekBar.getMax();
txtView.setText("" + progress);
txtView.setX(seekBar.getX() + val + seekBar.getThumbOffset() / 2);
}
#Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
#Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
});
}
private void downloadpdf(final String fileName) {
new AsyncTask<Void, Integer, Boolean>() {
#Override
protected Boolean doInBackground(Void... params) {return downloadpdf();}
#Nullable
private Boolean downloadpdf() {
try {
File file = getFileStreamPath(fileName);
if (file.exists())
return true;
try {
FileOutputStream fileOutputStream = openFileOutput(fileName, Context.MODE_PRIVATE);
URL u = new URL(Pdf_LINK);
URLConnection conn = u.openConnection();
int contentLength = conn.getContentLength();
InputStream input = new BufferedInputStream(u.openStream());
byte data[] = new byte[contentLength];
long total = 0;
int count;
while ((count = input.read(data)) != -1) {
total += count;
publishProgress((int) ((total * 100) / contentLength));
fileOutputStream.write(data, 0, count);
}
fileOutputStream.flush();
fileOutputStream.close();
input.close();
return true;
} catch (final Exception e) {
e.printStackTrace();
return false;
}
} catch (Exception e) {
e.printStackTrace();
}
return false;
}
#Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
seekBar.setProgress(values[0]);
}
#Override
protected void onPostExecute(Boolean aBoolean) {
super.onPostExecute(aBoolean);
if (aBoolean) {
openPdf(fileName);
} else {
Toast.makeText(MainActivity.this, "Unable to download this file", Toast.LENGTH_SHORT).show();
}
}
}.execute();
}
private void openPdf(String fileName) {
try {
File file = getFileStreamPath(fileName);
Log.e("file", "file: " + file.getAbsolutePath());
seekBar.setVisibility(View.GONE);
pdfView.setVisibility(View.VISIBLE);
pdfView.fromFile(file)
.enableSwipe(true)
.swipeHorizontal(false)
.load();
} catch (Exception e) {
e.printStackTrace();
}
}
}
What is the error in this code? How can I solve this? If I try to download a pdf file from another site, it works well. But the problem is only, when trying to download from google drive. please help me.
I was able to download large public shareable files from google drive.
Use the URL:
https://drive.google.com/uc?id=<FILE_ID>&export=download
Replace <FILE_ID> with your shareable file ID.
I used the code in 'private class DownloadTask'
in this solution:
Download a file with Android, and showing the progress in a ProgressDialog
The code inside the doInBackground function works, I modified it for my own needs, used ProgressBar instead. I am not posting my code since it's too long.
Hope you can solve your problem.
Android: FTP client file transfer in passive mode taking time to close connection after 100% upload
While transferring files through FTP client, in passive mode, we are using async task.
Even after the progress update specified 100% of the file has been uploaded, still ftp connection holds async task from coming to on post execute.
The time taken is directly proportional to Internet speed and size of the file uploaded.
Tried with standalone application to upload zip files,
Tried ftp both in active and passive modes.
Still the issue persists.
public class UploadZipFiles extends AsyncTask<Object, Integer, Object> {
ArrayList<String> zipFiles;
String userName, password;
WeakReference<ServiceStatusListener> listenerReference;
private Context mContext;
private long totalFileSize = 0;
protected long totalTransferedBytes = 0;
final NumberFormat nf = NumberFormat.getInstance();
private CustomFtpClient ftpClient = null;
public UploadZipFiles(Context mContext, ServiceStatusListener listener,
ArrayList<String> zipFiles, String userName, String password) {
Log.d("u and p", "" + userName + "=" + password);
this.mContext = mContext;
this.zipFiles = zipFiles;
this.userName = userName;
this.password = password;
this.listenerReference = new WeakReference<ServiceStatusListener>(
listener);
nf.setMinimumFractionDigits(2);
nf.setMaximumFractionDigits(2);
}
#Override
protected void onPreExecute() {
super.onPreExecute();
// getting total size of the file
for (String file : zipFiles) {
totalFileSize = totalFileSize + new File(file).length();
}
}
#Override
protected Object doInBackground(Object... arg0) {
ftpClient = new CustomFtpClient();
try {
ftpClient.connect(ftpUrl, 21);
ftpClient.login(userName, password);
ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);
for (String file : zipFiles) {
InputStream in;
in = new FileInputStream(new File(file));
ftpClient.storeFile(new File(file).getName(), in);
in.close();
}
} catch (IOException e1) {
e1.printStackTrace();
}
return "Success";
}
#Override
protected void onPostExecute(Object result) {
if (result instanceof Exception) {
listenerReference.get().onFailure(
new Exception(result.toString()));
} else {
listenerReference.get().onSuccess("Success");
}
}
#Override
protected void onProgressUpdate(Integer... values) {
int uploadProgress = ((float) values[0] / totalFileSize) * 100);
//Some code to show loader
.......
}
/** Custom client to publish progress **/
public class CustomFtpClient extends FTPClient {
public boolean storeFile(String remote, InputStream local)
throws IOException {
final OutputStream output;
final Socket socket;
if ((socket = _openDataConnection_(FTPCommand.STOR, remote)) == null)
return false;
output = new BufferedOutputStream(socket.getOutputStream(),
getBufferSize());
try {
Util.copyStream(local, output, getBufferSize(),
CopyStreamEvent.UNKNOWN_STREAM_SIZE,
new CopyStreamListener() {
#Override
public void bytesTransferred(
long totalBytesTransferred,
int bytesTransferred, long streamSize) {
totalTransferedBytes = totalTransferedBytes
+ bytesTransferred;
publishProgress((int) totalTransferedBytes);
if (totalTransferedBytes == totalFileSize) {
Log.d(TAG, "upload completed");
}
}
#Override
public void bytesTransferred(
CopyStreamEvent arg0) {
// TODO Auto-generated method stub
}
});
} catch (IOException e) {
try {
socket.close();
} catch (IOException f) {
}
throw e; }
output.close();
socket.close();
return completePendingCommand();
}
}
}
I have two AsyncTasks, one is used to download xml file (DownloadTask), another is for parsing the file (ParseXMLTask).
There are two cases of using this tasks:
1) File doesn't exists > execute DownloadTask, onPostExecute > ParseXMLTask
2) File exists > execute only ParseXMLTask.
Everything is working, but the thing is, while performing the second case, there is a blocking the ui about 3 sec (black screen) that surely would make a user annoyed. This is absolutely confusing me, because the job in the second case seems to be easier.
So when I am testing my app, a situation is like that: I click on the button for the first time, file is being downloaded, saved on the sd card, parsed and finally opened. Then I go back and click on the button again. Now I see that lag while switching between activities.
Code:
Executing the tasks
private void downloadPack() {
if (packDownloaded) {
parseXML();
} else {
download = new DownloadFile(fileName, this, loadingBar);
download.execute(serverURL + fileName + ".xml");
}
}
private void parseXML() {
ParseXMLTask parseTask = new ParseXMLTask(this, this);
parseTask.execute(PATH + fileName + ".xml");
}
public void postDownload(File result) {
parseXML();
}
public void postParse() {
Intent packIntent = new Intent(this, PackActivity.class);
startActivity(packIntent);
}
ParseXMLTask.java
public class ParseXMLTask extends AsyncTask<String, Integer, Void> {
private Context context;
private XmlPullParser xpp;
private IPostParse iPostParse;
public ParseXMLTask(Context context, IPostParse iPostParse) {
this.context = context;
this.iPostParse = iPostParse;
}
#Override
protected Void doInBackground(String... params) {
File file = new File(params[0]);
/* doing the job */
}
#Override
protected void onPostExecute(Intent result) {
iPostParse.postParse(result);
}
}
DownloadFile.java
public class DownloadFile extends AsyncTask<String, Integer, File> {
private static final String PATH = Environment
.getExternalStorageDirectory().getPath() + "/.chgkgame/";;
private File dir;
private ProgressBar progressBar;
private String fileName;
private IPostDownload postDownload;
private boolean download;
public DownloadFile(String name, IPostDownload pDownload, ProgressBar pBar) {
progressBar = pBar;
fileName = name;
postDownload = pDownload;
}
#Override
protected File doInBackground(String... sUrl) {
URL url;
try {
url = new URL(sUrl[0]);
URLConnection urlConnection = url.openConnection();
urlConnection.connect();
int fileLength = urlConnection.getContentLength();
dir = new File(PATH + fileName + ".xml");
InputStream input = new BufferedInputStream(url.openStream());
OutputStream output = new FileOutputStream(dir);
byte[] data = new byte[1024];
long total = 0;
int count;
while ((count = input.read(data)) != -1) {
total += count;
publishProgress((int) (total * 100 / fileLength));
output.write(data, 0, count);
}
output.flush();
output.close();
input.close();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return dir;
}
#Override
protected void onPostExecute(File result) {
if (postDownload != null) postDownload.postDownload(result);
}
#Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
if (progressBar != null) {
progressBar.setProgress(values[0]);
}
}
}
There is nothing wrong with the above.
The parsing is pretty fast that is why you only see the layout for a split second.
The black screen will be the PackActivity loading, check this activity for what is blocking the UI thread.
You could have also put LogCat messages in to show that the parsing has finished and onCreate of the next Activity is called.