Repository: thundernest/k-9
Issue: The application still has some bugs

Hello. I noticed some crashes in logs. The corresponding commit version of code is e85e91c, and application version is 5.6.

## 1.com.fsck.k9.activity.LauncherShortcuts
The exception trace is:
*FATAL EXCEPTION: main
android.util.SuperNotCalledException: Activity {com.fsck.k9/com.fsck.k9.activity.LauncherShortcuts} did not call through to super.onCreate()
	at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2913)
	at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3032)
	at android.app.ActivityThread.-wrap11(Unknown Source:0)
	at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1696)
	at android.os.Handler.dispatchMessage(Handler.java:105)
	at android.os.Looper.loop(Looper.java:164)
	at android.app.ActivityThread.main(ActivityThread.java:6944)
	at java.lang.reflect.Method.invoke(Native Method)
	at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:327)
	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1374)*

### The command to trigger it is: adb shell am start -n com.fsck.k9/com.fsck.k9.activity.LauncherShortcuts

## 2.com.fsck.k9.activity.MessageList
The exception trace is:
*FATAL EXCEPTION: main
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.fsck.k9/com.fsck.k9.activity.MessageList}: java.lang.NullPointerException: Attempt to invoke virtual method 'boolean java.lang.String.equals(java.lang.Object)' on a null object reference
	at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2957)
	at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3032)
	at android.app.ActivityThread.-wrap11(Unknown Source:0)
	at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1696)
	at android.os.Handler.dispatchMessage(Handler.java:105)
	at android.os.Looper.loop(Looper.java:164)
	at android.app.ActivityThread.main(ActivityThread.java:6944)
	at java.lang.reflect.Method.invoke(Native Method)
	at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:327)
	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1374)
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'boolean java.lang.String.equals(java.lang.Object)' on a null object reference
	at com.fsck.k9.search.LocalSearch.addAccountUuid(LocalSearch.java:113)
	at com.fsck.k9.activity.MessageList.decodeExtras(MessageList.java:424)
	at com.fsck.k9.activity.MessageList.onCreate(MessageList.java:224)
	at android.app.Activity.performCreate(Activity.java:7183)
	at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1220)
	at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2910)*
### And this is our test case "*action*: android.intent.action.SEARCH;; *category*: null;; *data*: null;; *type*: null;; *extradata*: String->query->abcde,Bundle->app_data->BundleObj,(,String->com.fsck.k9.search_folder->abcde,),"

## 3.com.fsck.k9.activity.Search
The exception trace is:
*FATAL EXCEPTION: main
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.fsck.k9/com.fsck.k9.activity.Search}: java.lang.NullPointerException: Attempt to invoke virtual method 'boolean java.lang.String.equals(java.lang.Object)' on a null object reference
	at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2957)
	at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3032)
	at android.app.ActivityThread.-wrap11(Unknown Source:0)
	at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1696)
	at android.os.Handler.dispatchMessage(Handler.java:105)
	at android.os.Looper.loop(Looper.java:164)
	at android.app.ActivityThread.main(ActivityThread.java:6944)
	at java.lang.reflect.Method.invoke(Native Method)
	at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:327)
	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1374)
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'boolean java.lang.String.equals(java.lang.Object)' on a null object reference
	at com.fsck.k9.search.LocalSearch.addAccountUuid(LocalSearch.java:113)
	at com.fsck.k9.activity.MessageList.decodeExtras(MessageList.java:424)
	at com.fsck.k9.activity.MessageList.onCreate(MessageList.java:224)
	at android.app.Activity.performCreate(Activity.java:7183)
	at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1220)
	at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2910)*
### And this is our test case "*action*: android.intent.action.SEARCH;; *category*: null;; *data*: null;; *type*: null;; *extradata*: String->query->abcde,Bundle->app_data->BundleObj,(,String->com.fsck.k9.search_folder->abcde,),"

Because all these activities are exported ones, i.e., be exposed to outside, they may receive unfriendly commands and then lead to app crash. After investigation, we found that the missing of null checkers causes those crashes.
Please help to confirm whether they are true bugs. We believe that fixing these bugs will further improve the robustness of this app.

Changed files:
app/ui/src/main/java/com/fsck/k9/activity/LauncherShortcuts.java, app/ui/src/main/java/com/fsck/k9/activity/MessageList.java

diff --git a/app/ui/src/main/java/com/fsck/k9/activity/LauncherShortcuts.java b/app/ui/src/main/java/com/fsck/k9/activity/LauncherShortcuts.java
index 1e26574b7..990d24793 100644
--- a/app/ui/src/main/java/com/fsck/k9/activity/LauncherShortcuts.java
+++ b/app/ui/src/main/java/com/fsck/k9/activity/LauncherShortcuts.java
@@ -12,13 +12,12 @@ import com.fsck.k9.search.SearchAccount;
 public class LauncherShortcuts extends AccountList {
     @Override
     public void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+
         // finish() immediately if we aren't supposed to be here
         if (!Intent.ACTION_CREATE_SHORTCUT.equals(getIntent().getAction())) {
             finish();
-            return;
         }
-
-        super.onCreate(icicle);
     }
 
     @Override
diff --git a/app/ui/src/main/java/com/fsck/k9/activity/MessageList.java b/app/ui/src/main/java/com/fsck/k9/activity/MessageList.java
index 02095f820..43f3f9954 100644
--- a/app/ui/src/main/java/com/fsck/k9/activity/MessageList.java
+++ b/app/ui/src/main/java/com/fsck/k9/activity/MessageList.java
@@ -53,6 +53,7 @@ import com.fsck.k9.search.SearchSpecification;
 import com.fsck.k9.search.SearchSpecification.Attribute;
 import com.fsck.k9.search.SearchSpecification.SearchCondition;
 import com.fsck.k9.search.SearchSpecification.SearchField;
+import com.fsck.k9.ui.BuildConfig;
 import com.fsck.k9.ui.K9Drawer;
 import com.fsck.k9.ui.R;
 import com.fsck.k9.ui.Theme;
@@ -437,10 +438,15 @@ public class MessageList extends K9Activity implements MessageListFragmentListen
 
                 Bundle appData = intent.getBundleExtra(SearchManager.APP_DATA);
                 if (appData != null) {
-                    search.addAccountUuid(appData.getString(EXTRA_SEARCH_ACCOUNT));
-                    // searches started from a folder list activity will provide an account, but no folder
-                    if (appData.getString(EXTRA_SEARCH_FOLDER) != null) {
-                        search.addAllowedFolder(appData.getString(EXTRA_SEARCH_FOLDER));
+                    String searchAccountUuid = appData.getString(EXTRA_SEARCH_ACCOUNT);
+                    if (searchAccountUuid != null) {
+                        search.addAccountUuid(searchAccountUuid);
+                        // searches started from a folder list activity will provide an account, but no folder
+                        if (appData.getString(EXTRA_SEARCH_FOLDER) != null) {
+                            search.addAllowedFolder(appData.getString(EXTRA_SEARCH_FOLDER));
+                        }
+                    } else if (BuildConfig.DEBUG) {
+                        throw new AssertionError("Invalid app data in search intent");
                     }
                 } else {
                     search.addAccountUuid(LocalSearch.ALL_ACCOUNTS);
@@ -466,14 +472,22 @@ public class MessageList extends K9Activity implements MessageListFragmentListen
         }
 
         if (search == null) {
-            // We've most likely been started by an old unread widget
             String accountUuid = intent.getStringExtra("account");
-            String folderServerId = intent.getStringExtra("folder");
+            if (accountUuid != null) {
+                // We've most likely been started by an old unread widget
+                String folderServerId = intent.getStringExtra("folder");
+
+                search = new LocalSearch(folderServerId);
+                search.addAccountUuid(accountUuid);
+                if (folderServerId != null) {
+                    search.addAllowedFolder(folderServerId);
+                }
+            } else {
+                if (BuildConfig.DEBUG) {
+                    throw new AssertionError("MessageList started without required extras");
+                }
 
-            search = new LocalSearch(folderServerId);
-            search.addAccountUuid((accountUuid == null) ? "invalid" : accountUuid);
-            if (folderServerId != null) {
-                search.addAllowedFolder(folderServerId);
+                search = SearchAccount.createUnifiedInboxAccount().getRelatedSearch();
             }
         }