3

Android app code operates successfully on a variety of devices, including as early as API 14 and up to API 19 (target). However, Samsung G5 v4.4.4 it throws NPE when attempting to setVisibilty(true) for an activity. This error may have only started occurring after a recent upgrade of the G5 OS, via download from Sprint. We have reviewed many varieties of NPE problems and Samsung specific issues, but none seem applicable.

The log:

01-08 20:58:40.122: W/dalvikvm(7972): threadid=1: thread exiting with uncaught exception (group=0x41963da0)

01-08 20:58:40.132: W/System.err(7972): java.lang.NullPointerException

01-08 20:58:40.132: W/System.err(7972): at android.app.Activity.makeVisible(Activity.java:4355)

01-08 20:58:40.142: W/System.err(7972): at android.app.Activity.setVisible(Activity.java:4336)

01-08 20:58:40.142: W/System.err(7972): at com.taskassure.app.StartTaskActivity.setActivityVisible(StartTaskActivity.java:531)

01-08 20:58:40.142: W/System.err(7972): at com.taskassure.app.StartTaskActivity.access$1(StartTaskActivity.java:529)

01-08 20:58:40.142: W/System.err(7972): at com.taskassure.app.StartTaskActivity$4.run(StartTaskActivity.java:298)

01-08 20:58:40.142: W/System.err(7972): at android.os.Handler.handleCallback(Handler.java:733)

01-08 20:58:40.142: W/System.err(7972): at android.os.Handler.dispatchMessage(Handler.java:95)

01-08 20:58:40.142: W/System.err(7972): at android.os.Looper.loop(Looper.java:146)

01-08 20:58:40.142: W/System.err(7972): at android.app.ActivityThread.main(ActivityThread.java:5678)

01-08 20:58:40.142: W/System.err(7972): at java.lang.reflect.Method.invokeNative(Native Method)

01-08 20:58:40.152: W/System.err(7972): at java.lang.reflect.Method.invoke(Method.java:515)

01-08 20:58:40.152: W/System.err(7972): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1291)

01-08 20:58:40.152: W/System.err(7972): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1107)

01-08 20:58:40.152: W/System.err(7972): at dalvik.system.NativeStart.main(Native Method)

Review of StartTaskActivity confirms we are attempting to set the visibility to true when the exception is thrown. Segments of the related code include:

Activity that will launch the failing activity (StartTaskActivity):

/**
* The intent to open the task start confirm dialog. Put in globalspace so
* that data can be added to it from anywhere in this class.
*/
public intent      confirmActivity  = null;

/**
* Sets up the tab view showing the task details and checkpoints, as well as
* setting up the location client to get the most recent location.
*/

@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.view_task_activity);
// Set up the action bar.
final ActionBar actionBar = getActionBar();
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);

...

// initialize confirmActivity so we can add the necessary
// information from our fragments
confirmActivity = new Intent(getApplicationContext(),
    StartTaskActivity.class);
}

Related methods in the class that will launch StartTaskActivity

/** * Sends a request to start the task to the server, gets back any checkpoint * warnings that need to be overridden before we can start the task. Upon * overriding any warnings (if any) The StartTaskActivity is launched. */

private void requestTaskStart()
{

...
          try
          {
            JSONObject JsonResponse = new JSONObject(responseBody);
            JSONArray checkpoints = (JSONArray) JsonResponse
                .get("chekpoint_status");

            JSONObject userData = new JSONObject(getIntent().getExtras()
                .getString("user"));
            userData = userData.getJSONObject("user");
            confirmActivity.putExtra("training_set_size", new JSONObject(
                getIntent().getExtras().getString("user"))
                .getInt("training_set_size"));
            confirmActivity.putExtra("requestStartInfo",
                responseBody);
            confirmActivity.putExtra("user_id",
                Integer.parseInt(userData.getString("id")));
            confirmActivity.putExtra("taskId", task.getInt("id"));

            mDialog.dismiss();

            // show checkpoint override if there are any
            if ( checkpoints.length() != 0 )
            {
              // show first checkpoint dialog
              showCheckpointDialog(checkpoints, 0);
            }
            else
            {
              startActivityForResult(confirmActivity,
                  CONFIRM_TASK_START);
            }

StartTaskActivity - the activity class that throws NPE on Samsung G5

/**
* Activity that is shown after choosing to start a task. Shows the confirmation
* window before a task is started. This activity also handles starting face
* verification if necessary.
*/

public class StartTaskActivity extends Activity
{
    ...
/**
* Creates the task confirm screen, downloads the users photo from the server.
* Checks the task checkpoints to see if face verification needs to be done
* before starting the task. Keeps the activity invisible until all
* checkpoints are properly met.
*/
@Override
protected void onCreate(Bundle savedInstanceState)
{
    super.onCreate(savedInstanceState);
    setContentView(R.layout.start_task_confirm_layout);

    Intent launchIntent = getIntent();
    Bundle args = launchIntent.getExtras();

    try
    {
      requestTaskStartData = new JSONObject(args.getString("requestStartInfo"));
      taskCheckpoints = new JSONArray(args.getString("checkpoints"));
      taskId = args.getInt("taskId");

      ((TextView) findViewById(R.id.task_confirm_textview))
          .setText(requestTaskStartData.getString("task_summary"));

      new Thread(new Runnable()
      {
        @Override
        public void run()
        {

            ... 
            // code retrieves an image file from server on separate thread
            // depending on results, call checkVerifyIdentity for additional processing and to show view
            ... 
            checkVerifyIdentity(bmp)

  }).start();

  ((TextView) findViewById(R.id.task_password_content_textview))
      .setText(requestTaskStartData.getString("task_password"));

}
catch ( JSONException e )
{
  ((TextView) findViewById(R.id.task_password_title_textview))
      .setVisibility(TextView.INVISIBLE);

  e.printStackTrace();
}

findViewById(R.id.task_confirm_button).setOnClickListener(
    new View.OnClickListener()
    {

      @Override
      public void onClick(View v)
      {
        setResult(RESULT_OK);
        finish();
      }
    });

findViewById(R.id.task_deny_button).setOnClickListener(
    new View.OnClickListener()
    {

      @Override
      public void onClick(View v)
      {

        setResult(RESULT_CANCELED);
        finish();
      }
    });

}  // end of StartTaskActivity.onCreate

    ...

// Check some parameters, and finish setting up view for display (runs on UI thread)
private void checkVerifyIdentity(final Bitmap bmp)
{
    final Context context = this;
    StartTaskActivity.this.runOnUiThread(new Runnable()
    {
      public void run()
      {
        if ( bmp != null )
        {
          ((ImageView) findViewById(R.id.task_confirm_imageview))
              .setImageBitmap(bmp);
        }
        if ( taskCheckpoints.length() > 0 )
        {
            ... // do some processing
        }
        else
        {
          setActivityVisible();  
        }
      }
    });
}

    ...
/**
* Sets the activity as visible. Should be called once all verifications are
* properly checked.
*/
private void setActivityVisible()
{
    this.setVisible(true);

}

The above line to setVisible is line 531 of StartTaskActivity which eventually causes the NPE for Samsung G5, but not other devices/versions that we can test. As reflected in comments, subsequent test on 4.4.4 emulator is not able to replicate the error. So far, error only observed on actual Samsung G5 with 4.4.4.

UPDATE:

Based on a labor intensive debug step process of mapping a good source view (4.4.4 emulator) with the Samsung incorrect source view, we have narrowed in on the cause of the NPE. The app throws an NPE when it calls StartTaskActivity.setActivityVisible, which eventually runs into a null object. Because of the limits to the tracing process, I can’t say with certainty what that object is, but my guess is that it is the window, or view. The line of code that throws it is “mDecor.setVisibility(View.VISIBLE)” (line 4355 in Samsung = line 4143 in Emulator of Activity.java). So, technically, some part of the mDecor object is null.

Will probably take a different approach to achieve our goal, since we cannot determine why the Samsung v4.4.4 throws NPE when no other device/emulator seems to, including Samsung v4.4.2. Perhaps even though this question is unresolved, it might be useful to others in the future.

Community
  • 1
  • 1
ssurfr
  • 71
  • 7
  • Can you test 4.4.4 on an emulator? – nasch Jan 10 '15 at 00:19
  • Not currently. Would like to! Using Eclipse, the only options seems to be up to 4.4.2. Have not made the switch yet to Android Studio. On 4.4.2 emulator tests perfectly fine. As noted, prior to a recent OS upgrade of the Samsung (courtesy of Sprint) this same function on the add performed without error on this same device. – ssurfr Jan 10 '15 at 20:15
  • Note, in an attempt to trace the NPE to better understand what the "null" is, we tried using Step In within debug. Once the debug goes into open source code where the exception occurs (e.g. Activity.setVisible, Activity.makeVisible) the debugger is not showing the correct source. I believe this is also due to Eclipse only having 4.4.2 java available, not 4.4.4. If there's a way around this, we haven't found it. – ssurfr Jan 10 '15 at 20:19
  • UPDATE: from SO article on Genymotion emulator for 4.4.4 [link](http://stackoverflow.com/questions/25597156/4-4-4-not-in-android-sdk-manager) we were able to equip Eclipse to emulate a Samsung G5 with 4.4.4. The app ran without error on the emulator. Using exact same app variables (logged in as same user, running identical process) the app will not perform the function on Samsung device, but does succeed on emulator. Anyone have ideas or suggestions? – ssurfr Jan 10 '15 at 23:04
  • Have you downloaded the 4.4.4 source with your SDK manager? Is that API level 20? Maybe that will help with the debugging. – nasch Jan 10 '15 at 23:28
  • When I test with 4.4.4 emulator, using breakpoint in the app then I step into code, which goes to java Activity.setVisible. Able to see correct source code in java. However, when I connect Samsung and try same thing (with same Eclipse configuration, etc.) it still shows the wrong source. I can tell it is not the correct source for example, because it is "stepping" through comment lines. If both are running on 4.4.4, why would debugger not see the valid code during the stepping? BTW, my understanding is that 4.4.4 is API 19. My Eclipse SDK has 19 installed, but also 21. Should I uninstall 21? – ssurfr Jan 10 '15 at 23:43
  • To answer @nasch question directly - Eclipse does not appear to permit 4.4.4 source download, only 4.4.2, which we have installed. Supposedly the Genymotion Samsung emulator is 4.4.4, but when we debug running it, the source seems correct. But when real Samsung is connected, source is not correct. Can Samsung have a bogus install? – ssurfr Jan 10 '15 at 23:52
  • I don't know about bogus, but it might be possible Samsung has altered the code. Seems unlikely though, and they would have to make the source available if they did so (though they might make it hard to find). My SDK manager doesn't even show 4.4.4, I just have 4.4.2 (19), 4.4W.2 (20), and 5.0.1 (21). – nasch Jan 12 '15 at 04:06

1 Answers1

2

Significant time was spent attempting to isolate the cause of this issue. We have not been able to reproduce the NPE exception on any other device or emulator except the Samsung G5 (Sprint) running 4.4.4. The crash occurs when attempting to use the setVisible method on an activity that had a background thread launched from within onCreate, which then launches a runsOnUiThread. Perhaps this was an improper practice that for some reason wasn't bothered by other systems, but the Samsung (at least) found it unacceptable.

In any case, we resolved this by showing/hiding the view associated with the activity (using for example v.setVisibility(View.VISIBLE) and some worthwhile refactoring. As indicated by the Android documentation, use Activity#setVisible method with caution.

ssurfr
  • 71
  • 7
  • I'm having this same issue but it apparently happens with all Samsung devices running 4.4.4. The workaround suggested above doesn't work as it leaves the screen completely black for me. Trying some other things to see if I can work around the issue – Daniel Ochoa Feb 24 '15 at 03:51
  • @Daniel, I can only recommend that if you are using Activity#setVisible, then replace with an equivalent approach using v.setVisibility(View.VISIBLE). – ssurfr Feb 25 '15 at 20:05