Mousewait.
It's an unofficial Disneyland application which seeks to simplify navigating the park with a single do-it-all style application. Its got wait times and scheduling and bathroom locations and, heck, even quizzes to kill time while you're waiting in line for the bathroom break that you scheduled at 3:30.
It's also, really, really cluttered, and overflowing with information.
Look at all dem buttons. Yes this is on iOS, but on Android the situation really isn't any better.
Admittedly, MouseWait sees this kind of interface as convenient, a one-handed mode of operation. While certainly debatable, there is no argument about it that MouseWait presents a lot of information. This information is, in my opinion, poorly organized into these radio button categories in this television remote like interface.
If one were to try and clean up the interface without changing much of the actual design patterns around it, I would do so first by replacing these buttons with Card like views. The cards could be re-arranged so that the things I view more important can go on top for easy access. Similarly, the things I view as not important at all can be dismissed into an archive of sorts so that they do not clutter up the main view.
If one were to go even deeper, reorganizing the application into a tabbed view-pager like interface can also provide some benefits. Think about the Google Play store, and the massive amount of information that it presents. It separates this information into distinct categories, which it then presents individually per tab. MouseWait could do with a system of categorization around common themes of its interface.
For example, the tabs for Disneyland and California Adventure wait times could be condensed into one view page centered around Wait Times that is split into two halves. Each half can then be dedicated to either Disneyland or California wait times.
Similarly, the Find Food and Find Restrooms and Find Events nearby you buttons could all be condensed into a Nearby page with some kind of similar structure.
Settings would be moved into its own category in a menu button, as the Settings control how the application itself works and does not necessarily affect the park experience.
Yes this would ultimately amount to more clicks, more swipes, and more taps, but it allows the user to break down each section of MouseWait's presented information into concise groupings. Users interested in wait times will go to the Wait Time tab and then work entirely in there until they are done focusing on wait times. Users seeking nearby refreshment can go to the nearby tab and work from there. It is very important for applications which present a large amount of information to break it down into small, easily processed pieces so that a user will not become more confused by trying to use the application.
To keep the theme of a "do-it-all" kind of application, the default tab that the application opens to can serve as a dashboard like interface, where the user's favorites and most commonly visited actions can be presented on the page. This will allow the users who want this fine grained customization to place wait times on the dashboard next to their nearby food locations, and can make the app feel more personalized and therefore create more of an emotional attachment for the user.
Now I am not the developer behind the MouseWait application nor do I know what his or her goals for the application may be. Admittedly I am not a very regular user of the application either, but perhaps if I found the interface less confusing I would be open to using it more.
========================
Follow pyamsoft around the Web for updates and announcements about the newest applications!
Like what I do?
Send me an email at: pyam.soft@gmail.com
Or find me online at: https://pyamsoft.blogspot.com
Follow my FaceBook Page
Follow my Google+ Page
=========================
Tuesday, May 17, 2016
Expressing Intent in Annotations
So lets talk Java Annotations for a bit. Specifically how they can apply to Android.
Annotations were added waaayy back when, something like Java 1.5 in 2004. You probably have noticed them strewn about your code already in the form of @Override in front of some of your functions.
Annotations are useful and neat and are relatively lightweight. While not necessary, they can save you headaches down the line when you are designing a large application or designing with a team. Many popular libraries rely on powerful Java Annotations to do things like dependency injection and mocking for tests, and so some developers seem to view annotations as just another way to declare things in Java.
While these annotation based libraries are very useful, I've found one commonly overlooked thing about annotations is the ability to use them to check for basic code mistakes and simplify usage of various functions around the project.
Lets focus for a bit on three annotations included in the Android support library, @NonNull, @Nullable, and @CheckResult.
@NonNull declares that the variable annotated with it should not be null. This would allow you to remove checks in your code that would check for the existence of the object, at least in the scope that it is referenced as @NonNull. It will throw up a lint warning if a null check is performed on a @NonNull variable.
@Nullable does the opposite of @NonNull, declaring that the annotated variable can be null, and will give out a lint warning if its usage is not guarded.
Note that both @NonNull and @Nullable do not throw up any compile time errors if the annotation contract should be violated. This means it is possible for you to pass a null argument into a @NonNull field, but you will get lint warnings when you attempt to do so. Similarly, even though you pass in an argument that is @NonNull, if the actual function you are passing that argument to specifies it as @Nullable, you will need to guard its access anyway. These annotations do not protect you from stupidity or bad programming practices, but they can make it easier to detect potential bugs in the code.
@CheckResult is slightly different in that it can show a lint error if the annotation contract is not respected. @CheckResult should only be applied to functions, and it will cause lint to throw an error if the return value of that function is not used in some way. It can be very useful in distinguishing between functions that return a value and those that do not. In many cases unless you are constructing a public API, my personal preference is to annotate any function that does not return void with @CheckResult.
There are many other useful annotations provided just by the Android support library. Take a peek at them here.
========================
Follow pyamsoft around the Web for updates and announcements about the newest applications!
Like what I do?
Send me an email at: pyam.soft@gmail.com
Or find me online at: https://pyamsoft.blogspot.com
Follow my FaceBook Page
Follow my Google+ Page
=========================
Annotations were added waaayy back when, something like Java 1.5 in 2004. You probably have noticed them strewn about your code already in the form of @Override in front of some of your functions.
Annotations are useful and neat and are relatively lightweight. While not necessary, they can save you headaches down the line when you are designing a large application or designing with a team. Many popular libraries rely on powerful Java Annotations to do things like dependency injection and mocking for tests, and so some developers seem to view annotations as just another way to declare things in Java.
While these annotation based libraries are very useful, I've found one commonly overlooked thing about annotations is the ability to use them to check for basic code mistakes and simplify usage of various functions around the project.
Lets focus for a bit on three annotations included in the Android support library, @NonNull, @Nullable, and @CheckResult.
@NonNull declares that the variable annotated with it should not be null. This would allow you to remove checks in your code that would check for the existence of the object, at least in the scope that it is referenced as @NonNull. It will throw up a lint warning if a null check is performed on a @NonNull variable.
@Nullable does the opposite of @NonNull, declaring that the annotated variable can be null, and will give out a lint warning if its usage is not guarded.
Note that both @NonNull and @Nullable do not throw up any compile time errors if the annotation contract should be violated. This means it is possible for you to pass a null argument into a @NonNull field, but you will get lint warnings when you attempt to do so. Similarly, even though you pass in an argument that is @NonNull, if the actual function you are passing that argument to specifies it as @Nullable, you will need to guard its access anyway. These annotations do not protect you from stupidity or bad programming practices, but they can make it easier to detect potential bugs in the code.
@CheckResult is slightly different in that it can show a lint error if the annotation contract is not respected. @CheckResult should only be applied to functions, and it will cause lint to throw an error if the return value of that function is not used in some way. It can be very useful in distinguishing between functions that return a value and those that do not. In many cases unless you are constructing a public API, my personal preference is to annotate any function that does not return void with @CheckResult.
There are many other useful annotations provided just by the Android support library. Take a peek at them here.
========================
Follow pyamsoft around the Web for updates and announcements about the newest applications!
Like what I do?
Send me an email at: pyam.soft@gmail.com
Or find me online at: https://pyamsoft.blogspot.com
Follow my FaceBook Page
Follow my Google+ Page
=========================
Monday, May 16, 2016
Getting Started with Android
Last one for today, unless I get bored.
I'm currently trying to teach (show) a colleague how to get started programming for Android. Let me preface this by saying that I do not claim to be a good or even a decent Android programmer, but I at least have a grasp on the basics in my opinion.
Anyway.
Android is hard. Not just in the same sense that, well, programming is hard. But Android is hard mainly because there is no simple answer to the "how do I do this?" question. Especially for a beginner.
My colleague, whom I will simply refer to as 'he' or 'him' from now on, is running into many a road block as he attempts to learn the ins and outs of Android. He barely knows Java. He's never worked with Android before, but is 'curious.' Normally, one would wonder why I would be wasting my time trying to teach someone to, essentially, code Java from the ground up and then attach Android knowledge onto it as well. My answer to that is that I see in him what I saw in myself when I first started. I had a will to learn and a hope to improve. I would find it extremely disheartening to be turned down before I had even began.
But where to begin?
First, you need to know Java. Luckily, Java has been around for a long time, and can be picked up with a basic understanding of the ideas of Classes and Object Orientated Programming. But once you know basic Java, that's where the real fun begins.
There is no disagreement around the fact that if you want to learn Android programming, you must understand the Android Activity. The Activity is, arguably, the single most important piece of any Android application as that it what the user will in many cases actually interact with. But the Activity is big, and has many additions that are sometimes used and sometimes not. And most folks don't even use the plain Activity anymore -- Oh sorry, I meant to link this one. If a new developer were to jump into the Android Activity and try his luck at creating even a super simple application, he may not always know where to start.
Android's default project layout gives a MainActivity java file and a couple of activity related XML files. It also imports a dependency library, appcompat, which imports with it another library, support. It also manages these dependencies in Gradle.
That seems like an awful lot of work to make a single Activity which displays 'Hello World.' And it is. But this is the world that a new developer is introduced into. This confusing mess of build systems, dependencies, and Android support libraries that have almost effectively become a core part of app development.
One way to learn about a framework or a programming language is to make a To-Do list application in that language or using that Framework (this is a step that I did not do when starting out). To-do lists generally touch on a large amount of various concepts, like programming an interface and setting up a service to notify the user at given times. So my programmer padawan begins this by first creating an Activity. He doesn't know what he's going to really need yet, but its a good place to start.
We muck around for a bit with which Activity implementation he should use. I'm not going to start confusing him with various support libraries, so I just have him use the framework Activity class. Awesome. Now for his to-do list, he's going to need, well, a list, so he starts to spin up a ListView.
Normally, this is the part where I tell him that ListView has "kind of" been replaced by this new, cooler version, but I hold my tongue. He won't be able to truly appreciate how much easier things are until he suffers the view holder pattern firsthand. Then comes the first of what I can only assume will be many "Android WTF" questions.
"If Android documentation recommends the viewholder pattern, and everyone seems to use the viewholder pattern, why didn't they just make the ListView use it by default instead of me having to make it every time."
Good question, my son. Android likes choice and doesn't believe the developer should be tied to one way of doing things. But aside from that, I can't really say why. In fact, Android seems to have realized this too, hence the release of RecyclerView which revolves around the ViewHolder pattern. But its support lib appcompat only.
But anyway, back to our story. He's hacked out a ListView with a viewholder-y adapter and he's ready to rumble. A couple HLOC later and now he's gotten to a point where he wants to be able to save his to-do list items somewhere so that he can close the app and still have them. We talk about SharedPreferences for a bit, seems easy enough. He wants to know if he can save images into SharedPreferences also, but I tell him that's a topic for another day and a different tool.
He wants to have the todo list start when he starts his phone and ping him with all of his open tasks. All good, we chat about Broadcast Receivers and a bit about Toasts. Easy peasy. Everything is going swimmingly, so let's pause for a second.
It is both good and bad to learn about the Android framework in this way. I am there with him, so I can point out his mistakes and tell him about what classes and tools to use for the problems he is seeing. I can help explain to him why certain bits are how they are, and what has worked in my experience.
But if I wasn't there, I wonder how would he have gone about figuring out what to use to create this simple to-do. Sure, it would be easy to Google search the questions he had. But some answers may point him to things like SQL databases, or ORMS, and he doesn't quite need that yet. He may not know what term to search for, or how to describe his problem to the search engine. He would not know what to do because he would not even know if the class exists. Sure he could read the documentation, just like he could read the Android Studio TOS, but its going to take him down a path that, while he may learn a lot, may distract him from answering his original questions.
Of course, one can argue that in order to learn you must have an open mind and welcome new knowledge; That you should learn the "right" way, not be spoon fed the answers. I fully agree. But this is not the situation that we all face, and sometimes we lack the patience or the knowledge or the experience to approach problems in a well thought out manner.
What Ifs aside though, I was there and I did tell him. So he doesn't have to search. He types, and I talk and explain what he's doing and he nods in fake understanding. I know he doesn't understand fully, as how could anyone the first time they are exposed to so much information, but I'm hoping that he will read back the code he's produced and at least try to make heads or tails of it. I'm hoping that he will learn everything he can now, so that when he ventures into the world of the support libraries and their tools, and bugs, he will be ready. So that when he learns about Android and its major fragmentation across versions and vendors (Samsung) he'll be prepared. So that when he reads about MVP and how "everything you've done up to this point is wrong, god activities, blah blah" he'll be ready to go back and make things cleaner and nicer. So that when he begins using RxJava and other fancier Android toolkits that he will at least be able to approach his problems and think critically.
But first, he'll have to suffer. He'll have to design applications the wrong way to understand why the correct way is "better." He'll need to hand code his threading so that he can appreciate the ease of use that libraries bring. He'll need to learn a lot, while still keeping up with the massive changes that happen in the Android ecosystem almost every day. And once he has suffered, he will be ready.
For Android N to come along and change every way he thinks about Activities. For Android O to come along and break loaders again for another year.
I'm gonna go type.
========================
Follow pyamsoft around the Web for updates and announcements about the newest applications!
Like what I do?
Send me an email at: pyam.soft@gmail.com
Or find me online at: https://pyamsoft.blogspot.com
Follow my FaceBook Page
Follow my Google+ Page
=========================
I'm currently trying to teach (show) a colleague how to get started programming for Android. Let me preface this by saying that I do not claim to be a good or even a decent Android programmer, but I at least have a grasp on the basics in my opinion.
Anyway.
Android is hard. Not just in the same sense that, well, programming is hard. But Android is hard mainly because there is no simple answer to the "how do I do this?" question. Especially for a beginner.
My colleague, whom I will simply refer to as 'he' or 'him' from now on, is running into many a road block as he attempts to learn the ins and outs of Android. He barely knows Java. He's never worked with Android before, but is 'curious.' Normally, one would wonder why I would be wasting my time trying to teach someone to, essentially, code Java from the ground up and then attach Android knowledge onto it as well. My answer to that is that I see in him what I saw in myself when I first started. I had a will to learn and a hope to improve. I would find it extremely disheartening to be turned down before I had even began.
But where to begin?
First, you need to know Java. Luckily, Java has been around for a long time, and can be picked up with a basic understanding of the ideas of Classes and Object Orientated Programming. But once you know basic Java, that's where the real fun begins.
There is no disagreement around the fact that if you want to learn Android programming, you must understand the Android Activity. The Activity is, arguably, the single most important piece of any Android application as that it what the user will in many cases actually interact with. But the Activity is big, and has many additions that are sometimes used and sometimes not. And most folks don't even use the plain Activity anymore -- Oh sorry, I meant to link this one. If a new developer were to jump into the Android Activity and try his luck at creating even a super simple application, he may not always know where to start.
Android's default project layout gives a MainActivity java file and a couple of activity related XML files. It also imports a dependency library, appcompat, which imports with it another library, support. It also manages these dependencies in Gradle.
That seems like an awful lot of work to make a single Activity which displays 'Hello World.' And it is. But this is the world that a new developer is introduced into. This confusing mess of build systems, dependencies, and Android support libraries that have almost effectively become a core part of app development.
One way to learn about a framework or a programming language is to make a To-Do list application in that language or using that Framework (this is a step that I did not do when starting out). To-do lists generally touch on a large amount of various concepts, like programming an interface and setting up a service to notify the user at given times. So my programmer padawan begins this by first creating an Activity. He doesn't know what he's going to really need yet, but its a good place to start.
We muck around for a bit with which Activity implementation he should use. I'm not going to start confusing him with various support libraries, so I just have him use the framework Activity class. Awesome. Now for his to-do list, he's going to need, well, a list, so he starts to spin up a ListView.
Normally, this is the part where I tell him that ListView has "kind of" been replaced by this new, cooler version, but I hold my tongue. He won't be able to truly appreciate how much easier things are until he suffers the view holder pattern firsthand. Then comes the first of what I can only assume will be many "Android WTF" questions.
"If Android documentation recommends the viewholder pattern, and everyone seems to use the viewholder pattern, why didn't they just make the ListView use it by default instead of me having to make it every time."
Good question, my son. Android likes choice and doesn't believe the developer should be tied to one way of doing things. But aside from that, I can't really say why. In fact, Android seems to have realized this too, hence the release of RecyclerView which revolves around the ViewHolder pattern. But its support lib appcompat only.
But anyway, back to our story. He's hacked out a ListView with a viewholder-y adapter and he's ready to rumble. A couple HLOC later and now he's gotten to a point where he wants to be able to save his to-do list items somewhere so that he can close the app and still have them. We talk about SharedPreferences for a bit, seems easy enough. He wants to know if he can save images into SharedPreferences also, but I tell him that's a topic for another day and a different tool.
He wants to have the todo list start when he starts his phone and ping him with all of his open tasks. All good, we chat about Broadcast Receivers and a bit about Toasts. Easy peasy. Everything is going swimmingly, so let's pause for a second.
It is both good and bad to learn about the Android framework in this way. I am there with him, so I can point out his mistakes and tell him about what classes and tools to use for the problems he is seeing. I can help explain to him why certain bits are how they are, and what has worked in my experience.
But if I wasn't there, I wonder how would he have gone about figuring out what to use to create this simple to-do. Sure, it would be easy to Google search the questions he had. But some answers may point him to things like SQL databases, or ORMS, and he doesn't quite need that yet. He may not know what term to search for, or how to describe his problem to the search engine. He would not know what to do because he would not even know if the class exists. Sure he could read the documentation, just like he could read the Android Studio TOS, but its going to take him down a path that, while he may learn a lot, may distract him from answering his original questions.
Of course, one can argue that in order to learn you must have an open mind and welcome new knowledge; That you should learn the "right" way, not be spoon fed the answers. I fully agree. But this is not the situation that we all face, and sometimes we lack the patience or the knowledge or the experience to approach problems in a well thought out manner.
What Ifs aside though, I was there and I did tell him. So he doesn't have to search. He types, and I talk and explain what he's doing and he nods in fake understanding. I know he doesn't understand fully, as how could anyone the first time they are exposed to so much information, but I'm hoping that he will read back the code he's produced and at least try to make heads or tails of it. I'm hoping that he will learn everything he can now, so that when he ventures into the world of the support libraries and their tools, and bugs, he will be ready. So that when he learns about Android and its major fragmentation across versions and vendors (Samsung) he'll be prepared. So that when he reads about MVP and how "everything you've done up to this point is wrong, god activities, blah blah" he'll be ready to go back and make things cleaner and nicer. So that when he begins using RxJava and other fancier Android toolkits that he will at least be able to approach his problems and think critically.
But first, he'll have to suffer. He'll have to design applications the wrong way to understand why the correct way is "better." He'll need to hand code his threading so that he can appreciate the ease of use that libraries bring. He'll need to learn a lot, while still keeping up with the massive changes that happen in the Android ecosystem almost every day. And once he has suffered, he will be ready.
For Android N to come along and change every way he thinks about Activities. For Android O to come along and break loaders again for another year.
I'm gonna go type.
========================
Follow pyamsoft around the Web for updates and announcements about the newest applications!
Like what I do?
Send me an email at: pyam.soft@gmail.com
Or find me online at: https://pyamsoft.blogspot.com
Follow my FaceBook Page
Follow my Google+ Page
=========================
The Internet is a Strange Place
I'll never sometimes understand the Internet.
To date, one of the most popular posts so far in my fields of musings is this one.
Many people wonder about why the Internet seems to be filling up more and more each day with clickbait and other shady kinds of advertisement practices.
Perhaps it is because it is easier to produce than actual content. Perhaps it gives the best return for investment.
Perhaps it is because at the end of the day, this kind of content is all we really want.
And that's fine.
========================
Follow pyamsoft around the Web for updates and announcements about the newest applications!
Like what I do?
Send me an email at: pyam.soft@gmail.com
Or find me online at: https://pyamsoft.blogspot.com
Follow my FaceBook Page
Follow my Google+ Page
=========================
To date, one of the most popular posts so far in my fields of musings is this one.
Many people wonder about why the Internet seems to be filling up more and more each day with clickbait and other shady kinds of advertisement practices.
Perhaps it is because it is easier to produce than actual content. Perhaps it gives the best return for investment.
Perhaps it is because at the end of the day, this kind of content is all we really want.
And that's fine.
========================
Follow pyamsoft around the Web for updates and announcements about the newest applications!
Like what I do?
Send me an email at: pyam.soft@gmail.com
Or find me online at: https://pyamsoft.blogspot.com
Follow my FaceBook Page
Follow my Google+ Page
=========================
Whats in the Pipeline
PadLock update soon hopefully. Cleans up the logic for how and when the LockScreen is launched, should fix cases where the screen launches when it is not wanted, and similarly, should fix cases when it does not launch but it should.
Other than that, just some general code fixes and updates.
ZapTorch will be updated too to take advantage of newer libraries and hopefully cleaner code base.
What I would like to work on next will be revisiting SoftGlow. I would like to redesign the application effectively from the ground up. This means a couple of new things.
SoftGlow will be bumped to version 3, even though it had a very short version 2 lifespan. Instead of tinting the screen based on the time of day as most other overlay applications do, I want to make use of the newer Android light sensors APIs so that the screen will be tinted when the Light sensor detects a certain level of light or lack of light. In this way, even if it is something like 8 AM in the morning (which should mean the sun is up in most cases), if your device is in the dark as you stare at your phone from under your bedsheets, the screen will still be tinted.
The other thing I hope to address will be the requirement for using the System Overlay permission. I have tested as a proof of concept for creating an overlay that does not require this permission and it most cases it is feasible. Some users will run into issues where the lock screen is not tinted without the System Overlay permission, so this next release for SoftGlow will bring allow tinting of most screens with no permission, and enable the tinting of all screens when the draw overlays permission is granted.
The next release will also remove the Internet permission as it will not be required (no ads anymore) and will bring in its place instead Android In App Purchasing via the same means as the other updated pyamsoft applications.
Finally, I hope to revise SoftGlow to work with many of the same design principles that SoftGlow and ZapTorch have been created with. This means that I will try (to the best of my ability) to implement a clean MVP architecture and adhere to the idea of SOLID classes as much as possible. But of course, I'm only human.
Hopefully I will have more news in the future, but for now I should work on putting code on the page. Stay tuned.
EDIT: Fixed a typo. Sacrificed a french fry.
========================
Follow pyamsoft around the Web for updates and announcements about the newest applications!
Like what I do?
Send me an email at: pyam.soft@gmail.com
Or find me online at: https://pyamsoft.blogspot.com
Follow my FaceBook Page
Follow my Google+ Page
=========================
Other than that, just some general code fixes and updates.
ZapTorch will be updated too to take advantage of newer libraries and hopefully cleaner code base.
What I would like to work on next will be revisiting SoftGlow. I would like to redesign the application effectively from the ground up. This means a couple of new things.
SoftGlow will be bumped to version 3, even though it had a very short version 2 lifespan. Instead of tinting the screen based on the time of day as most other overlay applications do, I want to make use of the newer Android light sensors APIs so that the screen will be tinted when the Light sensor detects a certain level of light or lack of light. In this way, even if it is something like 8 AM in the morning (which should mean the sun is up in most cases), if your device is in the dark as you stare at your phone from under your bedsheets, the screen will still be tinted.
The other thing I hope to address will be the requirement for using the System Overlay permission. I have tested as a proof of concept for creating an overlay that does not require this permission and it most cases it is feasible. Some users will run into issues where the lock screen is not tinted without the System Overlay permission, so this next release for SoftGlow will bring allow tinting of most screens with no permission, and enable the tinting of all screens when the draw overlays permission is granted.
The next release will also remove the Internet permission as it will not be required (no ads anymore) and will bring in its place instead Android In App Purchasing via the same means as the other updated pyamsoft applications.
Finally, I hope to revise SoftGlow to work with many of the same design principles that SoftGlow and ZapTorch have been created with. This means that I will try (to the best of my ability) to implement a clean MVP architecture and adhere to the idea of SOLID classes as much as possible. But of course, I'm only human.
Hopefully I will have more news in the future, but for now I should work on putting code on the page. Stay tuned.
EDIT: Fixed a typo. Sacrificed a french fry.
========================
Follow pyamsoft around the Web for updates and announcements about the newest applications!
Like what I do?
Send me an email at: pyam.soft@gmail.com
Or find me online at: https://pyamsoft.blogspot.com
Follow my FaceBook Page
Follow my Google+ Page
=========================
Saturday, May 14, 2016
PadLock updated
An update to PadLock was pushed earlier today which brings its version to 1.1.1
This release cleans up the SQL table that holds the locked entries for the system and also fixes some potential crashes. Some code cleanups and a better way to handle updates from SQL to the Android main thread.
Expect to see an update in the Play Store in a few hours.
========================
Follow pyamsoft around the Web for updates and announcements about the newest applications!
Like what I do?
Send me an email at: pyam.soft@gmail.com
Or find me online at: https://pyamsoft.blogspot.com
Follow my FaceBook Page
Follow my Google+ Page
=========================
This release cleans up the SQL table that holds the locked entries for the system and also fixes some potential crashes. Some code cleanups and a better way to handle updates from SQL to the Android main thread.
Expect to see an update in the Play Store in a few hours.
========================
Follow pyamsoft around the Web for updates and announcements about the newest applications!
Like what I do?
Send me an email at: pyam.soft@gmail.com
Or find me online at: https://pyamsoft.blogspot.com
Follow my FaceBook Page
Follow my Google+ Page
=========================
Friday, May 13, 2016
What I've learned
TL;Dr I have a lot to learn.
I like Android, no secret there.
I've been attempting to do things on Android for the past 3 years or so. I started knowing literally nothing, no Java, no XML, not even design or best practices or anything really.
I've been attempting to do things on Android for the past 3 years or so. I started knowing literally nothing, no Java, no XML, not even design or best practices or anything really.
I knew one academic quarter of Python. And I had some free time.
The first year I struggled wrapping my head around just plain Java and making layouts in XML. I felt like there was always so much about Android that I could never manage to learn it all.
In a way, I was right. There is so much in the Android SDK, even experienced developers will sometimes run across a feature they've never seen before. And this should come as no surprise, as there are many problems that an application can tackle and many ways to solve the same problem. My first year with Android was all about worrying if I would ever learn enough.
My second year was all about catching up on the things I had missed the first year around when I was getting Java and Android under my fingers. Basic things I had missed. Things like orientation change, context leaks, memory management, threading on Android. Layout efficiency and inflation was a topic I had recently discovered and it fascinated me. It was around this time I also began using Git, and scripting much of my build process in shell scripts. I felt like already I had come a long way, even if my Android applications themselves may have not shown much difference.
In my third year is when I feel like I truly began exploring the world of Android and Java. I learned about libraries and how useful they are. I learned about RxJava and the idea of applying functional programming concepts to an OOP language. I learned about MVP and what I should look for when designing my applications. I learned why Java and Android were ugly, and how many differences there were across devices and platform versions. I learned I had a lot of rewriting to do. I'm happy that I learned this all now, because if I had known about this any earlier I probably would have stopped Android. Any later I would have been too deep in bad habits to really make a change.
And there is still so much out there I just don't know. I don't know how it works or maybe I don't even know it exists. Case in point, I learned about the existence of RoboElectric about 2 days ago.
I'm not the best programmer, but I've found over the years that I don't have to be. Improving comes with time, as long as my drive to get better is still there. As long as I know there is more out there to learn. As long as Android continues to persevere as the open system that encourages improvement and change.
I'm always learning, always striving to get better. Always looking for new things to make.
give me money
========================
Follow pyamsoft around the Web for updates and announcements about the newest applications!
Like what I do?
Send me an email at: pyam.soft@gmail.com
Or find me online at: https://pyamsoft.blogspot.com
Follow my FaceBook Page
Follow my Google+ Page
=========================
Follow pyamsoft around the Web for updates and announcements about the newest applications!
Like what I do?
Send me an email at: pyam.soft@gmail.com
Or find me online at: https://pyamsoft.blogspot.com
Follow my FaceBook Page
Follow my Google+ Page
=========================
Wednesday, May 11, 2016
Disk Encryption on a crummy laptop
About 30 minutes ago I decided that I wanted to use full disk encryption on my Arch Linux installation. My setup would be something simple (I'm not looking for plausible deniability or protecting my information to any extreme degree). It would effectively look like this:
/dev/sda1 -> encrypted root partition (home, var, everything)
/dev/sdb1 -> un-encrypted boot partition
As a laptop user, I want things to be rather convenient, but I still want to maintain at least a basic level of encryption. My setup then is that the OS will be placed on a fully encrypted single partition as I'm too lazy to setup LVM or the like, and that partition will hold the LUKS header (so no plausible deniability of encryption) which will store a single password based LUKS key. The disk itself will not know how to boot.
The boot partition will be stored on a separate, un-encrypted USB stick. This stick will need to be plugged in each time the machine boots, and will also need to be present for any upgrades which deal with kernel images or the bootloader (GRUB in my case). By doing so, a person would need to have the physical USB stick as well as know the password (or execute some variety of an evil maid attack).
Would it make things safer? Not necessarily, but then again this is more of a learning experience than an actual data privacy guarantee.
The actual process was not that hard. The Arch Wiki has a page on dm-crypt setup for a very simple layout. One can follow all of the simple layout steps except that boot should be created on a separate USB stick instead of the internal hard disk. It will only take about 30 minutes to do from the beginning of the install to restoring all of my system information from Git repositories and re-downloaded packages (not accounting the time it may take to erase and encrypt the drive).
========================
Follow pyamsoft around the Web for updates and announcements about the newest applications!
Like what I do?
Send me an email at: pyam.soft@gmail.com
Or find me online at: https://pyamsoft.blogspot.com
Follow my FaceBook Page
Follow my Google+ Page
=========================
/dev/sda1 -> encrypted root partition (home, var, everything)
/dev/sdb1 -> un-encrypted boot partition
As a laptop user, I want things to be rather convenient, but I still want to maintain at least a basic level of encryption. My setup then is that the OS will be placed on a fully encrypted single partition as I'm too lazy to setup LVM or the like, and that partition will hold the LUKS header (so no plausible deniability of encryption) which will store a single password based LUKS key. The disk itself will not know how to boot.
The boot partition will be stored on a separate, un-encrypted USB stick. This stick will need to be plugged in each time the machine boots, and will also need to be present for any upgrades which deal with kernel images or the bootloader (GRUB in my case). By doing so, a person would need to have the physical USB stick as well as know the password (or execute some variety of an evil maid attack).
Would it make things safer? Not necessarily, but then again this is more of a learning experience than an actual data privacy guarantee.
The actual process was not that hard. The Arch Wiki has a page on dm-crypt setup for a very simple layout. One can follow all of the simple layout steps except that boot should be created on a separate USB stick instead of the internal hard disk. It will only take about 30 minutes to do from the beginning of the install to restoring all of my system information from Git repositories and re-downloaded packages (not accounting the time it may take to erase and encrypt the drive).
========================
Follow pyamsoft around the Web for updates and announcements about the newest applications!
Like what I do?
Send me an email at: pyam.soft@gmail.com
Or find me online at: https://pyamsoft.blogspot.com
Follow my FaceBook Page
Follow my Google+ Page
=========================
Tuesday, May 10, 2016
Shrinking Migrations
So this is just a small post regarding a recent operation I had to do regarding SQL database migrations.
PadLock version 1.1.0 (currently on the Play Store) had an SQL database with a schema looking something like this:
This would mean that entries in PadLock looked like this:
The displayName field was the exact same for every application in a package. For an application like Chrome or the Amazon Store, this could lead to hundreds of entries all storing the same value for the displayName field.
The displayName field existed only for one purpose, to populate the toolbar on the LockScreenActivity. Seems like a lot of work for something that can be loaded by the PackageManager as long as we have the package name.
So I wanted to go about removing the displayName field which would make the database cleaner and free up the space otherwise held by that TEXT entry. In order to do so, I needed to bump the database version and provide a migration.
SQLite on Android only provides a subset of the ALTER TABLE functionality. Effectively, it can only rename tables. There is no support for dropping individual columns, which is what I needed to do in this case.
The hacky solution then, was this.
While not too difficult in practice, this is admittedly a hacky work around to a limitation with SQLite, but appears to be the only nice way to get things done.
========================
Follow pyamsoft around the Web for updates and announcements about the newest applications!
Like what I do?
Send me an email at: pyam.soft@gmail.com
Or find me online at: https://pyamsoft.blogspot.com
Follow my FaceBook Page
Follow my Google+ Page
=========================
PadLock version 1.1.0 (currently on the Play Store) had an SQL database with a schema looking something like this:
packageName TEXT,
activityName TEXT,
displayName TEXT,
lockCode TEXT,
lockUntilTime INTEGER,
ignoreUntilTime INTEGER,
systemApplication INTEGER As BOOLEAN
This would mean that entries in PadLock looked like this:
com.pyamsoft.padlock|com.pyamsoft.padlock.app.main.MainActivity|PadLock|NULL|0|0|0
com.pyamsoft.padlock|com.pyamsoft.padlock.app.lockscreen.LockScreenActivity|PadLock|NULL|0|0|0The displayName field was the exact same for every application in a package. For an application like Chrome or the Amazon Store, this could lead to hundreds of entries all storing the same value for the displayName field.
The displayName field existed only for one purpose, to populate the toolbar on the LockScreenActivity. Seems like a lot of work for something that can be loaded by the PackageManager as long as we have the package name.
So I wanted to go about removing the displayName field which would make the database cleaner and free up the space otherwise held by that TEXT entry. In order to do so, I needed to bump the database version and provide a migration.
SQLite on Android only provides a subset of the ALTER TABLE functionality. Effectively, it can only rename tables. There is no support for dropping individual columns, which is what I needed to do in this case.
The hacky solution then, was this.
ALTER the old table by naming it to a new name.
Copy the schema of the table and remove all of the columns that are being dropped.
Create a new table using the original table nameCopy over all of the needed information from the old table into the new one.
Delete the old table to free up the memory space.
While not too difficult in practice, this is admittedly a hacky work around to a limitation with SQLite, but appears to be the only nice way to get things done.
========================
Follow pyamsoft around the Web for updates and announcements about the newest applications!
Like what I do?
Send me an email at: pyam.soft@gmail.com
Or find me online at: https://pyamsoft.blogspot.com
Follow my FaceBook Page
Follow my Google+ Page
=========================
Monday, May 9, 2016
Visiting Presenter State saving
Commence the blah.
I would like to use this post to discuss the methods presented in the article on Android presenters and how to save their state in the application via the Android Loader framework. You can find the post on Medium about this, here.
Over this past weekend I attempted to use this solution to handle saving the state of presenters in PadLock. At the end of these trials I have found a couple of points why I would advocate for, and against preserving Presenters in this way, and most importantly, why I ultimately would not recommend this method.
The pro of this method is the fact that because Loaders are preserved between orientation changes and cleaned up after the lifecycle ends, you do not have to worry about leaking the view that the presenter is attached to or manually clean up the presenter yourself.
I would address this by stating that you should be keeping a Weak Reference to your view in the presenter, not a strong one, which would automatically unbind the presenter from your View whenever it would normally be cleaned up.
The major cons I see in this method of preserving your Presenters through a custom Loader implementation, is that if you wish to use your presenter, it is only guaranteed available in all cases after onStart() in your Activities, and onResume() in your Fragments. While the presenter is available in onStart() for the first time it is used in Fragments, it is not guaranteed at any onStart() call thereafter, making the first guaranteed time in Fragments onResume(). By using Loaders, you sacrifice doing any important work relating to your presenter in onCreate(), onDestroy(), and other areas of the lifecycle that it is not guaranteed to be available. In my opinion, it is not very useful to have the presenter be managed in the lifecycle if it cannot be used for more than half of the Activity/Fragment lifecycle anyway.
To compound onto what I see as the major con to this approach, the ability for the Loader to preserve state is currently broken making it not worth your time at this point. Note that even if the Loader were to be fixed in the future, the above con still stands as my main reason for not advocating this method. Loaders also deliver results on orientation change twice by design, making using them to preserve state effectively a bit of a hack around as well.
Because of the various issues which surround the use of Loaders for preserving Presenter state, I currently take an approach which relies on a headless retained fragment to save arbitrary objects into a SparseArray. This approach is ugly and will need to be manually written into each onSaveInstanceState(), but the FragmentManager will automatically clean itself up once its activity lifecycle has ended. This allows me to avoid using retained fragments that are associated with views, and only use a retained fragment in my headless data holding instance. I do not mind the calls to onSaveInstanceState() all too much, as the lifecycle should be handled entirely by the view anyway, and Android already provides us this call to do so. While this does prevent saving data in any Child sub-Fragments, you should not be using those anyway.
It is not a good approach. But it lets me at least use the full lifecycle of the Activity/Fragment while not having to worry about preserving the Presenters I need. I find it better than an in-memory cache because it is automatically associated and destroyed with its Activity, where as you would have to manually manage an in-memory singleton cache yourself.
========================
Follow pyamsoft around the Web for updates and announcements about the newest applications!
Like what I do?
Send me an email at: pyam.soft@gmail.com
Or find me online at: https://pyamsoft.blogspot.com
Follow my FaceBook Page
Follow my Google+ Page
=========================
I would like to use this post to discuss the methods presented in the article on Android presenters and how to save their state in the application via the Android Loader framework. You can find the post on Medium about this, here.
Over this past weekend I attempted to use this solution to handle saving the state of presenters in PadLock. At the end of these trials I have found a couple of points why I would advocate for, and against preserving Presenters in this way, and most importantly, why I ultimately would not recommend this method.
The pro of this method is the fact that because Loaders are preserved between orientation changes and cleaned up after the lifecycle ends, you do not have to worry about leaking the view that the presenter is attached to or manually clean up the presenter yourself.
I would address this by stating that you should be keeping a Weak Reference to your view in the presenter, not a strong one, which would automatically unbind the presenter from your View whenever it would normally be cleaned up.
The major cons I see in this method of preserving your Presenters through a custom Loader implementation, is that if you wish to use your presenter, it is only guaranteed available in all cases after onStart() in your Activities, and onResume() in your Fragments. While the presenter is available in onStart() for the first time it is used in Fragments, it is not guaranteed at any onStart() call thereafter, making the first guaranteed time in Fragments onResume(). By using Loaders, you sacrifice doing any important work relating to your presenter in onCreate(), onDestroy(), and other areas of the lifecycle that it is not guaranteed to be available. In my opinion, it is not very useful to have the presenter be managed in the lifecycle if it cannot be used for more than half of the Activity/Fragment lifecycle anyway.
To compound onto what I see as the major con to this approach, the ability for the Loader to preserve state is currently broken making it not worth your time at this point. Note that even if the Loader were to be fixed in the future, the above con still stands as my main reason for not advocating this method. Loaders also deliver results on orientation change twice by design, making using them to preserve state effectively a bit of a hack around as well.
Because of the various issues which surround the use of Loaders for preserving Presenter state, I currently take an approach which relies on a headless retained fragment to save arbitrary objects into a SparseArray. This approach is ugly and will need to be manually written into each onSaveInstanceState(), but the FragmentManager will automatically clean itself up once its activity lifecycle has ended. This allows me to avoid using retained fragments that are associated with views, and only use a retained fragment in my headless data holding instance. I do not mind the calls to onSaveInstanceState() all too much, as the lifecycle should be handled entirely by the view anyway, and Android already provides us this call to do so. While this does prevent saving data in any Child sub-Fragments, you should not be using those anyway.
It is not a good approach. But it lets me at least use the full lifecycle of the Activity/Fragment while not having to worry about preserving the Presenters I need. I find it better than an in-memory cache because it is automatically associated and destroyed with its Activity, where as you would have to manually manage an in-memory singleton cache yourself.
========================
Follow pyamsoft around the Web for updates and announcements about the newest applications!
Like what I do?
Send me an email at: pyam.soft@gmail.com
Or find me online at: https://pyamsoft.blogspot.com
Follow my FaceBook Page
Follow my Google+ Page
=========================
Subscribe to:
Posts (Atom)