如何在列表视图中添加原生广告?

时间:2014-08-16 13:04:52

标签: android listview ads advertising

这是我的活动 我想在列表视图中插入原生广告。 我正在尝试遵循本指南https://github.com/StartApp-SDK/Documentation/wiki/android-advanced-usage但我觉得很难理解。 你可以帮我一把,也许可以举出代码示例吗?谢谢

活性

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 个答案:

答案 0 :(得分:5)

listView BaseAdapter首先调用方法getCount()来检索要显示的行数,然后为每行调用getView(int position, View convertView, ViewGroup parent)方法创建并返回一个View对象。给定的位置。

方法是扩展BaseAdapter并创建自己的自定义适配器,而不是使用默认的ArrayAdapter。然后,当您想要展示广告时,您需要返回“广告”视图而不是通常的普通视图。这意味着您需要覆盖getCount()以返回更多行(例如,如果您有10行,则表示您需要返回11 = 10个实际内容+ 1个广告)

然后你需要决定创建这个View的位置,我想你可以通过简单地检查position变量来做到这一点:

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

无论如何,这整件事情真的很棘手,因为事情很容易失控(与视图等不匹配的位置)。 StartApp应该能够控制listView适配器为您完成所有这些。我的猜测是你的适配器与StartApp无法正常通信(也许你没有正确初始化?)。

尝试深入了解文档或找到他们的示例。如果您无法弄明白,还可以使用其他替代品,如Avocarrot,Namomedia,Inmobi等。

我使用了Avocarrot ,它在github中有一个开源示例,用于在listViews中插入广告。 您可以运行它并在适合您的情况下使用它:https://github.com/Avocarrot/android-demo-app

答案 1 :(得分:0)

我不知道StartApp框架,但基本上你必须执行以下操作:

  1. 编写自己的适配器,不要使用ArrayAdapter。以下是可用于简化适配器视图回收的基础类:https://github.com/sockeqwe/appkit/blob/master/adapter/src/main/java/com/hannesdorfmann/appkit/adapter/SimpleAdapter.java

  2. 通过覆盖getItemViewType(int position)getViewTypeCount()

  3. 指定自己的查看单元格
  4. 为将出现在ListView中的横幅指定自己的视图类型和视图持有者。

  5. 根据我的看法,横幅广告需要在onSaveInstanceState()中保存并恢复onRestoreInstanceState()中的内容。我不确定这是否需要或在ListView中查看。只需在有或没有此电话的情况下尝试。如果需要,那么您必须在适配器中保留一个横幅项列表 必须在您的活动代码中执行类似的操作:

    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);
      } 
     }
    

答案 2 :(得分:0)

最近我坚持使用相同的问题,但是对于新的Admob原生广告。然后我决定将我的解决方案发布到admobadapter。希望它会对你有所帮助。我相信您可以在为StartApp-SDK进行一些自定义后使用AdmobAdapterWrapper ...请查看 AdmobFetcher.java 结果可能显示为this

答案 3 :(得分:0)

我已经在这方面工作了一段时间了。我正在为广告使用BaseAdapter和LinearLayout持有人。这些是我的全局变量:

LinearLayout adHolderView;
private AdRequest adRequest;
NativeExpressAdView singleAdView;

我还有一些其他全局变量:

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

以下是我的BaseAdapter,请阅读评论

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();
    }
};

您会在我的BaseAdapter中注意到我有一个名为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);

    }
}

由此您需要一些其他方法:

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;
}

最后,如果您最终使用的是GridView,则最后要添加的内容是为了在方向更改后加载正确尺寸的广告:

@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);
}