4

In my app I have a TextView and an ImageView that I update based on sensor information. This works perfectly on emulators and most of the handsets I have tried it on, however on Samsung handsets from the S7 to the S9 for some reason neither of them changes when they should be updated.

They are part of a Fragment overlaying a SurfaceView with a camera preview in it, there is a second SurfaceView overlay above them:

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="myApp.CameraViewFragment">


    <FrameLayout
        android:id="@+id/control"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_alignParentBottom="true"
        android:layout_alignParentStart="true">

        <myApp.CameraSurfaceView
            android:id="@+id/camera_view"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentStart="true"
            android:layout_alignParentTop="true" />


        <TextView
            android:id="@+id/direction"
            android:layout_width="80dp"
            android:layout_height="wrap_content"
            android:background="@color/black_overlay"
            android:layout_gravity="center_horizontal"
            android:gravity="center"
            android:layout_centerInParent="true"
            android:layout_centerHorizontal="true"
            android:layout_marginTop="10dp"
            android:textSize="30dp"
            android:text="" />

        <ImageButton
            android:id="@+id/gpsNotification"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:src="@drawable/gps_unfixed"
            android:layout_gravity="right"
            android:tint="@color/gps_unfixed"
            android:background="@null" />

    </FrameLayout>
    <com.myapp.OverlaySurfaceView 
         android:id="@+id/overlay_view"
         android:layout_width="200dp"
         android:layout_height="200dp"
         android:gravity="center"
         android:layout_gravity="center_horizontal|center_vertical"
         android:layout_centerHorizontal="true"
         android:layout_centerVertical="true" />
</FrameLayout>

As far as I know, this is the relevant part of the Fragment code:

public class CameraViewFragment extends Fragment
{
    private TextView directionView;
    private CameraSurfaceView cameraView;
    private OverlaySurfaceView overlay;

    @Override
    public void onViewCreated(final View view, Bundle savedInstanceState) {
        cameraView = (CameraSurfaceView) view.findViewById(R.id.camera);
        directionView = (TextView) view.findViewById(R.id.direction);
        overlay = (OverlaySurfaceview) view.findViewById(R.id.overlay_view);
    }

    private void setDirection(AccurateDirection direction) {
        final String directionString = direction.getDirection();
        overlay.update();
        Activity activity = getActivity();
        if ( activity != null ) {
            activity.runOnUiThread(new Runnable() {
                public void run() {
                    directionView.setText(directionString);
                    directionView.invalidate();
                }
            });
        }
    }
}

When I run this on a regular handset, the directionView text updates as new direction data arrives. On a Samsung S7 the value gets set once, maybe updated once right at the start and then it seems to stick and not change any more. If I pause in the debugger and call directionView.getText() from the immediate window, it gives me the result I am expecting, not what I see on the screen. If I call directionView.setText('ABC') in the immediate window, the value returned by directionView.getText() changes but again the value on the screen does not. The ImageView also seems to get stuck in its initial state regardless of changes that should adjust it.

Previous questions on this topic seem to involve updates not being triggered from the UI thread or failures to call invalidate on the view component, so I have fixed both of those already but the problem persists.

I have only seen this on recent Samsung handsets ( my old Samsung S4 appears to be fine ) which makes it hard to troubleshoot. Why are my view components not changing on the Samsung devices and what do I need to do to get them to update?

Edit: Apologies to anyone previously attempting to answer this as I had ommited the OverlaySurfaceView and I now realise that the other components update correctly if the OverlaySurfaceView is removed, so apparently having that second SurfaceView in the view hierarchy is interfering, but only on Samsung. Switching on and off hardware acceleration doesn't seem to make a difference, but there may be a specific place or way that I need to do it. On a working handset hardware acceleration is marked as disabled for the `OverlaySurfaceView.

glenatron
  • 11,018
  • 13
  • 64
  • 112
  • So to answer your question we must have to have a Samsung S7, S8 or S9 :( – Vikasdeep Singh Jul 02 '18 at 14:22
  • Honestly I have no idea - these are the only phones I have seen it on of the ones I have tried - I would _love_ to find a way of debugging this problem that doesn't require an expensive phone that I don't own but my target users are very likely to, absolutely. I just... don't know what it is. – glenatron Jul 02 '18 at 15:34
  • Are you certain that this issue is device specific and not Android version specific? I think S4 runs Android 5.1 or so, and S7 and later run 7.0 or 8.0. You could try verifying this behavior on an emulator. – SpaceBison Jul 03 '18 at 07:36
  • As I say in the question I have tried it on other handsets and I haven't been able to reproduce it in an emulator, including emulators configured to match the profile of the phones in question. The only place it seems to show up is on those physical handsets. I was kind of hoping it was a known problem or feature of these phones, but no sign of that. – glenatron Jul 03 '18 at 09:44
  • Can you create an MCVE that demonstrates the problem? – Cheticamp Jul 06 '18 at 10:30
  • @glenatron I know this approach will not be the more appropiated or the most efficient but if you dont have another way to refresh it you always can relaunch your activity saving the needed values as static – Joaquín Jul 06 '18 at 14:01
  • @cheticamp I haven't done that yet, but I guess I will have to. Of course the problem I have is that without one of the handsets that manifests the problem constructing an MCVE is quite difficult. Perhaps the solution is to find the cheapest second-hand phone I can :( – glenatron Jul 09 '18 at 08:35
  • @JoaquinAlvarez unfortunately these are part of a camera-overlay so I need a live feed from the camera and it takes a second or two to start the Activity - I can't do that every time my sensor data changes or we would never see an image. – glenatron Jul 09 '18 at 08:37
  • @glenatron What is the reason for invalidate call after doing setText ? any reason? – Pankaj Kumar Jul 09 '18 at 08:43
  • 1
    Have you tried to disable hardware acceleration on TextView or activity? https://developer.android.com/guide/topics/graphics/hardware-accel#controlling – weaknespase Jul 09 '18 at 08:47
  • I see what you mean about the MCVE. I had a similar issue with Samsung S7 with the positioning of a popup window. It defied analysis or solution until, one day, the problem just went away with an update. – Cheticamp Jul 09 '18 at 12:32
  • @PankajKumar it was just one of the things that I found in other answers to questions about TextViews not updating- it doesn't appear to make any difference in this case but I wanted to make sure there was no obvious solution missing from my code. – glenatron Jul 10 '18 at 10:38

1 Answers1

1

I had the same issue with Samsung S7 device, eventually I realized i was not handling the setZOrderOnTop correctly

check out this answer : Button on top of SurfaceView with setZOrderOnTop set to true in Android

Eli Leszczynski
  • 145
  • 1
  • 7