-
-
Notifications
You must be signed in to change notification settings - Fork 2.3k
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
Implementing automatic "safe display mode" for e-ink devices. #17646
base: main
Are you sure you want to change the base?
Conversation
First PR! 🚀 We sincerely appreciate that you have taken the time to propose a change to AnkiDroid! Please have patience with us as we are all volunteers - we will get to this as soon as possible. |
now in future commit i will implement |
Please don't submit a PR until it's ready for review. I've marked this as a draft for now, please un-draft when completed |
sorry for that, will keep this thing in mind for future. |
I’ve added the hasEInkDisplay() method to detect E-Ink devices and integrated it with initializeSafeDisplayMode() to set preferences. Could you review the implementation and suggest improvements? Also, since Android Studio lacks E-Ink emulation, how would you recommend testing this functionality? |
private fun hasEInkDisplay(): Boolean { | ||
return try { | ||
// Load JSON from assets | ||
val jsonFileName = "eink_devices.json" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is there a real benefit to having this in a JSON file and loading it vs just having a map of manufacturers with an array of their modules in the code? I'm not sure I see a benefit
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Externalizing data improves code readability, maintainability, and future-proofing by separating data from logic. This modular approach simplifies updates and supports dynamic configurations(that can be introduced in future ), but a hardcoded map can be implemented if preferred.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
as you can see my current json file which contains almost 90-95% e-ink devices is huge , add these many code lines in the code itself just for populating the map seems inefficient , but i can implement map if you want . please review
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No need for a file. Hardcode it so we're doing less I/O on startup
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the file isn't that big
"locality" for a feature is a value of it's own in my opinion - by which I mean "everything related to a feature in one spot"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay i will get it done , i will make an map of eink_devices, but i want to confirm should i make the map in the hasEInkDisplay method itself or another method wich return the map to be used , please clarify
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Separate class, it doesn't belong in AnkiDroidApp
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think that could be overkill , to make a seperate DeviceInfo class , making private map of knowin eink devices of key - manufacturer string and value as list of string of models , is it fine ?
* This method checks if the `safe_display` key is already set in the shared preferences. | ||
* If the key is not set and the device has an e-ink display, it sets the `safe_display` key to `true`. | ||
*/ | ||
@OptIn(UnstableApi::class) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
curious, what are the unstable APIs used here and below and why are they necessary vs a stable API ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I initially used OptIn(UnstableApi::class) due to reliance on experimental APIs like android.system.Os and android.media3.common.util.Log for advanced system operations and logging. However, I've since replaced these unstable APIs with Timber, a stable and widely-used logging tool, ensuring better stability and compatibility while maintaining the required functionality.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i have finally fixed all the timber issues that were present in my code , please review, the issues were , i was not able to see my timber logs with "SafeDisplayMode" tag in the log cat , and when i checked with some Log.d statemnts i came to know my Timber tree was not getting intialized , thus i made a intializeTimberTree method
You may try adding something like this |
@@ -1,22 +1,142 @@ | |||
[ | |||
{ | |||
"manufacturer": "Onyx", | |||
"models": ["Boox Note Air", "Boox Note 5", "Boox Nova Air", "Boox Nova 3", "Boox Poke 3", "Boox Tab Ultra"] | |||
"manufacturer": "Onyx Boox", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Where did you source this data from?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i did some research used these websites,
https://www.androidauthority.com/best-e-ink-tablet-3230616
https://www.androidpolice.com/best-e-ink-tablets
https://cincodias.elpais.com/smartlife/gadgets/2024-10-23/nuevos-boox-note-air4-c-palma-2-note-max-caracteristicas.html
https://www.androidcentral.com/best-e-ink-tablet
and in the end used Ai tools for completing it
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are you sure that this is what the devices are reporting as manufacturer
/model
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sorry i can't confirm 100% about that because nowhere it is directly written what does Build.MODEL print for the devices , although there were some issue in my data i am fixing that .
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
any guidance on how to collect the accurate data will be extremely helpful
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hi , i was asking about keeping a naming convention for models in the map can i keep names such that the names only contains numbers and alphabets that too lowercase , no symbols like "-" or spaces , and then after getting the Build.Manufacturer and Build.Model , i can process them to remove any symbols and sapcing for better mathcing , please suggest ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, find a list which you know is accurate, even if it's incomplete, rather than AI-generated slop. If you're not certain, it's best not to include it (and therefore, I believe we're starting from scratch).
My first example found from a quick search in the repo doesn't match. You can bounce from this to a decent source.
Manufacturer = ONYX
Model = NovaAir
You'll want to use an authoritative source. None of those blogs are usable
* Returns true if a match is found, false otherwise. | ||
*/ | ||
fun hasEInkDisplay(): Boolean { | ||
initializeTimber("SafeDisplayMode") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Eh? Why not initialize this after logging is setup?
It doesn't need to be done so early
private fun hasEInkDisplay(): Boolean { | ||
return try { | ||
// Load JSON from assets | ||
val jsonFileName = "eink_devices.json" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No need for a file. Hardcode it so we're doing less I/O on startup
val deviceManufacturer = Build.MANUFACTURER.lowercase().trim() | ||
val deviceModel = Build.MODEL.lowercase().trim() | ||
|
||
Timber.tag("SafeDisplayMode").d("Checking device: manufacturer=$deviceManufacturer, model=$deviceModel") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a non-idiomatic use of Timber, please fix to match our code style.
for (i in 0 until jsonArray.length()) { | ||
val deviceInfo = jsonArray.getJSONObject(i) | ||
val manufacturer = deviceInfo.getString("manufacturer").lowercase().trim() | ||
val models = deviceInfo.getJSONArray("models") | ||
|
||
// If manufacturer matches, check models | ||
if (deviceManufacturer.contains(manufacturer) || manufacturer.contains(deviceManufacturer)) { | ||
for (j in 0 until models.length()) { | ||
val model = models.getString(j).lowercase().trim() | ||
if (deviceModel.contains(model) || model.contains(deviceModel)) { | ||
Timber.tag("SafeDisplayMode").d("E-Ink display detected: Manufacturer=$manufacturer, Model=$model") | ||
return true | ||
} | ||
} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This method feels like it should be ~1 line of code:
return knownEInkDevices.contains(DeviceInfo(Build.MANUFACTURER, Build.MODEL))
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
okay , i can get i done , but this requires creating an inner class DeviceInfo and an companion object ( knownEInkDevices map ) is it allowed ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's pseudocode, but it feels like a reasonable solution, is there a reason you're asking in partiuclar?
`hasEInkDisplay` method which uses JSON file.
02be2fe
to
a6635ff
Compare
…nfirmed devices,modified `hasEInkDisplay` method.
a6635ff
to
64f04e5
Compare
Purpose / Description
I am solving issue #17618 by implementing the
initializeSafeDisplayMode()
andhasEInkDisplay()
methodApproach
The
initializeSafeDisplayMode()
method activates safe display mode if the device has an e-ink display and the user hasn't modified this setting. ThehasEInkDisplay()
method, which detects e-ink displays using a project-specific lookup knownEInkDevices set file of manufacturers and models.How Has This Been Tested?
I added { "manufacturer": "Google", "models": ["sdk_gphone64_x86_64"] } ( for Pixel 5) and tested it , i have added video of it
Screen_recording_20241222_122258.mp4
Checklist
Please, go through these checks before submitting the PR.