How to show a pdf file from storage using AndroidPdfViewer library? - java

I want to load a pdf file from external storage (Download/Pdfs/myfile.pdf) using AndroidPdfViewer but it shows blank screen without any error. I tried lots of ways but it's not working.
public class PdfViewActivity2 extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
File path = new File(Environment.getExternalStorageDirectory().getPath() + "/Download/Pdfs/myfile.pdf");
PDFView pdfView = findViewById(R.id.pdfView);
pdfView.fromFile(path).load();
I have a pdf file in my "Download/Pdfs/myfile.pdf" and i used the above code to load the file but it's not working.
I have given storage permission manually from settings.
Can anyone please correct me where i am making a mistake.

I have tested your code and it works just fine on Android 10 device. Your are missing something from the below:
1.In Android Manifest File add the READ_EXTERNAL_STORAGE permission
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
and inside application tag add requestLegacyExternalStorage to true to be able to have access on External Storage on Android 10 device and above.
<application
android:requestLegacyExternalStorage="true"
2.Verify that the pdf exists on the device under "/Download/Pdfs/myfile.pdf" path.
3.Change your activity using the below code by requesting External Storage permission at runtime first in onCreate method:
public class PdfViewActivity2 extends AppCompatActivity {
private static final int READ_STORAGE_PERMISSION_REQUEST_CODE = 1000;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//check if Read External Storage permission was granded
boolean granded = checkPermissionForReadExtertalStorage();
if(!granded){
requestPermissionForReadExtertalStorage();
}
else {
readPdf();
}
}
public boolean checkPermissionForReadExtertalStorage() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
int result = checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE);
return result == PackageManager.PERMISSION_GRANTED;
}
return false;
}
public void requestPermissionForReadExtertalStorage() {
try {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, READ_STORAGE_PERMISSION_REQUEST_CODE);
} catch (Exception e) {
e.printStackTrace();
}
}
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
switch (requestCode) {
case READ_STORAGE_PERMISSION_REQUEST_CODE: {
// If request is cancelled, the result arrays are empty.
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// permission was granted. Read Pdf from External Storage
readPdf();
} else {
// permission denied. Disable the functionality that depends on this permission.
}
}
}
}
private void readPdf(){
File path = new File(Environment.getExternalStorageDirectory().getPath() + "/Download/Pdfs/myfile.pdf");
PDFView pdfView = findViewById(R.id.pdfView);
pdfView.fromFile(path).load();
}
}

First, add the library to your build.gradle file
implementation 'com.github.barteksc:android-pdf-viewer:2.8.2'
To open a PDF file from storage, use this code. There are comments that explain what it does.
public class PdfViewActivity2 extends AppCompatActivity {
// Declare PDFView variable
private PDFView pdfView;
private final int PDF_SELECTION_CODE = 99;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Initialize it
pdfView = findViewById(R.id.pdfView);
// Select PDF from storage
// This code can be used in a button
Toast.makeText(this, "selectPDF", Toast.LENGTH_LONG).show();
Intent browseStorage = new Intent(Intent.ACTION_GET_CONTENT);
browseStorage.setType("application/pdf");
browseStorage.addCategory(Intent.CATEGORY_OPENABLE);
startActivityForResult(Intent.createChooser(browseStorage, "Select PDF"), PDF_SELECTION_CODE);
}
// Get the Uniform Resource Identifier (Uri) of your data, and receive it as a result.
// Then, use URI as the pdf source and pass it as a parameter inside this method fromUri(Uri uri)
#Override
protected void onActivityResult(int requestCode, int resultCode, #Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == PDF_SELECTION_CODE && resultCode == Activity.RESULT_OK && data != null) {
Uri selectedPdfFromStorage = data.getData();
pdfView.fromUri(selectedPdfFromStorage).defaultPage(0).load();
}
}
}

In an Android 10 device your app has no access to external storage.
Unless you add
android:requestLegacyExternalStorage="true"
in application tag of manifest file.

Instead of using fromFile() use fromSource(). i.e. Declare pathe as DocumentSource instead of File.
public class PdfViewActivity2 extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
DocumentSource path = new File(Environment.getExternalStorageDirectory().getPath() + "/Download/myfile.pdf");
PDFView pdfView = findViewById(R.id.pdfView);
pdfView.fromSource(path).load();

Related

How to use system_alert_window popup in java

I need to have my app draw over other apps, and I tried getting SYSTEM_ALERT_WINDOW permission shown below.
public class excessiveusageactivity extends AppCompatActivity {
static final int REQUEST_OVERLAY_PERMISSION = 1; //request code
TextView result;
#Override
protected void onActivityResult(int requestCode, int resultCode, #Nullable Intent data) {
result = findViewById(R.id.result);
if (requestCode == REQUEST_OVERLAY_PERMISSION) {
if (Settings.canDrawOverlays(this)) {
Toast permissionok = Toast.makeText(this, "permission granted!", Toast.LENGTH_SHORT);
permissionok.show();
//permission granted do stuff
result.setText("yay");
}else{
Toast permissionnotgrantedtoast = Toast.makeText(this,"permission request failed, try again!", Toast.LENGTH_LONG);
permissionnotgrantedtoast.show();
//permission not granted
result.setText("not granted");
}
}
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_excessiveusageactivity);
if(
Settings.canDrawOverlays(this)
) {
// ask for overlay permission
Intent requestoverlaypermissionintent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
Uri.parse("package:" + getPackageName()));
startActivityForResult(requestoverlaypermissionintent, REQUEST_OVERLAY_PERMISSION);
result.setText("here");
}
}
}
I got this code from here by user Jayman Jani.
I wish to make a custom system alert popup when the user uses an app for X minutes/hour consecutively, but I can't seem to find any information on how to set up this popup. I am quite new to all this so it would be great if someone can explain it mostly step-by-step. Thank you!

onActivityResult always returning not authorized

I'm trying to just sign a user to the app to be able to use Google Drive API, but in my activityResults I always get the else statement and that means the user is not authorized or the sign in have failed. Why might this be? I have followed the official docs.
Here is my code:
private static final int REQUEST_CODE_SIGN_IN = 0;
private DriveClient mDriveClient;
private DriveResourceClient mDriveResourceClient;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
signIn();
}
private void initializeDriveClient(GoogleSignInAccount signInAccount) {
mDriveClient = Drive.getDriveClient(getApplicationContext(), signInAccount);
mDriveResourceClient = Drive.getDriveResourceClient(getApplicationContext(), signInAccount);
}
/**
* Starts the sign-in process and initializes the Drive client.
*/
private void signIn() {
Set<Scope> requiredScopes = new HashSet<>(2);
requiredScopes.add(Drive.SCOPE_FILE);
requiredScopes.add(Drive.SCOPE_APPFOLDER);
GoogleSignInAccount signInAccount = GoogleSignIn.getLastSignedInAccount(this);
if (signInAccount != null && signInAccount.getGrantedScopes().containsAll(requiredScopes)) {
initializeDriveClient(signInAccount);
} else {
GoogleSignInOptions signInOptions =
new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
.requestScopes(Drive.SCOPE_FILE)
.requestScopes(Drive.SCOPE_APPFOLDER)
.build();
GoogleSignInClient googleSignInClient = GoogleSignIn.getClient(this, signInOptions);
startActivityForResult(googleSignInClient.getSignInIntent(), REQUEST_CODE_SIGN_IN);
}
}
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode) {
case REQUEST_CODE_SIGN_IN:
if (resultCode == Activity.RESULT_OK) {
// App is authorized, you can go back to sending the API request
Log.e("SignIn", "App autorizada");
} else {
// User denied access, show him the account chooser again
Log.e("SignIn", "App No Autorizada");
finish();
}
break;
}
super.onActivityResult(requestCode, resultCode, data);
}
Solved my own problem pasting the SHA1 and package name into credentials in my google console, it seemed i was doing something wrong with the credentials.
Code looks fine. Check if you have added google_services.json file in the project. Also check if th SHA1 key is correct.

java.lang.SecurityException: was not granted this permission: android.permission.WRITE_SETTINGS

I going to change some system setting in android and i use this code :
ContentResolver cr = getContentResolver();
Settings.System.putInt(cr, Settings.System.HAPTIC_FEEDBACK_ENABLED, 0);
this code used for change screen Brightness use Brightness sensor,
but in android 6 I get this exception
java.lang.SecurityException: com.vpn.sabalan was not granted this permission: android.permission.WRITE_SETTINGS.
i can use this method to get permission from user , but i need get permission programmetically can any one help me ?
private void showBrightnessPermissionDialog( )
{
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !android.provider.Settings.System.canWrite(this))
{
Intent intent = new Intent(android.provider.Settings.ACTION_MANAGE_WRITE_SETTINGS);
intent.setData(Uri.parse("package:"+getPackageName()));
startActivity(intent);
}
}
Update Android Marshmallow and Higher
You can start System settings to grant Write System Settings. Once this permission is grant by user you can set brightness without any issues
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (Settings.System.canWrite(this)) {
Intent intent = new Intent(Settings.ACTION_MANAGE_WRITE_SETTINGS);
intent.setData(Uri.parse("package:" + getPackageName()));
startActivity(intent);
}
}
Follow the step by step provided in documentation. It is very thorough.
https://developer.android.com/training/permissions/requesting.html
All you have to do is request permission, and override the callback for onRequestPermissionsResult to check if you got it or not. If you did, then you are good to go. You still need it in your manifest though or it won't work.
UPDATE to show details based on your comments.
public class MainActivity extends AppCompatActivity implements ActivityCompat.OnRequestPermissionsResultCallback{
private static final int REQUEST_WRITE_PERMISSION = 1001;
#Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
if (requestCode == REQUEST_WRITE_PERMISSION && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
doFileWork();
}else{
//handle user denied permission, maybe dialog box to user
}
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
requestPermission();
}
private void requestPermission() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
requestPermissions(new String[]{android.Manifest.permission.WRITE_EXTERNAL_STORAGE}, REQUEST_WRITE_PERMISSION);
} else {
doFileWork();
}
}
}
There are also many good libraries out there that wrap this callback context if you really want to go that route, but it isn't that complex. Make sure you also have write permission in your Manifest.

Android runtime permissions- how to implement

Android Developer Documentation gives this example of requesting permissions at runtime:
// Here, thisActivity is the current activity
if (ContextCompat.checkSelfPermission(thisActivity,
Manifest.permission.READ_CONTACTS)
!= PackageManager.PERMISSION_GRANTED) {
// Should we show an explanation?
if (ActivityCompat.shouldShowRequestPermissionRationale(thisActivity,
Manifest.permission.READ_CONTACTS)) {
// Show an expanation to the user *asynchronously* -- don't block
// this thread waiting for the user's response! After the user
// sees the explanation, try again to request the permission.
} else {
// No explanation needed, we can request the permission.
ActivityCompat.requestPermissions(thisActivity,
new String[]{Manifest.permission.READ_CONTACTS},
MY_PERMISSIONS_REQUEST_READ_CONTACTS);
// MY_PERMISSIONS_REQUEST_READ_CONTACTS is an
// app-defined int constant. The callback method gets the
// result of the request.
}
}
What is "MY_PERMISSIONS_REQUEST_READ_CONTACTS" in this example? It says it's an app-defined int constant, but does that mean I should make a Constants.java and declare a public static int? What should the value be?
In other examples I see people use 1 here, or 0 or 0xFFEEDDCC, but I can't find an explanation of what it is. Can someone explain to me what needs to go here and why? (In my case, I need to make sure the app has permission to access fine location)
The ActivityCompat documentation says "Application specific request code to match with a result reported to onRequestPermissionsResult"? This does not help me.
What is "MY_PERMISSIONS_REQUEST_READ_CONTACTS" in this example?
It is an int, to tie a particular requestPermissions() call to the corresponding onRequestPermissionsResult() callback.
Under the covers, requestPermissions() uses startActivityForResult(); this int serves the same role as it does in startActivityForResult().
does that mean I should make a Constants.java and declare a public static int?
I would just make it a private static final int in the activity. But, you can declare it wherever you want.
What should the value be?
I seem to recall that it needs to be below 0x8000000, but otherwise it can be whatever you want. The value that you use for each requestPermissions() call in an activity should get a distinct int, but the actual numbers do not matter.
If your activity has only one requestPermissions() call, then the int value really does not matter. But many apps will have several requestPermissions() calls in an activity. In that case, the developer may need to know, in onRequestPermissionsResult(), what request this is the result for.
Look just a little further down in the documentation under "Handle the permissions request response" and you will see its purpose.
A callback method called onRequestPermissionsResult gets sent back the same code as a parameter so you know which permission was being requested/granted:
#Override
public void onRequestPermissionsResult(int requestCode,
String permissions[], int[] grantResults) {
switch (requestCode) {
case MY_PERMISSIONS_REQUEST_READ_CONTACTS: {
// If request is cancelled, the result arrays are empty.
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// permission was granted, yay! Do the
// contacts-related task you need to do.
} else {
// permission denied, boo! Disable the
// functionality that depends on this permission.
}
return;
}
// other 'case' lines to check for other
// permissions this app might request
}
}
Since the constant is used by you only you can give it whatever value you like as a public static final int. Each permission being requested needs its own constant.
I went through all answers, but doesn't satisfied my exact needed answer, so here is an example that I wrote and perfectly works, even user clicks the Don't ask again checkbox.
Create a method that will be called when you want to ask for runtime permission like readContacts() or you can also have openCamera() as shown below:
private void readContacts() {
if (!askContactsPermission()) {
return;
} else {
queryContacts();
} }
Now we need to make askContactsPermission(), you can also name it as askCameraPermission() or whatever permission you are going to ask.
private boolean askContactsPermission() {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
return true;
}
if (checkSelfPermission(READ_CONTACTS) == PackageManager.PERMISSION_GRANTED) {
return true;
}
if (shouldShowRequestPermissionRationale(READ_CONTACTS)) {
Snackbar.make(parentLayout, R.string.permission_rationale, Snackbar.LENGTH_INDEFINITE)
.setAction(android.R.string.ok, new View.OnClickListener() {
#Override
#TargetApi(Build.VERSION_CODES.M)
public void onClick(View v) {
requestPermissions(new String[]{READ_CONTACTS}, REQUEST_READ_CONTACTS);
}
}).show();
} else if (contactPermissionNotGiven) {
openPermissionSettingDialog();
} else {
requestPermissions(new String[]{READ_CONTACTS}, REQUEST_READ_CONTACTS);
contactPermissionNotGiven = true;
}
return false;
}
Before writing this function make sure you have defined the below instance variable as shown:
private View parentLayout;
private boolean contactPermissionNotGiven;;
/**
* Id to identity READ_CONTACTS permission request.
*/
private static final int REQUEST_READ_CONTACTS = 0;
Now final step to override the onRequestPermissionsResult method as shown below:
/**
* Callback received when a permissions request has been completed.
*/
#RequiresApi(api = Build.VERSION_CODES.M)
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions,
#NonNull int[] grantResults) {
if (requestCode == REQUEST_READ_CONTACTS) {
if (grantResults.length == 1 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
queryContacts();
}
}
}
Here we are done with the RunTime permissions, the addon is the openPermissionSettingDialog() which simply open the Setting screen if user have permanently disable the permission by clicking Don't ask again checkbox. below is the method:
private void openPermissionSettingDialog() {
String message = getString(R.string.message_permission_disabled);
AlertDialog alertDialog =
new AlertDialog.Builder(MainActivity.this, AlertDialog.THEME_DEVICE_DEFAULT_LIGHT)
.setMessage(message)
.setPositiveButton(getString(android.R.string.ok),
new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
Intent intent = new Intent();
intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
Uri uri = Uri.fromParts("package", getPackageName(), null);
intent.setData(uri);
startActivity(intent);
dialog.cancel();
}
}).show();
alertDialog.setCanceledOnTouchOutside(true);
}
What we missed ?
1. Defining the used strings in strings.xml
<string name="permission_rationale">"Contacts permissions are needed to display Contacts."</string>
<string name="message_permission_disabled">You have disabled the permissions permanently,
To enable the permissions please go to Settings -> Permissions and enable the required Permissions,
pressing OK you will be navigated to Settings screen</string>
Initializing the parentLayout variable inside onCreate method
parentLayout = findViewById(R.id.content);
Defining the required permission in AndroidManifest.xml
<uses-permission android:name="android.permission.READ_CONTACTS" />
The queryContacts method, based on your need or the runtime permission you can call your method before which the permission was needed. in my case I simply use the loader to fetch the contact as shown below:
private void queryContacts() {
getLoaderManager().initLoader(0, null, this);}
This works great happy coding :)
public class SplashActivity extends RuntimePermissionsActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_splash);
SplashActivity.super.requestAppPermissions(new
String[]{android.Manifest.permission.READ_PHONE_STATE,
Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.READ_EXTERNAL_STORAGE}, R.string.app_name
, 20);
}
#Override
public void onPermissionsGranted(int requestCode) {
try {
TelephonyManager tele = (TelephonyManager) getApplicationContext()
.getSystemService(Context.TELEPHONY_SERVICE);
String imei =tele.getDeviceId()
} catch (Exception e) {
e.printStackTrace();
}
}
public abstract class RuntimePermissionsActivity extends AppCompatActivity {
private SparseIntArray mErrorString;
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mErrorString = new SparseIntArray();
}
#Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
int permissionCheck = PackageManager.PERMISSION_GRANTED;
for (int permission : grantResults) {
permissionCheck = permissionCheck + permission;
}
if ((grantResults.length > 0) && permissionCheck == PackageManager.PERMISSION_GRANTED) {
onPermissionsGranted(requestCode);
} else {
finish();
}
}
public void requestAppPermissions(final String[] requestedPermissions,
final int stringId, final int requestCode) {
mErrorString.put(requestCode, stringId);
int permissionCheck = PackageManager.PERMISSION_GRANTED;
boolean shouldShowRequestPermissionRationale = false;
for (String permission : requestedPermissions) {
permissionCheck = permissionCheck + ContextCompat.checkSelfPermission(this, permission);
shouldShowRequestPermissionRationale = shouldShowRequestPermissionRationale || ActivityCompat.shouldShowRequestPermissionRationale(this, permission);
}
if (permissionCheck != PackageManager.PERMISSION_GRANTED) {
if (shouldShowRequestPermissionRationale) {
ActivityCompat.requestPermissions(RuntimePermissionsActivity.this, requestedPermissions, requestCode);
/*Snackbar.make(findViewById(android.R.id.content), stringId,
Snackbar.LENGTH_INDEFINITE).setAction("GRANT",
new View.OnClickListener() {
#Override
public void onClick(View v) {
ActivityCompat.requestPermissions(RuntimePermissionsActivity.this, requestedPermissions, requestCode);
}
}).show();*/
} else {
ActivityCompat.requestPermissions(this, requestedPermissions, requestCode);
}
} else {
onPermissionsGranted(requestCode);
}
}
public abstract void onPermissionsGranted(int requestCode);
}

Calling onActivityResult to determine when a file has been received

I have a WebActivity that sets a JavascriptInterface for a WebView, on the Interface I have created various methods to be called with Javascript for different tasks, one of them is to send a file through Bluetooth.
The file sends just fine, but I want to inform the user when the file has already been accepted and transmited completely on the other end.
I am trying to use onActivityResult on my main WebActivity and also have tried on the separate class that handles the Bluetooth transmission and has a method called on the JavascriptInterface but I am not getting any callback results after the file is succesfully sent:
//First attempt
public class WebActivity extends ActionBarActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
//some code here
//Here I set the interface
myWebView.addJavascriptInterface(new WebAppInterface(this), "Android");
}
#Override
protected void onActivityResult(int requestCode, int resultCode,
Intent data) {
if (requestCode == 0) {
//This message is shown after the file transfer has started but no
//finished
Toast.makeText(this, "File Sent", Toast.LENGTH_SHORT).show();
if(resultCode == Activity.RESULT_OK){
//It doesn't work here either I always get Activity.RESULT_CANCELED (0)
//flag afer the file transfer has started
}
}
}
}
//Second Attempt
public class BluetoothTasks {
//code here
private void startTransferIntent() {
//some more code here
Intent intent = new Intent();
intent.setAction(Intent.ACTION_SEND);
intent.setType("text/plain");
File file_to_transfer = new File(Environment.getExternalStorageDirectory() +
"/txtTransfer.txt");
intent.putExtra(Intent.EXTRA_STREAM,Uri.fromFile(file_to_transfer));
//some more code here
Activity act = (Activity) mContext;
act.startActivityForResult(intent, TRANSFER_RESULT);
}
protected void onActivityResult(int requestCode, int resultCode,
Intent data) {
if (requestCode == TRANSFER_RESULT) {
//Not working here either
//code that is not executed
}
}
}
Could you please tell me if there is a way to do this and if so how would be accomplished?. Thank you.

Categories