Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Updated targetSdkVersion and compileSdkVersion to 30 and Migrated from Support Library to AndroidX. #994

Merged
merged 28 commits into from May 2, 2021

Conversation

codegsaini
Copy link
Contributor

@codegsaini codegsaini commented Mar 25, 2021

As per Google Play’s target API level requirements, which states that -

New apps and app updates must target Android 10 (API level 29) or higher; except for Wear OS apps, which must target API level 28.

It is necessary to change targetSdkVersion from 28 to 29 or higher.

The first problem to do this :

Version 28 (intended for Android Pie and below) is the last version of the legacy support library. Because this project ( the app ) is using support library. It is the initial problem in order to update targetSdkVersion.

The solution for this initial problem :

As per Support Library Documentation, which states that -

With the release of Android 9.0 (API level 28) there is a new version of the support library called AndroidX which is part of Jetpack. The AndroidX library contains the existing support library and also includes the latest Jetpack components.

So, the project should be migrated from Support Library to AndroidX.

Is this solution enough?

As issue #973 and #989 comments that Image To PDF feature was stopped working after changing targetSdkVersion from 28 to 29, further work was to be done to resolves these mentioned issues.

Resolution of Issues #973 and #989 :

The problem is due to scoped storage concept of Google's new storage policy!

Problem?
As Google's new storage policy states that -

To give users more control over their files and to limit file clutter, apps that target Android 10 (API level 29) and higher are given scoped access into external storage, or scoped storage, by default.

What is scoped storage?
Scoped storage as its name suggest, it is the specific storage path or specific folder that user have chosen to save any data, files, etc.

Why google Introduced this storage policy?
When WRITE_EXTERNAL_STORAGE permission is granted by user then the app get full access to the entire storage. It can do anything with any file in the storage ( except other app's private storage ). And by this behaviour, you can understand how danger this permission is if given to any bad app.

What exactly this policy say?
Now, in API 29+, even if user granted WRITE_EXTERNAL_STORAGE permission, the app still not granted write access. Rather when the app wanted to write anything in the storage, the user will specifically have to choose a specific directory to save the file. It means app can't do anything with the storage without user's consent (neither can create folder nor can delete any).

What changed, Before policy vs After policy?

  • Before, any app with WRITE_EXTERNAL_STORAGE permission can do anything with storage.
  • Now, any app even with WRITE_EXTERNAL_STORAGE permission, can't do anything until user choose to give the permission to specific folder (SPECIFIC FOLDER NOT ENTIRE STORAGE).

More information at developer.android.com.
Thus, implementing scoped storage method to save pdf or images to storage will fix #973 , fix #989

Type of change

How Has This Been Tested?

  • ./gradlew assembleDebug assembleRelease
  • ./gradlew checkstyle

Successfully tested on :

  • Android 9 Pie (Redmi 6A API 28) --Physical device
  • Android 10 Q (Pixel 2 API 29) --Android Virtual Device(AVD)

Checklist:

  • Migrated to AndroidX
  • App targeted to API 30 (Thus satisfy Google requirement)
  • Solved scoped storage related issue in android 10 or higher ( api 29+)

Updated README.md

  • Added GIF of updated UI in screenshot folder ( image_to_pdf2.gif )
  • Delete GIF of previous UI in screenshot folder ( image_to_pdf.gif )

Additional note
Closed #975 (redundant issue), because it is not closed by issue opener even after being resolved.

A note on resolution of scoped storage issue

  • Optimized runtime permissions
  • Removed unnecessary permissions
  • Removed permission request from main activity because runtime permission should only be requested just before the action for which it is needed.
  • Camera permission is only needed in Qr scanner activity, so removed from other activities and fragments
  • In Api 29+, no permission is needed expect the camera permission ( keeping matisse library in exception because it only need READ_EXTERNAL_STORAGE permission.

@codeclimate
Copy link

codeclimate bot commented Mar 25, 2021

Code Climate has analyzed commit 1b82c4f and detected 0 issues on this pull request.

View more on Code Climate.

@Rautarchit001
Copy link

Rautarchit001 commented Mar 25, 2021

This have same problem which i told you earlier, it does not create PDF only application works fine but doesn't create pdf.

@codegsaini
Copy link
Contributor Author

codegsaini commented Mar 26, 2021

This have same problem which i told you earlier, it does not create PDF only application works fine but doesn't create pdf.

Actually I am not understanding the exact problem when you say 'it does not create pdf only app work fine'.

Please confirm step by step :

  • you can select image from storage?
  • Green tick appear after pressing create pdf button?
  • Open pdf button appear?
  • you can view pdf after pressing open pdf button?
  • Pdf saved in storage?

@Rautarchit001
Copy link

Yes we can select image and image get selected

Green tick also appear after processing

Open PDF also appear

After clicking view pdf it doesn't work showing error.

PDF is not saved on storage

@codegsaini
Copy link
Contributor Author

codegsaini commented Mar 26, 2021

I need more detailed understanding of this project to solve this scope storage issue to make it compatible with api 29+.
This may take some time. Thanks...

SideNote~
App must target to api 29 before August 2021 and must target to 30 before November 2021.

@Rautarchit001
Copy link

Same problem after clearing data
image

@Swati4star
Copy link
Owner

Swati4star commented Mar 27, 2021 via email

@codegsaini
Copy link
Contributor Author

codegsaini commented Mar 27, 2021

Hey Swati 👋,
As per the storage policy, in api29+ app does not have write permission to storage, even after granting WRITE_EXTERNAL_STORAGE permission.
So, in settings when we try to change location, FilePicker.class can't show/list directories because it doesn't have permission.
Thus,
While nothing will work,
All we have to do is to solve this problem by Storage Access Framework or somthing like that.

Gaurav

@Rautarchit001
Copy link

Yes same problem here, but we are giving storage permission why it required additional permission?

@codegsaini
Copy link
Contributor Author

codegsaini commented Mar 27, 2021

Please make it clear, this is not additional permission. I'm telling you why it is not additional permission -

  • WRITE_EXTERNAL_STORAGE permission is only needed to ask in API 28 and below, we don't even need to ask this permission in API 29 and above. As Android documentation states -

If your app targets Android 11, both the WRITE_EXTERNAL_STORAGE permission and the WRITE_MEDIA_STORAGE privileged permission no longer provide any additional access.

And this documentation states

If your app uses scoped storage, it should request storage-related permissions only for devices that run Android 9 (API level 28) or lower.

Kindly continue asking about it, until your every doubts are cleared :)
I'll try my best to clear your doubts.
Happy coding 👍

@Rautarchit001
Copy link

Thank you @codegsaini I understand that.

Can you check #989 here @AvneeshGupta1 has added his Repository link where he had converted this code to kotlin and updated target SDK also but in that project, there is no such error, pdf get created properly.

@codegsaini
Copy link
Contributor Author

Actually, I forgot to mention that android:requestLegacyExternalStorage="true" only work if targetSdkVersion is 29 and compileSdkversion is 29 as well.
And you getting this error because the version is set to 30.

You can temporarily solve the issue by android:requestLegacyExternalStorage="true" and targetSdkVersion =29", but I don't mentioned this trick earlier because it will only work till November 1, 2021. So we should find the future proof solution rather than using tricks.

As you can see in below image app must target to API 30 before november 2021

ScreenShot from PlayConsoleHelp which states that -

Screenshot (3)

@Rautarchit001
Copy link

Ohhh you are right, we should find solution for this

@codegsaini
Copy link
Contributor Author

Yup, I'm working on it...

@Swati4star
Copy link
Owner

@codegsaini - Any updates here?

@Swati4star Swati4star closed this Apr 9, 2021
@Swati4star Swati4star reopened this Apr 9, 2021
@codegsaini
Copy link
Contributor Author

codegsaini commented Apr 10, 2021

I'm sorry to say that I postponed the work due to personal reasons ( exams are ahead ). But for sure, I will figure out the solution before the google deadline of updating target SDK version. I will begin working on it as soon as my exams are over.
With apologize.
Thanks

Is it fine or should I give it time amid exams preparation?
SideNote~ I am ready to cut an hour or two from my sleep if this is urgent!👍

@codegsaini
Copy link
Contributor Author

Not a problem... I'm okay with your late reply and here to tell you that, I started working on it again and will be back with the solution soon(a day or two maybe).

@AvneeshGupta1
Copy link

It's very simple. We can not create folder on root directory but inside app we have created PdfFiles folder.
Out folder path should be something like.
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS).toString().

This will work. i will update the code in my branch today.

https://github.com/AvneeshGupta1/DocScanner/tree/main

@codegsaini
Copy link
Contributor Author

Hey Avneesh, Your welcome for mentioning it. Working on something same concept though, most probably tomorrow I'll be back here with a solution. Good luck for your update, Cheers...

@codegsaini
Copy link
Contributor Author

codegsaini commented Apr 14, 2021

As android has some public directories (i.e Alarm, DCIM, Downloads, Documents, Pictures, etc.), it allows app to save files in related public directory. And we can get the path of these public directories by getExternalStoragePublicDirectory().
But things also changed here since api 29, as it deprecate the direct access to the paths of these directories due to following reasons --

  • Any app can change other app's files stored in these public directories, either they can delete other app's property or can modify them and this can be dangerous if any bad app make its entry into the game thats why this method is now deprecated.

Because the app using getExternalStoragePublicDirectory() path for saving files, the android documentaion says --

This method was deprecated in API level 29.
To improve user privacy, direct access to shared/external storage devices is deprecated. When an app targets Build.VERSION_CODES.Q, the path returned from this method is no longer directly accessible to apps. Apps can continue to access content stored on shared/external storage by migrating to alternatives such as Context#getExternalFilesDir(String), MediaStore, or Intent#ACTION_OPEN_DOCUMENT.

So, undoubtedly this solution is still not future proof, As android can remove deprecated methods anytime.

What is the solution then? (Good question)

I'll be back with the solution after going through the android documentations and some (re)search on google.
In the meantime anyone is welcome to share suggestions.

(Edit 1)Update so far--
The solution moves around MediaStore API, as I never implemented this api before, I'm learning this api along with figuring out the solution. So there can be little delay. In the meantime suggestions are welcome.

The storage permission was removed by mistake in commit a5b916a and now it is implemented again.
@codegsaini
Copy link
Contributor Author

I will submit another pull request after solving issue #996. Until then you can merge this pull request. Although there are so many changes in the this pull request, You can ask me about any change in particular.
Thanks...

@Swati4star
Copy link
Owner

@codegsaini I was occupied somewhere for last couple of weeks. This PR looks good. I'll merge this one :)

@Swati4star Swati4star merged commit 8f6e855 into Swati4star:master May 2, 2021
@Ravipatel401
Copy link

I have checked and test the recent commit, Creating a PDF file is working perfectly but facing an issue in Add Password, Merge PDF, Add Text, and others, Like showing "we are unable to access the file at this location" after selecting PDF file.

@codegsaini
Copy link
Contributor Author

@Ravipatel401 While testing in Redmi 6A (API 28), the issue is never produced. I'm assuming that this issue is on API 29+. After testing on emulator with API 29+ I'll start working on it.
That being said, Now I want to suggest you that if you have any issue then please open a separate issue so that anyone can work on it. Because this pull request is merged and no longer accessible directly, so no one will get to know about this issue easily.

TL;DR

I'll be working on this issue soon.
Thanks

@Ravipatel401
Copy link

@codegsaini Thank you so much for your response, I am creating a new issue.

Copy link

@ruby100edfdefe ruby100edfdefe left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not Solve Android 10 And 10+ Not Working

@ruby100edfdefe
Copy link

@codegsaini Not Working Android 10 And 10+ Not Working

@codegsaini
Copy link
Contributor Author

@ruby100edfdefe Issue like #1003 #1022 #1028 #1029 are being considered to be resolved in PR #1007, Wait until resolved...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
6 participants