What is the difference between them? As far as I can see they both do the same thing.
If you go to sources, you will find PhoneWindow.class that have implementation of Window.setBackgroundDrawable method:
#Override
public final void setBackgroundDrawable(Drawable drawable) {
if (drawable != mBackgroundDrawable || mBackgroundResource != 0) {
mBackgroundResource = 0;
mBackgroundDrawable = drawable;
if (mDecor != null) {
mDecor.setWindowBackground(drawable);
}
if (mBackgroundFallbackResource != 0) {
mDecor.setBackgroundFallback(drawable != null ? 0 : mBackgroundFallbackResource);
}
}
}
As you can see, it calls different method of DecorView setWindowBackground:
public void setWindowBackground(Drawable drawable) {
if (getBackground() != drawable) {
setBackgroundDrawable(drawable);
if (drawable != null) {
drawable.getPadding(mBackgroundPadding);
} else {
mBackgroundPadding.setEmpty();
}
drawableChanged();
}
}
Which is actually use method DecorView.setBackgroundDrawable but also provides additional logic for Window. So I would suggest you to use getWindow().setBackgroundDrawable().
Related
I use this code for Camera X binding. When I run app for the first time everything works fine. But when I close app and start it again I get "ViewPort is NULL". Why viewPort is NULL I do not understand. What is wrong with my code?
#OptIn(markerClass = androidx.camera.lifecycle.ExperimentalUseCaseGroupLifecycle.class)
private void bindAllCameraUseCases() {
if (cameraProvider != null) {
// As required by CameraX API, unbinds all use cases before trying to re-bind any of them.
cameraProvider.unbindAll();
createPreviewUseCase();
createImageCaptureUseCase();
createAnalysisUseCase();
if (previewUseCase != null && analysisUseCase != null && imageCaptureUseCase != null) {
ViewPort viewPort = ((PreviewView)findViewById(R.id.preview_view)).getViewPort();
if (viewPort != null) {
#OptIn(markerClass = androidx.camera.core.ExperimentalUseCaseGroup.class)
UseCaseGroup useCaseGroup = new UseCaseGroup.Builder()
.addUseCase(previewUseCase)
.addUseCase(analysisUseCase)
.addUseCase(imageCaptureUseCase)
.setViewPort(viewPort)
.build();
camera = cameraProvider.bindToLifecycle(/* lifecycleOwner= */ this, cameraSelector, useCaseGroup);
LiveData<Integer> torchStateObserver = camera.getCameraInfo().getTorchState();
torchStateObserver.observe(this, new Observer<Integer>() {
#Override
public void onChanged(Integer state) {
torchState = state;
}
});
} else {
Toast.makeText(this, "VIEWPORT is NULL", Toast.LENGTH_SHORT).show();
}
}
}
}
I'm new to Webrtc, I'm using the AWS Webrtc demo with Android Nav Component. When I exited the app with the back button, I can see that Webrtc is still running or I can see the following log:
EglRenderer: cameraSurfaceViewDropping frame - No surface
In my fragment at the onStop method my code is as follow:
Thread.setDefaultUncaughtExceptionHandler(null)
if (rootEglBase != null) {
rootEglBase!!.release()
rootEglBase = null
}
if (remoteView != null) {
remoteView!!.release()
remoteView = null
}
if (localPeer != null) {
localPeer!!.dispose()
localPeer = null
}
if (videoSource != null) {
videoSource!!.dispose()
videoSource = null
}
if (videoCapturer != null) {
try {
videoCapturer?.stopCapture()
videoCapturer?.dispose()
} catch (e: InterruptedException) {
Timber.e("Failed to stop webrtc video capture. $e ")
}
videoCapturer = null
}
if (client != null) {
this.client!!.disconnect()
this.client = null
}
peerConnectionFoundMap.clear()
pendingIceCandidatesMap.clear()
However, I can see the problem only when I exited the app through the back button, if I killed the app, I don't get the log. Has anyone experienced this?
Thank you.
This is the way you should destroy your WebRTC session on onDestroy() or onStop().
if (videoCaptureAndroid != null) {
videoCaptureAndroid?.stopCapture()
videoCaptureAndroid = null
}
if (localPeer != null) {
localPeer?.close()
localPeer = null
}
if (videoSource != null) {
videoSource?.dispose()
videoSource = null
}
if (audioSource != null) {
audioSource?.dispose()
audioSource = null
}
if (localAudioTrack != null) {
localAudioTrack?.dispose()
localAudioTrack = null
}
if (currentRemoteMediaStream != null) {
currentRemoteMediaStream?.dispose()
currentRemoteMediaStream = null
}
if (localVideoView != null) {
localVideoView?.release()
localVideoView = null
}
if (remoteVideoView != null) {
remoteVideoView?.release()
remoteVideoView = null
}
rootEglBase.release();
if (buttonClicked.contains(1) && buttonClicked.contains(2)) {
if (playerOneLastClicked) {
imgViewBackground1.setImageResource(R.drawable.rca)
} else {
imgViewBackground1.setImageResource(R.drawable.wac)
}
}
if (buttonClicked.contains(3) && buttonClicked.contains(4) && buttonClicked.contains(5)) {
if (playerOneLastClicked) {
imgViewBackground2.setImageResource(R.drawable.rca)
} else {
imgViewBackground4.setImageResource(R.drawable.wac)
}
}
when player1 or player2 last click in (buttonClicked.contains(1) && buttonClicked.contains(2)) imgViewBackgound1 change but when the players click button 3,4 or 5 imgViewBackground keep changing.
I want when imgViewBackground1 take (R.drawable.rca) or (R.drawable.wac) don't change any more.
If imgViewBackground is not going to have an imageview you could just add an extra check e.g.
if (imgViewBackground1.drawable == null) {
if (playerOneLastClicked) {
imgViewBackground1.setImageResource(R.drawable.rca)
} else {
imgViewBackground1.setImageResource(R.drawable.wac)
}
}
}
or if it would have an imageview already and you don't want it set again
if (imgViewBackground1.drawable != resources.getDrawable(R.drawable.rcs, null)
|| imgViewBackground1.drawable != resources.getDrawable(R.drawable.wac, null))
if (playerOneLastClicked) {
imgViewBackground1.setImageResource(R.drawable.rca)
} else {
imgViewBackground1.setImageResource(R.drawable.wac)
}
}
}
I have two fragments in my activity. When I switch fragment use the code:
private void switchCourseFragment() {
if (mCourseFragment == null || getActivity().isFinishing()) return;
FragmentTransaction mTransaction = mFragmentManager.beginTransaction();
if (mFragmentLogin != null && mFragmentLogin.isAdded()) {
mTransaction.remove(mFragmentLogin);
}
if (!mCourseFragment.isAdded()) {
mTransaction.add(R.id.learncenter_contain, mCourseFragment).commitAllowingStateLoss();
}
}
But this is not what I expected. The mFragmentLogin is not been removed, but the mCourseFragment is been added.
You have to commit for it to take effect.
private void switchCourseFragment() {
if (mCourseFragment == null || getActivity().isFinishing()) return;
if (mFragmentLogin != null && mFragmentLogin.isAdded()) {
mFragmentManager.beginTransaction().remove(mFragmentLogin).commit();
}
if (!mCourseFragment.isAdded()) {
mFragmentManager.beginTransaction().add(R.id.learncenter_contain, mCourseFragment).commitAllowingStateLoss();
}
}
but why don't you use replace instead?
private void switchCourseFragment() {
if (mCourseFragment == null || getActivity().isFinishing()) return;
if (!mCourseFragment.isAdded()) {
mFragmentManager.beginTransaction().replace(R.id.learncenter_contain, mCourseFragment).commitAllowingStateLoss();
}
}
This assume that both your fragments are in the same container.
I need a little help to get an idea of how to refactor my code, but I can't see options besides what's done, I would like to add the objects but not using so many lists (and if's conditions).
Here is my code, if anyone could help, I appreciate. Thanks
#ViewById
BannerHomeViewPager place1, place2, place3, place4, place5, place6, place7,
place8, place9;
The lists:
private List<HomeItem> allHomeItems = new ArrayList<HomeItem>(),
placeItems1 = new ArrayList<HomeItem>(),
placeItems2 = new ArrayList<HomeItem>(),
placeItems3 = new ArrayList<HomeItem>(),
placeItems4 = new ArrayList<HomeItem>(),
placeItems5 = new ArrayList<HomeItem>(),
placeItems6 = new ArrayList<HomeItem>(),
placeItems7 = new ArrayList<HomeItem>(),
placeItems8 = new ArrayList<HomeItem>(),
placeItems9 = new ArrayList<HomeItem>();
1) Items mocked, ok.
2)
#UiThread
void updateUI() {
if (allHomeItems != null && allHomeItems.size() > 0) {
for (HomeItem item : allHomeItems) {
if (item.getPlacement().contains("1")) {
placeItems1.add(item);
} else if (item.getPlacement().contains("2")) {
placeItems2.add(item);
} else if (item.getPlacement().contains("3")) {
placeItems3.add(item);
} else if (item.getPlacement().contains("4")) {
placeItems4.add(item);
} else if (item.getPlacement().contains("5")) {
placeItems5.add(item);
} else if (item.getPlacement().contains("6")) {
placeItems6.add(item);
} else if (item.getPlacement().contains("7")) {
placeItems7.add(item);
} else if (item.getPlacement().contains("8")) {
placeItems8.add(item);
} else {
placeItems9.add(item);
}
}
}
setupAdapters();
}
3) setupAdapters()
private void setupAdapters() {
if (place1 != null)
place1.update(placeItems1);
if (place2 != null)
place2.update(placeItems2);
if (place3 != null)
place3.update(placeItems3);
if (place4 != null)
place4.update(placeItems4);
if (place5 != null)
place5.update(placeItems5);
if (place6 != null)
place6.update(placeItems6);
if (place7 != null)
place7.update(placeItems7);
if (place8 != null)
place8.update(placeItems8);
if (place9 != null)
place9.update(placeItems9);
}
As #DanielBo answer:
private Map<String, ArrayList<HomeItem>> placeItems = new HashMap<String,ArrayList<HomeItem>>();
void updateUI() {
if (allHomeItems != null && allHomeItems.size() > 0) {
for (HomeItem item : allHomeItems) {
if(!placeItems.containsKey(item.getPlacement())){
placeItems.put(item.getPlacement(), new ArrayList<HomeItem>());
}
placeItems.get(item.getPlacement()).add(item);
}
}
setupAdapters();
}
But why are you using so many views? I really can't say if this is correct bcs i don't know the purpose of this, but I can't figure a good use to so many list views in the same layout...