How to add native ads in a listview?

2019-03-30 13:35发布

this is my activity i want to insert a native ads into the list view. I'm trying to follow this guide https://github.com/StartApp-SDK/Documentation/wiki/android-advanced-usage But I find it hard to understand. can you give me a hand, maybe making examples of code? thank you

ACTIVITY

public class EpisodiActivity extends Activity {

private StartAppAd startAppAd = new StartAppAd(this);

public class ViewModel {
    private String url;
    private String name;

    public ViewModel(String url, String name) {
        this.url = url;
        this.name = name;
    }

    public String getUrl() {
        return this.url;
    }

    public void setUrl(String url) {
        this.url = url;
    }

    public String getName() {
        return this.name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String toString() {
        return this.name;
    }
}

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    // creazione fullscreen activity
    requestWindowFeature(Window.FEATURE_NO_TITLE);
    getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
            WindowManager.LayoutParams.FLAG_FULLSCREEN);
    setContentView(R.layout.episodi_activity);

    String[] episodi = getIntent().getStringArrayExtra("Product");
    String[] urls = getIntent().getStringArrayExtra("urls");

    ListView mylist = (ListView) findViewById(R.id.listView1);

    // And in this loop we create the ViewModel instances from
    // the name and url and add them all to a List
    List<ViewModel> models = new ArrayList<ViewModel>();
    for (int i = 0; i < episodi.length; i++) {
        String name = episodi[i];
        String url = "No value";
        if (i < urls.length) {
            url = urls[i];
        }
        ViewModel model = new ViewModel(url, name);
        models.add(model);
    }

    // Here we create the ArrayAdapter and assign it to the ListView
    // We pass the List of ViewModel instances into the ArrayAdapter
    final ArrayAdapter<ViewModel> adapter = new ArrayAdapter<ViewModel>(
            this, android.R.layout.simple_list_item_1, models);

    mylist.setAdapter(adapter);

    mylist.setOnItemClickListener(new AdapterView.OnItemClickListener() {
        public void onItemClick(AdapterView<?> arg0, View v, int position,
                long id) {

            // Here we get the ViewModel at the given position
            ViewModel model = (ViewModel) arg0.getItemAtPosition(position);

            // And the url from the ViewModel
            String url = model.getUrl();

            startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(url)));
        }
    });
}

@Override
public void onResume() {
    super.onResume();
    startAppAd.onResume();
    startAppAd.showAd();
}

@Override
public void onPause() {
    super.onPause();
    startAppAd.onPause();
}

}

4条回答
We Are One
2楼-- · 2019-03-30 14:06

Recently I stucked with the same question but for a new Admob native ads. Then I decided to post my solution for that to admobadapter. Hope it will help you. I believe you could use the AdmobAdapterWrapper after some customizations for the StartApp-SDK...Kindly look at the AdmobFetcher.java. The result could appear like this

查看更多
成全新的幸福
3楼-- · 2019-03-30 14:25

I've been working on this for a while now. I'm using a BaseAdapter and a LinearLayout holder for the ad. These are my global variables:

LinearLayout adHolderView;
private AdRequest adRequest;
NativeExpressAdView singleAdView;

I also have a few other global variables:

public static boolean adLoaded;
public static boolean allowShowAd = true;
public static int adLocation = 5;
Point adSanityCheck = new Point(0,0);

Here is my BaseAdapter, please read the comments

public BaseAdapter drawingsGridAdapter = new BaseAdapter() {

    //viewHolder classes are very common with BaseAdapters to speed up loading
    //It is not exactly needed but will be very usefull for different uses.
    //For example if you are using a GridView instead of a ListView like I am in this case
    //it would be good to have the orientation String which is used later on
    //in the adapter
    class ViewHolderItem {

        ImageView imageView;
        ImageView userImageView;
        TextView userNameView;
        TextView dateView;
        TextView numCommentsView;
        ImageView starView;
        TextView starCount;

        //below items are used for ads in a gridView
                int orientation;
                final int LANDSCAPE = 1;
                final int PORTRAIT = 2;
    }

    @SuppressLint("SimpleDateFormat")
    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        ViewHolderItem viewHolder;

        //check if you can use your viewHolderItem and make sure that
        //the view is not an Adview
        if (convertView == null || !(convertView.getTag() instanceof ViewHolderItem)) {
            viewHolder = new ViewHolderItem();
            LinearLayout ll = (LinearLayout) inflater.inflate(R.layout.gallery_item, null);
            viewHolder.dateView = (TextView) ll.findViewById(R.id.gal_item_date);
            //...
            //initialize your viewHolder items here
            //...
            convertView = ll;
            convertView.setTag(viewHolder);
        } else {
            viewHolder = (ViewHolderItem) convertView.getTag();
        }

        //...
        Tools.addDateToTextView(viewHolder.dateView, drawings.get(position).time);
        //do your view modifications here
        //...

    //now we start doing the ad stuff

        //this is optional. add it in to make it work on a gridview
        boolean landscape = false; if(getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE)
 landscape = true;

        //in my case I wanted the ad to be the same size as all my other Items so I made sure the values are accesable.
    //since you are only using a ListView, you only really need to check for getMeasuredHeight() or you could define your own
    //AdSize
        if (convertView.getMeasuredHeight()>0 && convertView.getMeasuredWidth()>0 && allowShowAd) {
            int adH = convertView.getMeasuredHeight();
            int adW = convertView.getMeasuredWidth();

    //if the adview needs to be set up then it will set it up, else it will make sure that the ad is the correct size
    //and fix it if it needs to
            if (singleAdView == null){
                if ((landscape && viewHolder.orientation == viewHolder.LANDSCAPE)
                        ||(!landscape && viewHolder.orientation == viewHolder.PORTRAIT))
                setUpAd(adW,adH, landscape);
            }else{
                if ((landscape && viewHolder.orientation == viewHolder.LANDSCAPE)
                        ||(!landscape && viewHolder.orientation == viewHolder.PORTRAIT)) {
                    //Log.d("ads","Adsize"+singleAdView.getAdSize());
                    if (singleAdView.getAdSize().getHeight() !=Tools.convertPixelsToDp(adH-1,MainMenuActivity.this)
                            || singleAdView.getAdSize().getWidth() !=Tools.convertPixelsToDp(adW-1,MainMenuActivity.this)) {
                        Log.d("Ads","ad sizesW:"+singleAdView.getAdSize().getWidth() + "vs" + Tools.convertPixelsToDp(adW-1,MainMenuActivity.this));
                        Log.d("Ads","ad sizesH:"+singleAdView.getAdSize().getHeight() + "vs" + Tools.convertPixelsToDp(adH-1,MainMenuActivity.this));

                        //sometimes the correct size is not reported so this will ensure ads are not loaded twice. This only really needs to be checked with a gridview
                        if (adSanityCheck.x == adW && adSanityCheck.y == adH) {
                            setUpAd(adW, adH, landscape);
                        }else{
                            adSanityCheck.x = adW;
                            adSanityCheck.y = adH;
                        }

                    }
                }
            }
        }//Log.d("Ads","tag ="+av.getTag());
        if (position == adLocation && singleAdView!=null && allowShowAd) {
            if (adLoaded) {
                adHolderView.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        //this seemed to help avoid ad flicker. may want to test to make sure
                        if (singleAdView!=null)
                            singleAdView.requestLayout();
                    }
                }, 100);
                return adHolderView;
            }
        }

        if (landscape)
            viewHolder.orientation = viewHolder.LANDSCAPE;
        else
            viewHolder.orientation = viewHolder.PORTRAIT;

        return convertView;
    }@Override
    public long getItemId(int position) {
        // TODO Auto-generated method stub
        return 0;
    }

    @Override
    public Object getItem(int position) {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public int getViewTypeCount() {
        return 2;
    }

    @Override
    public int getItemViewType(int position) {
        if (position == adLocation && singleAdView!=null && adLoaded && allowShowAd){
            return 1;
        }
        return 0;
    }

    @Override
    public int getCount() {
        return drawings.size();
    }
};

You will notice in my BaseAdapter, that I have a method called setUpAd:

private void setUpAd(int widthPX, int heightPX, boolean isLandscape){
    if (allowShowAd) {
        Log.d("draw", "setupAD");
        destroyAdView();

        adHolderView = new LinearLayout(MainMenuActivity.this);
        singleAdView = new NativeExpressAdView(this);

        adLoaded = false;

        drawingsGridAdapter.notifyDataSetChanged();
        singleAdView.setId(R.id.googleIdentify);
    singleAdView.setAdUnitId("ca-app-pub-xxxxxxxxxxxxxx/xxxxxxxxxxxxxx");
        int wh = Tools.convertPixelsToDp(widthPX - 1, MainMenuActivity.this);
        singleAdView.setAdSize(new AdSize(Tools.convertPixelsToDp(widthPX - 1, MainMenuActivity.this),
                Tools.convertPixelsToDp(heightPX - 1, MainMenuActivity.this)));
        adRequest = new AdRequest.Builder()
                .addTestDevice("TEST DEV ID")
                .build();
        singleAdView.setAdListener(new AdListener() {
            @Override
            public void onAdFailedToLoad(int errorCode) {
                super.onAdFailedToLoad(errorCode);
                adLoaded = false;
                drawingsGridAdapter.notifyDataSetChanged();
            }

            @Override
            public void onAdLoaded() {
                super.onAdLoaded();
                adLoaded = true;
                drawingsGridAdapter.notifyDataSetChanged();
            }
        });
        singleAdView.loadAd(adRequest);
        adHolderView.setLayoutParams(new LinearLayout.LayoutParams(widthPX, heightPX));
        adHolderView.setBackgroundColor(Color.WHITE);
        adHolderView.addView(singleAdView);

    }
}

From that you need a few other methods:

private void destroyAdView()
{
    if (singleAdView != null)
    {
        adRequest = null;
        singleAdView.removeAllViews();
        singleAdView.setAdListener(null);
        singleAdView.destroy();
        singleAdView.setEnabled(false);
        adHolderView.removeView(singleAdView);

        singleAdView = null;
        adHolderView = null;
    }
}

public static int convertPixelsToDp(float px, Context context){
    Resources resources = context.getResources();
    DisplayMetrics metrics = resources.getDisplayMetrics();
    float dp = px / ((float)metrics.densityDpi / DisplayMetrics.DENSITY_DEFAULT);
    return (int) dp;
}

And Finally, If you end up using a GridView, here is one last thing to add in order to load the right size ad after orientation changes:

@Override
public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);
        allowShowAd = false;

    gridView.postDelayed(new Runnable() {
        @Override
        public void run() {
    drawingsGridAdapter.notifyDataSetChanged();
            gridView.invalidateViews();
    gridView.requestLayout();
    gridView.postDelayed(new Runnable() {
    @Override
    public void run() {
        drawingsGridAdapter.notifyDataSetChanged();
    }
    },500);
    gridView.postDelayed(new Runnable() {
    @Override
    public void run() {
        allowShowAd = true;
        Log.d("Ads","allow ads now");
        drawingsGridAdapter.notifyDataSetChanged();
    }
    },1500);
        }
    }, 100);
}
查看更多
爷、活的狠高调
4楼-- · 2019-03-30 14:27

A listView BaseAdapter first calls the method getCount() to retrieve the number of rows to show and then for each row it calls the getView(int position, View convertView, ViewGroup parent) method to create and return a View object for the given position.

The approach is to extend BaseAdapter and create your own custom Adapter, instead of using the default ArrayAdapter. Then you need to return an “Ad” View instead of your usual normal View when you want to display an ad. This means that you need to override getCount() to return more rows (for example if you have 10 rows, that means you need to return 11 = 10 actual content + 1 ad)

Then you need to decide in which position to create this View, I think you can do it by simply checking the position variable:

if (position == VALUE) {
   // Create and return Ad View 
} else {
   // Create and return a normal View 
}

Anyway, this whole thing is really tricky as things can go easily out of hand (positions mismatching with Views etc). StartApp should be able to control your listView adapter to do all this for you. My guess is that your adapter is not communicating properly with StartApp (maybe you are not initialising correctly?).

Try to dig into the documentation or find an example by them. If you can’t figure it out, there are other alternatives you can use such as Avocarrot, Namomedia, Inmobi, etc

I have used Avocarrot which has an open source example in github for inserting ads in listViews. You can run it and use it if it fits you: https://github.com/Avocarrot/android-demo-app

查看更多
放荡不羁爱自由
5楼-- · 2019-03-30 14:29

I do not know the StartApp framework, but basically you have to do the following:

  1. Write your own adapter and do not use ArrayAdapter. Here is a basis class you can use to simplify the adapters view recycling: https://github.com/sockeqwe/appkit/blob/master/adapter/src/main/java/com/hannesdorfmann/appkit/adapter/SimpleAdapter.java

  2. Specify own View cells by overriding getItemViewType(int position) and getViewTypeCount()

  3. Specify a own view type and view holder for your banners that will appear in the ListView.

  4. From what I have seen, the banner needs to save something in onSaveInstanceState() and to restore something in onRestoreInstanceState() . Im not sure if this is needed or makes sence in a ListView. Simply try it with or without this calls. If this is needed, than you have to keep a List of Banner Items in you adapter and you have to do something like this in your Activities code:

    public class MyActivity extends Activity 
    {    
      public void onSaveInstanceState(Bundle b){
      super.onSaveInstanceState(b);
      adapter.saveInstancState(b);
     }
    
      public void restoreInstanceState(Bundle b){
      super.restoreInstanceState(b);
      adapter.restoreInstanceState(b);
      } 
     }
    
查看更多
登录 后发表回答