# Android "When Things Go Wrong" Guide If you are reading this guide, things went wrong in your app. Don't worry, that's normal. This guide is written to help you fix your issues. ## Easy Fixes to Try Before we get started on specific recommendations, be sure to follow this checklist if things are acting weird or a network request isn't working: 1. [Clear the Project Caches](https://hackmd.io/s/ByTRUq-Y#clear-project-caches) 2. [Uninstall and re-install the application](https://stackoverflow.com/a/12448020/313399) 3. Restart your emulator or device - This can fix certain issues especially if the emulator has lost internet 4. Consider creating a fresh emulator device When the problem isn't the emulator or the caches as outlined above, this means the issue is likely with your code. Usually, you have some code that isn't behaving as expected. Now we have a problem to investigate. ## Getting Started Every problem where something goes wrong starts with an expectation of yours failing. When something goes wrong, here are the rough steps to follow: 1. [Understand how to reproduce the issue](#Reproduce-the-Expectation-Mismatch) - Figure out how to reproduce the problem you encountered reliably 2. [Enumerate the various likely suspects](#Round-up-the-Possible-Suspects) - Identify the most likely reasons that the problem has gone wrong 4. [Review each suspect to narrow down the culprit](#Exploring-the-Scene-of-the-Crime) - Go through each suspect and investigate to identify the culprit 5. [Identify possible solutions](#Identifying-the-Culprit) - Once the culprit is found, explore possible solutions to resolve the issue 6. [Resolve the issue](#Resolving-the-Issue) - Apply the fix and verify that the issue is now resolved. ### Investigation Methods In order to handle when things go wrong, you'll need to get familiar with your options for investigating problems. Here are a few of the most common tools: * **Toasts** - Using toasts to alert us to failures * **Logging** - Using the logging system to print out values * **Breakpoints** - Using the breakpoint system to investigate values * **Network Logging** - Using the Android Studio network profiling tool to see network requests being sent and their responses. Start by reviewing this [debugging video](https://www.youtube.com/playlist?list=PLrT2tZ9JRrf7ziWU_Qtec6szeWylUTxp6) the [debugging Android apps guide](http://guides.codepath.com/android/Debugging-Exceptions-within-your-App#investigation-methodologies) for details about each of these methods. ## Breaking Down a Problem (Step-by-step) Every problem where things go wrong starts with a failed expectation. In other words, you expected one thing to happen and something else happens instead. This can be formed in the following way: > "I expected the app to ______ when I _____ but instead it _________" For example: I expected the app to display a list of articles when I clicked search but instead it did not show any items and the screen is blank. ### Reproduce the Expectation Mismatch Once we understand the expectation mismatch, we can use our [investigation methodologies described above](http://guides.codepath.com/android/Debugging-Exceptions-within-your-App#investigation-methodologies) to begin exploring the issue. In order to do this, we need to be able to reproduce the problem easily. In other words, you need to be able to identify how to consistently achieve the problem. For example, perhaps the problem is as simple as: 1. Launch the app 2. Type a search term into the actionbar 3. Hit "Search" 4. Expect to see items in the list but I don't Solving problems usually starts with the **ability to identify the steps required to recreate the problem again and again in a reliable manner** so you can bring the proper tools to investigate the "scene of the crime" also known as the circumstances of the problem you are facing. ### Round up the Possible Suspects In this case, the mismatch of expectations is surrounding the failure to see items after I click the "Search" button. Every problem has one or more possible suspects responsible. Our role as the investigator of this issue is to both eliminate elements that are **not the culprit** and **find clues as to what is responsible**. For the issue above, we know that in order to see items in the list there is a particular chain of events that have to happen successfully. If even one link in that chain were to fail, then the entire thing may no longer work. In this example, here are links in the chain: 1. Search button is being pressed but **the event listener isn't properly configured**. 2. Event listener for button is configured properly but network call to fetch items is **not being executed at the right time** 3. Network call is being executed at the right time but the **response is blank or coming back with an error code** 4. Network call response is coming back with data but the **response is not being parsed correctly into a data model** 5. Network call response is being parsed correctly, but the **data model isn't being loaded properly into the RecyclerView adapter** 6. Data is being loaded correctly into the RecyclerView adapter but the **RecyclerView adapter isn't properly inflating rows** and populating each item with data 7. Data is being properly loaded into the RecyclerView adapter but the **RecyclerView isn't properly configured to be visible on screen** And the links in the chain continue from the start (hitting the button to search) all the way to the end (seeing the items properly parsed and listed on screen). ### Exploring the Scene of the Crime In order to handle when things go wrong, you'll need to get familiar with your options for investigating problems. Here are a few of the most common tools: * **Toasts** - Using toasts to alert us to failures * **Logging** - Using the logging system to print out values * **Breakpoints** - Using the breakpoint system to investigate values * **Network Logging** - Copy the URL into a web browser and see if you have a response. Start by reviewing this [debugging video](https://vimeo.com/73990805) the [debugging Android apps guide](http://guides.codepath.com/android/Debugging-Exceptions-within-your-App#investigation-methodologies) for details about each of these methods. Breakpoints are often the most powerful tool available to you. Breakpoints are about **setting up specific lines in the code where the application will be frozen in time** so you can investigate the scene at that moment thoroughly. Only once you hit "continue" on the debugger panel, then the app resumes and the app can only be interacted with when not frozen at a breakpoint. **Breakpoint Note:** Please note that breakpoints won't work well for complex multi-threaded behavior (code running across multiple threads) or can become very cumbersome. In these cases, you may be better off using alternative investigation methods such as logging. ### Identifying the Culprit In order to identify the issue, we need to start by identifying which of the links in the chain are causing the problem. We do this by asking questions step by step, forming a hypothesis, and then systematically ruling out that each is not the cause of the issue step-by-step. The process looks like: 1. Reproduce the circumstances leading up to the problem 2. Select a potential suspect from the links in the chain between an action and an unexpected result 3. Setup breakpoints or otherwise investigate the scene to understand if this could be the issue 4. Eliminate this suspect as the culprit 5. Repeat Step 1 with a new suspect For example, for the links in the chain outlined in the previous section, the first link is "Search button is being pressed but the event listener isn't properly configured". To test this, we could [place a toast](http://guides.codepath.com/android/Displaying-Toasts) or [set a breakpoint](http://guides.codepath.com/android/Debugging-Exceptions-within-your-App#investigating-using-breakpoints) inside the code that is handling the button click in our app. Then we ask the question: "Is the button being clicked running the code as I expect?". If the button press happens and you confirm that the click is happening, then you've **ruled out a particular suspect.** Now we know this is not the issue and you'll move on and repeat this process. Next, we might choose to look at the suspect of "Network call is being executed at the right time but the response is blank or coming back with an error code". This can be best done by [investigating your network calls](http://guides.codepath.com/android/Troubleshooting-API-calls) by copying the URL in a web browser or using the [Android networking profiler](https://developer.android.com/studio/profile/network-profiler) (**NOTE**: The profiler will not work with the Android Async HTTP library). You can also [use breakpoints](http://guides.codepath.com/android/Debugging-Exceptions-within-your-App#investigating-using-breakpoints) set when the network request is being sent out initially and in both the **success and failure callbacks** for your particular networking library. Suppose that we run this investigation and we find that indeed the request sent out is coming back into a failure callback or the response is coming back with a blank body or a 4xx / 5xx status code. This means that **we've found our culprit** which is an unexpected response from the API we are accessing. ## Resolving the Issue Now that we know the culprit is a failing network request, we need to begin to explore further to identify solutions. For network related issues, here are the questions you should be asking and investigating carefully? * Am I using the correct API key? * Am I passing in the correct HTTP GET/POST/PUT/DELETE request method? * Do I have the right base URL pattern? Are there any typos or missing elements of the URL? * Did I properly format each of the parameters being sent? Are the parameter keys correct? Am I missing required parameters? * What is the server error code? If the request is a 400-499 code, this means you've sent a bad request. * What is the server response? Does the response contain any hints to the problem? Refer to the [networking common gotchas](https://hackmd.io/s/ByTRUq-Y#networking) and [troubleshooting API calls](http://guides.codepath.com/android/Troubleshooting-API-calls) for more details on networking issues. Expanding this more broadly, many of the issues you will encounter involve one or more of these key aspects: 1. Attaching event handlers to views for user interaction 2. Forming and executing network requests 3. Parsing the network data to construct models 4. Configuring list adapters to display correct rows 5. Configuring layouts to have the correct views 6. Configuring views to be displayed as expected You can review common solutions to each of these issues and more in the [common gotchas and solutions guide](https://hackmd.io/s/ByTRUq-Y). ## Wrapping Up Once you get the hang of using breakpoints and investigating different issues, then you will get better and better at finding where to pause and investigate suspects. You will also get faster at tracking down the root issue once you've found the right place to investigate. Hopefully this guide has provided you a solid starting point for debugging Android applications in the wild!