Issue
When returning to IpFragment via navigateUp() it sometimes is blank, when it should be showing a couple simple textviews. Sometimes it renders correctly, but when it fails, the only error seems unrelated.
The fragment which appears blank when returning to it:
public class IpFragment extends Fragment implements ...{
private static final String TAG = "IpFragment";
private NavController navController;
private Context context;
private TextView tvIp;
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
navController = NavHostFragment.findNavController(this);
View v = inflater.inflate(R.layout.fragment_ip, container, false);
context = v.getContext();
return v;
}
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
Log.d(TAG, "onViewCreated");
ConnectivitySingleton.getInstance().registerCallback(this);
tvIp = view.findViewById(R.id.tvIp);
tvIp.setText(getDeviceIp());
}
@Override
public void onDestroyView() {
super.onDestroyView();
ConnectivitySingleton.getInstance().unregisterCallback(this);
}
...
}
The fragment we return from:
public class InterviewFragment extends Fragment implements ConnectionCallback, StreamStatusCallback, TextureView.SurfaceTextureListener, SpeakCallback {
private static final String TAG = "InterviewFragment";
private NavController navController;
private AutoFitDrawableView autoFitDrawableView;
private Context context;
public boolean isStreaming;
private MessageConnection messageConnection;
private TextView tvQuestion;
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
Log.d(TAG, "onCreateView");
// return super.onCreateView(inflater, container, savedInstanceState);
navController = NavHostFragment.findNavController(this);
View v = inflater.inflate(R.layout.fragment_interview, container, false);
context = v.getContext();
return v;
}
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
Log.d(TAG, "onViewCreated");
super.onViewCreated(view, savedInstanceState);
ConnectivitySingleton.getInstance().registerCallback(this);
VisionSingleton.getInstance().registerCallback(this);
SpeakSingleton.getInstance().registerCallback(this);
autoFitDrawableView = view.findViewById(R.id.autofit);
// need to set autoFitDrawableView's display size / rotation
int rotation = ((Activity) context).getWindowManager().getDefaultDisplay().getRotation();
autoFitDrawableView.setPreviewSizeAndRotation(800, 600, rotation); // w 800 h 600
// set listener to stream frames
autoFitDrawableView.setSurfaceTextureListenerForPreview(this);
tvQuestion = view.findViewById(R.id.question);
}
@Override
public void onDestroyView() {
Log.d(TAG, "onDestroyView");
super.onDestroyView();
ConnectivitySingleton.getInstance().unregisterCallback(this);
VisionSingleton.getInstance().unregisterCallback(this);
SpeakSingleton.getInstance().unregisterCallback(this);
}
@Override
public void onConnected() {
}
@Override
public void onDisconnected() {
navController.navigateUp();
}
@Override
/**
* Passes surfaceTexture to VisionSingleton once ST is available. VisionSingleton then sets up
* DTS camera to stream to surfaceTexture.
*/
public void onSurfaceTextureAvailable(SurfaceTexture surfaceTexture, int i, int i1) {
Log.d(TAG, "onSurfaceTextureAvailable");
VisionSingleton.getInstance().initPreview(surfaceTexture);
}
@Override
public void onSurfaceTextureSizeChanged(SurfaceTexture surfaceTexture, int i, int i1) { }
@Override
public boolean onSurfaceTextureDestroyed(SurfaceTexture surfaceTexture) {
Log.d(TAG, "onSurfaceTextureDestroyed");
VisionSingleton.getInstance().stopPreview();
return false;
}
@Override
/**
* If a 'vision start' command has been received, then surfaceTexture's frame should be sent to
* the phone app via messageConnection.
*/
public void onSurfaceTextureUpdated(SurfaceTexture surfaceTexture) {
if(isStreaming) {
try {
int tvWidth = autoFitDrawableView.getPreview().getWidth();
int tvHeight = autoFitDrawableView.getPreview().getHeight();
// Get bitmap from TextureView
Bitmap bm = Bitmap.createBitmap(tvWidth, tvHeight, Bitmap.Config.ARGB_8888);
autoFitDrawableView.getPreview().getBitmap(bm);
// Compress via JPG
ByteArrayOutputStream os = new ByteArrayOutputStream();
bm.compress(Bitmap.CompressFormat.JPEG, 50, os);
byte[] byteArray = os.toByteArray();
Log.d(TAG, "Byte size: " + byteArray.length);
if (byteArray.length > 1000000) {
Log.w(TAG, "Byte size is > 1 MB! Exceeds max sending size.");
} else {
messageConnection.sendMessage(new BufferMessage(byteArray));
}
} catch (Exception e) {
e.printStackTrace();
Log.e(TAG, e.getMessage());
}
}
}
@Override
public void onStartStream(final MessageConnection messageConnection) {
Log.d(TAG, "onStartStream");
isStreaming = true;
this.messageConnection = messageConnection;
}
@Override
public void onStopStream() {
Log.d(TAG, "onStopStream");
isStreaming = false;
}
@Override
public void onSpeakCommandReceived(String question) {
tvQuestion.setText(question);
}
}
Sometimes in InterviewFragment I get this caught error, which doesn't break anything at the time, but later when returning to IpFragment, it appears blank.
08-07 22:45:54.921 5196-5275/edu.unc.etlab.robojloomo W/MessageListener: Exception occured during command launch
android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
at android.view.ViewRootImpl.checkThread(ViewRootImpl.java:6357)
at android.view.ViewRootImpl.requestLayout(ViewRootImpl.java:874)
at android.view.View.requestLayout(View.java:17476)
at android.view.View.requestLayout(View.java:17476)
at android.view.View.requestLayout(View.java:17476)
at android.view.View.requestLayout(View.java:17476)
at android.view.View.requestLayout(View.java:17476)
at android.view.View.requestLayout(View.java:17476)
at android.support.constraint.ConstraintLayout.requestLayout(ConstraintLayout.java:3172)
at android.view.View.requestLayout(View.java:17476)
at android.view.View.requestLayout(View.java:17476)
at android.widget.RelativeLayout.requestLayout(RelativeLayout.java:360)
at android.view.View.requestLayout(View.java:17476)
at android.widget.TextView.checkForRelayout(TextView.java:6865)
at android.widget.TextView.setText(TextView.java:4057)
at android.widget.TextView.setText(TextView.java:3915)
at android.widget.TextView.setText(TextView.java:3890)
at edu.unc.etlab.robojloomo.InterviewFragment.onSpeakCommandReceived(InterviewFragment.java:168)
at edu.unc.etlab.robojloomo.loomo_services.SpeakSingleton.speak(SpeakSingleton.java:69)
at edu.unc.etlab.robojloomo.listeners.SpeakCommand.execute(SpeakCommand.java:14)
at edu.unc.etlab.robojloomo.listeners.MessageListener.onMessageReceived(MessageListener.java:85)
at com.segway.robot.sdk.connectivity.RobotMessageConnection.handleMessage(RobotMessageConnection.java:219)
at android.os.Handler.dispatchMessage(Handler.java:98)
at android.os.Looper.loop(Looper.java:135)
at android.os.HandlerThread.run(HandlerThread.java:61)
This error happens when I set the text of a textView within InterviewFragment:
public void onSpeakCommandReceived(String question) {
tvQuestion.setText(question);
}
Solution
Ok, so quickly after posting this question I fixed it. I referred to this post to fix the error I was getting: Android "Only the original thread that created a view hierarchy can touch its views.". and I changed onSpeakCommandReceived() to:
public void onSpeakCommandReceived(final String question) {
getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
tvQuestion.setText(question);
}
});
}
Still not sure how this error caused the next screen to be blank, since they occur at different times, but now the error is fixed everything seems to work.
Answered By - mhudnell
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.