I use AdView mAdView and the last updated libraries.
I placed the AdView into my layout (as shown in the examples):
<com.google.android.gms.ads.AdView
xmlns:ads="http://schemas.android.com/apk/res-auto"
android:id="#+id/adView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
ads:adSize="BANNER"
ads:adUnitId="#string/banner_ad_unit_id">
</com.google.android.gms.ads.AdView>
Then I identify it and try to load a new ad in the onCreate() method:
AdView mAdView = findViewById(R.id.adView);
AdRequest adRequest = new AdRequest.Builder().build();
mAdView.loadAd(adRequest);
But my layout has some animated objects. This animation is freezing (skipping some frames) while new ad is become visible.
We can't catch the same problem with the disabled Internet (it disables ads and not affect lags).
I'm trying to show the problem with my own record (GIF can't show that completely):
https://www.youtube.com/watch?v=adH2Mn79O7w
How can I remove ads' lags and make the user experience better?
This is a known issue, which has been discussed many times on the net, is enough to search by the words "AdMob fps drop" and the like.
The root of the problem here, most likely, is that running AdMob requires significant resources, which is why the animation starts to stall. As one solution, you can show ads with some delay:
Handler handler = new Handler ();
handler.postDelayed (new Runnable () {
#Override
public void run () {
AdRequest bannerRequest = new AdRequest.Builder (). Build ();
mAdView.loadAd (bannerRequest);
}
}, 2000);
You can make the delay not fixed, but bind it to user actions. For example, start downloading ads the moment after the user has stopped scrolling the screen.
Another solution is to disable graphics acceleration for ads by manipulating the LAYER_TYPE_SOFTWARE property.
mAdView.setAdListener(new AdListener(){
#Override
public void onAdLoaded(){
runOnWebView(mAdView, new WebViewAction(){
#Override
public void run(WebView view){
view.setLayerType(View.LAYER_TYPE_HARDWARE, null);
view.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
}
});
}
});
For such a solution, it is necessary to implement the following interface:
private void runOnWebView (View view, WebViewAction action) {
if (view instanceof WebView){
action.run((WebView)view);
return;
}
if (view instanceof ViewGroup) {
final ViewGroup parent = (ViewGroup)view;
for (int i = 0; i < parent.getChildCount(); i++) {
runOnWebView(parent.getChildAt(i), action);
}
}
}
private interface WebViewAction{
void run(WebView view);
}
Similarly, you can turn off the acceleration for some Activity:
<activity
android:hardwareAccelerated = "false"
android:softwareAccelerated = "false" />
As a workaround which I also have in my apps is setting a layertype:
mAdView.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
or
mAdView.setLayerType(View.LAYER_TYPE_HARDWARE, null);
I'd think, that the advertisments shouldn't be a banner, since that is a big advertisment, and that is slowing down the performance, as you should make it small. This also could cover things in your application, (if the advertisment is on banner).
Another thing is that you could not have ads, so that performance would be better. Try any of these. Ads most of the time have very good graphics and may slow down your application. :)
Place the ad view in a linear layout and implement ad listeners. In onAdLoaded() method of adListener add adView to your linear layout like linearLayout.addView(adView) and put your animation on linear layout. I hope it helps you.
Related
this is my xml code
i am trying to show the ad within a fragment
every thing work fine except for the ads
what ever i did it doesnot show , even when debuggibg using another device
also while pushing a new release with new version, it is now about 3 days "processing "
and now notifications are sent to testers. is it normal to take this time while processing a new release.
<com.google.android.gms.ads.AdView
android:id="#+id/adView_method_1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:visibility="visible"
app:adSize="SMART_BANNER"
app:adUnitId="ca-app-pub-6189698627273347/8329725005">
</com.google.android.gms.ads.AdView>
my java code
MobileAds.initialize(getActivity().getApplicationContext(), new OnInitializationCompleteListener() {
#Override
public void onInitializationComplete(InitializationStatus initializationStatus) {
}
});
List<String> testDeviceIds = Arrays.asList("3042108d-9adf-4586-b166-10ca1ad1abe1");
RequestConfiguration configuration =
new RequestConfiguration.Builder().setTestDeviceIds(testDeviceIds).build();
MobileAds.setRequestConfiguration(configuration);
adView = new AdView(getActivity());
AdRequest adRequest = new AdRequest.Builder().build();
adView.setAdUnitId("ca-app-pub-6189698627273347/8329725005");
adView.setAdSize(AdSize.SMART_BANNER);
adView.loadAd(adRequest);
In my application, I am using RecyclerView inside NestedScrollView and also, I am implementing pagination with this. I am attaching my piece of code below for implementing nested scroll view with pagination.
I have a large no data attaching to recyclerview, therefore, this data takes a lot of time attaching which effects the smooth scrolling of the list.
I had only a recylerview which had simple scrolling issues, wasn't smooth, but still pagination was working fine. I inserted my recyclerview inside the nestedscrollview, the scrolling becomes smooth only for the first page. But when pagination is called, the scrolling gets effected very badly.
When the page number increments, the scrolling goes from bad to worst.
Let me show my code that I used for nested view scrolling and pagination.
home.xml:
<android.support.v4.widget.NestedScrollView
android:id="#+id/nestedScroll"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.RecyclerView
android:id="#+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbars="none" />
</android.support.v4.widget.NestedScrollView>
And this is my Fragment Class.java:
#BindView(R.id.nestedScroll)
NestedScrollView nestedScroll;
private int currentPage = 0;
nestedScroll.getViewTreeObserver().addOnScrollChangedListener(new ViewTreeObserver.OnScrollChangedListener() {
#Override
public void onScrollChanged() {
View view = (View) nestedScroll.getChildAt(nestedScroll.getChildCount() - 1);
int diff = (view.getBottom() - (nestedScroll.getHeight() + nestedScroll.getScrollY()));
if (diff == 0) {
if (blnCheckREsult == false) {
blnCheckREsult = true;
if (ConnectivityReceiver.isConnected()) {
currentPage++;
getHomeData(currentPage);
} else {
Toast.makeText(activity, "Please check your internet connection", Toast.LENGTH_SHORT).show();
}
}
}
}
});
I want to implement smooth scrolling even when the adapter takes time while binding data to the view holder. But the scrolling becomes really slow when setting data inside the adapter.
Or If I am missing something else, please correct me.
Thanks in advance.
Try set this in your RecyclerView:
rv.setNestedScrollingEnabled(false);
before set adapter.
My activity is a Video Player Activity and its working fine, On some Videos it must throw a message (handleHardwareAccelerationError) if the video is not supported or high quality.
It shows as Toast with message fine.
Now I would like to change this Toast message to show a picture or small icon instead, is this possible? Here is my code for handleHardwareAccelerationError, Thanks in advance.
private void handleHardwareAccelerationError() {
mHardwareAccelerationError = true;
if (mSwitchingView)
return;
Toast.makeText(this, R.string.hardware_acceleration_error, Toast.LENGTH_LONG).show();
}
what I have tried is this but didnt show anything.
private void handleHardwareAccelerationError() {
mHardwareAccelerationError = true;
if (mSwitchingView)
return;
final View popupView = getLayoutInflater().inflate(R.layout.myinforbar, null);
mError = (ImageView) popupView.findViewById(R.id.errornew);
mError.setVisibility(View.VISIBLE);
}
and here is myinforbar.xml
<LinearLayout android:gravity="center_vertical" android:orientation="horizontal" android:layout_width="fill_parent" android:layout_height="21dp" android:layout_marginLeft="0.0dip" android:layout_marginTop="5.0dip"
android:background="#drawable/button5_background">
<ImageView
android:id="#+id/errornew"
android:src="#drawable/everyone_icon_nearby_cur"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:visibility="invisible"/>
</LinearLayout>
EDITED:
The original activity is long and it can be found here rather then pasting the whole activity you can see it here VideoPlayerActivity
( private void handleHardwareAccelerationError)
New Update...
This is without the message (onHardwareError) applied, I want to see icon inside this bottom little box that popup when video playing (infobar) instead of Toast message.
Toast is farily limited, you cannot show icons.
Edit: Gunjav Dave says it's possible, so it's approach worth a try.
Anyway this free library: SuperToast
can make what you need.
If you prefer to stick to Google's standards you can use, instead, the Snackbars, that don't allow, as far as I know, to put an icon, but can anyway be associated with an action/button, and they are standard.
I can't understand what you try to do with popupView, if you want to use a PopupWindow you have to use a completely different syntax. This Balloon Popup library of mine helps you to make a popup attached to a View, using a PopupWindow, you can also inflate into it a layout, or use it as an example on how to make a PopupWindow.
Edit:
You are inflating a layout inside a view, but this doesn't show the view. Instead, you should use a PopupWindow, and inflate inside it a layout.
This is an example taken from my BalloonPopup library:
// ....
hostedView = ((LayoutInflater) ctx.getSystemService(LAYOUT_INFLATER_SERVICE)).inflate(layoutRes, null);
textView = (TextView) hostedView.findViewById(R.id.text_view);
textView.setText(text);
// ....
popupWindow = new PopupWindow(hostedView, LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);
In other words, you should be able to do something like
PopupWindow popupWindow = new popupWindow(mError, LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);
in your code to show the popup window.
These are the essential points of the code, then you can reposition the popup, and eventually keep track of it to edit and re-show it instead of always creating from scratch. Please consider, anyway, to use BalloonPopup library, that does what you need, without getting crazy with animations, display times, window's permanence and positioning. You can just inflate into it your layout, for example with an icon and a text, and make it appear exactly on the center of another View, that can be your (already present) media player.
More edit:
Another very simple solution.
To get it simple, create a RelativeLayout, that hosts all your video player, and then create a simple ImageView in the center of it. Set its visibility to GONE when hidden and to VISIBLE when the error must be shown. Subsequently, you can use a timer or a touchListener to close it making it GONE again.
Try this
private void handleHardwareAccelerationError() {
mHardwareAccelerationError = true;
if (mSwitchingView)
return;
final View popupView = getLayoutInflater().inflate(R.layout.myinforbar, null);
PopupWindow pw = new PopupWindow(popupView , 300, 400, true);
pw.showAtLocation(popupView , Gravity.CENTER, 0, 0);
mError = (ImageView) popupView.findViewById(R.id.errornew);
mError.setVisibility(View.VISIBLE);
}
XML Name or Layout Name would be
<LinearLayout xmlns:androidclass="http://schemas.android.com/apk/res/android"
android:gravity="center_vertical"
android:orientation="horizontal"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#drawable/button5_background">
<ImageView
android:id="#+id/errornew"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/ic_launcher"/>
</LinearLayout>
Put This in Class:
LayoutInflater inflater = LayoutInflater.from(this);
View layout= inflater.inflate(R.layout.myinforbar, null);
Toast toast = new Toast(getApplicationContext());
toast.setDuration(Toast.LENGTH_SHORT);
toast.setGravity(Gravity.CENTER_VERTICAL, 0, 0);
toast.setView(layout);
toast.show();
using the most basic example with AppBarLayout and Toolbar, I cannot see the overscroll animation (the glow from bottom nor top) when trying to scroll more. However, if you fling the content, it will show it.
Here is the code (nav_drawer_toolbar_layout.xml):
<android.support.design.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<!-- Replace fragments in this content frame, like a RecycleView -->
<FrameLayout
android:id="#+id/content_frame"
app:layout_behavior="android.support.design.widget.AppBarLayout$ScrollingViewBehavior"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="#style/ThemeOverlay.AppCompat.Dark.ActionBar">
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:minHeight="?attr/actionBarSize"
app:titleTextAppearance="#style/Base.TextAppearance.AppCompat.Title"
app:popupTheme="#style/ThemeOverlay.AppCompat.Light"
app:layout_scrollFlags="scroll|enterAlways"/>
</android.support.design.widget.AppBarLayout>
</android.support.design.widget.CoordinatorLayout>
Followed by simple Activity class:
public class MyActivity extends AppCompatActivity implements {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.nav_drawer_toolbar_layout);
// Setup the toolbar/actionbar
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
FragmentManager manager = getFragmentManager();
manager.beginTransaction().replace(R.id.content_frame, new MyFragmentList).commit();
}
}
MyFragmentList is a fragment with a RecycleView with content to scroll the app.
However if I remove AppBarLayout from the xml and leave Toolbar open (just comment AppBarLayout opening and closing), it will show the overscroll animation (the glow) when scrolling.
Or if you remove layout_scrollFlags="scroll" then the overscroll works but you can't get the actionbar to hide when you scroll.
For extra information, debugging RecycleView, line 2272
if(this.mBottomGlow != null && !this.mBottomGlow.isFinished()) {
is always finished when including AppBarLayout and not finished when it is not there. Is something over-writing its touch events?
Does anyone know who to show overscroll animation (glow) with AppBarLayout?
EDIT: There seems to be a ticket for this bug. You could definintely do what artur.dr...#gmail.com did and extend RecyclerView to override RecyclerView#dispatchNestedScroll to always return false (he writes true in his report) you can get overscroll animations working, though i'm pretty sure it might break something down the line.
Unfortunately how RecyclerView is coded and how NestedScrollingChild API is made there is no clean way to have the desired behavior.
This is from RecyclerView (23.1.1, however I do not believe any version before it fixes the issue) inside the method scrollByInternal.
if (dispatchNestedScroll(consumedX, consumedY, unconsumedX, unconsumedY, mScrollOffset)) {
// Update the last touch co-ords, taking any scroll offset into account
mLastTouchX -= mScrollOffset[0];
mLastTouchY -= mScrollOffset[1];
if (ev != null) {
ev.offsetLocation(mScrollOffset[0], mScrollOffset[1]);
}
mNestedOffsets[0] += mScrollOffset[0];
mNestedOffsets[1] += mScrollOffset[1];
} else if (ViewCompat.getOverScrollMode(this) != ViewCompat.OVER_SCROLL_NEVER) {
if (ev != null) {
pullGlows(ev.getX(), unconsumedX, ev.getY(), unconsumedY);
}
considerReleasingGlowsOnScroll(x, y);
}
As we can see here on the javadoc for dispatchNestedScroll (part of the NestedScrollingChild API) as long as there is one parent that consumes the scroll, RecyclerView will not apply any overscroll animation (edge glow).
AppBarLayout does consume scrolling, more specifically as long as there is a NestedScrollingParent that returns true on onStartNestedScroll, overscroll animations will not happen.
CoordinatorLayout is a NestedScrollingParent but does not return true unless there is a CoordinatorLayout.Behavior that does. AppBarLayout's default behavior does implement this methdo to return true when there is vertical scrolling + AppBarLayout has something to scroll + view is big enough to scroll.
// Return true if we're nested scrolling vertically, and we have scrollable children
// and the scrolling view is big enough to scroll
final boolean started = (nestedScrollAxes & ViewCompat.SCROLL_AXIS_VERTICAL) != 0
&& child.hasScrollableChildren()
&& parent.getHeight() - directTargetChild.getHeight() <= child.getHeight();
Flinging takes a slightly different approach, allowing the overscroll animation happening regardless if the NestedScrollingParent is consuming the scrolling.
if (!dispatchNestedPreFling(velocityX, velocityY)) {
final boolean canScroll = canScrollHorizontal || canScrollVertical;
dispatchNestedFling(velocityX, velocityY, canScroll);
if (canScroll) {
velocityX = Math.max(-mMaxFlingVelocity, Math.min(velocityX, mMaxFlingVelocity));
velocityY = Math.max(-mMaxFlingVelocity, Math.min(velocityY, mMaxFlingVelocity));
mViewFlinger.fling(velocityX, velocityY);
return true;
}
}
Honestly I cannot tell if this is a bug because both logic make sense. If you are scrolling to the top part of the view, and you have something akin to a CollapsingToolbar, you wouldn't want an overscoll animation to happen. However there is a way to make it so that the behavior can consume the x/y amount of scrolling to stop the animation from happening. It is also weird that both code for scrolling and flinging is different.
I am using Admob for ads in my app and I ran into a problem. Whenever I turn the screen to landscape mode, the ad shows up but it's the same size as it was in portrait mode. This problem occured after I added this xml declaration in my manifest to my main activity that was necessary to keep the main parts of the app functioning smoothly:
android:configChanges="orientation|keyboardHidden|screenSize"
I am using smart banner in my ad for the size:
ads:adSize="SMART_BANNER"
I have attached pictures of this problem:
What do I have to do to get the ad to resize properly in landscape mode without deleting
android:configChanges="orientation|keyboardHidden|screenSize"
in the manifest for my main activity?
this is how I solved it:
#Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
orientation_changed = true;
renewAd();
}
private void renewAd() {
AdView ad = (AdView) findViewById(R.id.adView);
LayoutParams lp = (LayoutParams) ad.getLayoutParams();
// change relative layout for your layout which contains the adView
RelativeLayout parent = (RelativeLayout) ad.getParent();
parent.removeView(ad);
AdView newAd = new AdView(this, AdSize.SMART_BANNER, "YOUR ID");
newAd.setId(R.id.adView);
newAd.setLayoutParams(lp);
parent.addView(newAd);
newAd.loadAd(new AdRequest());
}
regards
In line with other responses (but updating them to the current AdMob SDK -v7.5-, and providing the full code), the onConfigurationChanged() method of the activity needs to include the destruction and creation of the Ad View:
// Remove the ad keeping the attributes
AdView ad = (AdView) myactivity.findViewById(R.id.adView);
LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) ad.getLayoutParams();
LinearLayout parentLayout = (LinearLayout) ad.getParent();
parentLayout.removeView(ad);
// Re-initialise the ad
ad.destroy();
ad = new AdView(parent);
ad.setAdSize(com.google.android.gms.ads.AdSize.SMART_BANNER);
ad.setAdUnitId(myactivity.getString(R.string.banner_ad_unit_id));
ad.setId(R.id.adView);
ad.setLayoutParams(lp);
parentLayout.addView(ad);
// Re-fetch add and check successful load
AdRequest adRequest = new AdRequest.Builder()
.addTestDevice(AdRequest.DEVICE_ID_EMULATOR)
.addTestDevice(parent.getString(R.string.test_device_id))
.build();