我的一位用户把猫从袋子里拿出来告诉我他们正在使用我的一款免费应用程序,该应用程序通过广告获利,但他们使用广告拦截器屏蔽了广告。他们嘲笑地告诉我这件事,好像我对此无能为力。
我能做点什么吗?有没有办法检测广告被阻止?
我知道广告拦截的一种工作方式(实际上在任何计算机上),他们编辑主机文件以指向所有已知广告服务器的 localhost。对于 android,它位于“etc/hosts”文件中。
例如,我使用 admob 广告,我从自定义 rom 中获取的主机文件列出了以下 admob 条目:
127.0.0.1 analytics.admob.com
127.0.0.1 mmv.admob.com
127.0.0.1 mm.admob.com
127.0.0.1 admob.com
127.0.0.1 a.admob.com
127.0.0.1 jp.admob.com
127.0.0.1 c.admob.com
127.0.0.1 p.admob.com
127.0.0.1 mm1.vip.sc1.admob.com
127.0.0.1 media.admob.com
127.0.0.1 e.admob.com
现在,任何时候进程尝试解析上述地址,在这种情况下,它们都会被路由到它们左侧列出的地址(localhost)。
我在我的应用程序中所做的是检查此主机文件并查找任何 admob 条目,如果我发现任何我通知用户我已检测到广告拦截并告诉他们从那里删除 admob 条目并且不允许他们使用应用程序。
毕竟,如果他们没有看到广告,这对我有什么好处?让他们免费使用该应用程序毫无意义。
这是我如何实现这一目标的代码片段:
BufferedReader in = null;
try
{
in = new BufferedReader(new InputStreamReader(
new FileInputStream("/etc/hosts")));
String line;
while ((line = in.readLine()) != null)
{
if (line.contains("admob"))
{
result = false;
break;
}
}
}
我发誓所有支持广告的应用程序都应该检查这个文件。您无需成为 root 即可访问它,但写入它可能是另一回事。
此外,不确定是否有任何其他文件在基于 linux 的操作系统上表现相同,但无论如何我们总是可以检查所有这些文件。
欢迎任何关于改进这一点的建议。
此外,名为“Ad Free android”的应用程序需要 root 访问权限,这意味着它很可能会更改主机文件以实现其目标。
因此,我对这个问题的代码是: -
try {
if (InetAddress.getByName("a.admob.com").getHostAddress().equals("127.0.0.1") ||
InetAddress.getByName("mm.admob.com").getHostAddress().equals("127.0.0.1") ||
InetAddress.getByName("p.admob.com").getHostAddress().equals("127.0.0.1") ||
InetAddress.getByName("r.admob.com").getHostAddress().equals("127.0.0.1")) {
//Naughty Boy - Punishing code goes here.
// In my case its a dialog which goes to the pay-for version
// of my application in the market once the dialog is closed.
}
} catch (UnknownHostException e) { } //no internet
希望有帮助。
作为开发人员,我们需要完成与用户同理心的艰巨工作,并在惩罚少数试图利用的人和许多遵守规则的人之间找到一个中间立场。移动广告是一种允许人们免费使用功能性软件的合理方式。使用广告拦截技术的用户可能会被视为收入损失,但如果您从大局来看,也可能是那些喜欢您的应用程序的人。在广告被屏蔽的系统上运行的一种更温和的方法是展示您自己的“自家”广告。创建一个或多个横幅图像,并使用ImageView将它们显示在与普通广告相同的位置相同的高度(例如 50dp)。如果您成功收到广告,请将 ImageView 的可见性设置为 View.GONE。您甚至可以创建一个计时器来循环播放多个自家广告以吸引用户的注意力。单击您的广告可以将用户带到市场页面以购买完整版本。
你能检查一下你的应用中是否加载了广告吗?
广告拦截器通过阻止您的应用下载数据来发挥作用。您可以检查广告框架中数据的内容长度,以确保那里有数据。
如果没有数据抛出一条消息并退出或通过电子邮件警告您。
这可能不像您想象的那么大,因为只有一小部分人会屏蔽广告。
前两个答案仅帮助您使用特定的(如果可能是最流行的)阻止广告的方法。Root 用户还可以使用设备上的防火墙阻止广告。WiFi 用户可以使用上游防火墙阻止广告。
我建议:
不要奖励屏蔽广告的用户。确保您的布局为广告保留部分显示,即使无法加载广告。或者,如果您有一个播放一段时间的全屏广告,请确保您的应用等待一段时间,即使该广告无法播放。如果您将通知用作广告(您是渣滓),请在您未能获得此类广告时通知用户。这可以理解为“惹恼所有用户”,但您的普通用户知道他们得到了什么,并且您的广告屏蔽“用户”不受欢迎。
要求广告拦截器停止。提供用户想要的东西的行业利润越低,该行业提供的用户想要的东西就越少。个人开发者会发现他为其他用户赚了更多的钱。您知道这一点,并且您的用户在您告诉他们之后会认为这是显而易见的,但这仍然是一个经济论点 - 它不直观。有一个备用广告,上面写着“这是我的工作。如果你不付钱给我,我会再买一个,你不会再从我这里得到更多这样的应用程序了。”
没有什么是你能做的,你的用户不能做得更好。
唯一想到的远程有效就是让广告成为程序不可分割的一部分,这样如果它们被阻止,用户就无法理解应用程序/与应用程序交互。
我的方法不是检查单个软件安装或修改的主机文件,而是使用这样的 AdListener ,如果由于NETWORK_ERROR广告无法加载,我只是获取一些随机的始终在线页面(用于踢球,apple.com)并检查页面是否加载成功。
如果是这样,则使用该应用程序繁荣。
要添加一些代码,侦听器类将类似于:
public abstract class AdBlockerListener implements AdListener {
@Override
public void onFailedToReceiveAd(Ad arg0, ErrorCode arg1) {
if (arg1.equals(ErrorCode.NETWORK_ERROR)) {
try {
URL url = new URL("http://www.apple.com/");
URLConnection conn = url.openConnection();
BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
reader.readLine();
onAdBlocked();
} catch (IOException e) {}
}
}
public abstract void onAdBlocked();
}
然后每个带有 adView 的活动都会执行以下操作:
AdView adView = (AdView) findViewById(R.id.adView);
adView.setAdListener(new AdBlockerListener() {
@Override
public void onAdBlocked() {
AlertDialog ad = new AlertDialog.Builder(CalendarView.this)
.setMessage("nono")
.setCancelable(false)
.setNegativeButton("OK", new OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
System.exit(1);
}
})
.show();
}
});
我认为这取决于广告的内容提供商。我知道 AdMob SDK 在广告请求失败时会提供回调。我怀疑您可能可以为此注册,然后在回调中检查连接 - 如果有连接并且您没有收到广告 - 请注意,如果它发生超过一次或两次,很可能是您的广告被屏蔽。我没有使用过 Google 的 AdSense for Mobile 工具集,但如果有类似的回调机制,我不会感到惊讶。
用户绕过广告有两种方式:
1)在没有互联网的情况下使用应用程序。
2) 使用 root 手机和修改过的主机文件。
我制作了两个可以实现的工具,请参见下面的代码。
checkifonline(); 适用于问题 1:
public void checkifonline() {
boolean haveConnectedWifi = false;
boolean haveConnectedMobile = false;
ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo[] netInfo = cm.getAllNetworkInfo();
for (NetworkInfo ni : netInfo) {
if (ni.getTypeName().equalsIgnoreCase("WIFI"))
if (ni.isConnected())
haveConnectedWifi = true;
if (ni.getTypeName().equalsIgnoreCase("MOBILE"))
if (ni.isConnected())
haveConnectedMobile = true;
}
if(haveConnectedWifi==false && haveConnectedMobile==false){
// TODO (could make massage and than finish();
}
}
广告块检查();是针对问题 2
private void adblockcheck() {
BufferedReader in = null;
boolean result = true;
try
{
in = new BufferedReader(new InputStreamReader(
new FileInputStream("/etc/hosts")));
String line;
while ((line = in.readLine()) != null)
{
if (line.contains("admob"))
{
result = false;
break;
}
}
} catch (UnknownHostException e) { }
catch (IOException e) {e.printStackTrace();}
if(result==false){
// TODO (could make massage and than finish();
}
}
这是先前答案的扩展。用户告诉我他们正在使用的应用程序称为 AdFree Android。它可以在市场上找到。该应用程序表示它的工作原理是“取消对服务广告的已知主机名的请求”。
我建议,如果您通过广告从您的任何应用程序中获利,请在启动时检查该程序并给用户一条讨厌的消息,然后终止您的应用程序。
首先,让我说,我认为广告拦截在应用程序方面实际上是一种盗版形式。广告支持这些应用程序,有时还有“付费许可证”来关闭广告和/或添加功能。通过屏蔽广告,用户正在从花时间创建您正在使用的应用程序的开发人员那里窃取潜在收入。
无论如何,我想添加一种方法来帮助防止使用广告拦截器。我使用这种方法,如果我检测到广告拦截器,我不允许用户使用该应用程序。人们会很生气,会给你很差的评价。但我也在我的应用程序描述中非常清楚地指出,如果您有广告拦截器,您将无法使用该应用程序。
我使用包管理器来检查是否安装了特定的包。虽然这不会获得所有的广告拦截器,但如果您对一些流行的广告拦截器保持“最新”,您可以获得大部分广告拦截器。
PackageManager pm = activity.getPackageManager ();
Intent intent = pm.getLaunchIntentForPackage ( "de.ub0r.android.adBlock" );
if ( Reflection.isPackageInstalled ( activity, intent ) ) {
// they have adblock installed
}
为您的用户提供一种在没有广告的情况下使用应用程序的方式。我个人认为广告是我电脑上可能发生的最烦人的事情之一,如果它能让我免于被广告扔到我脸上的侮辱,我会很乐意为应用程序付费。而且我确定我不是唯一一个。
对于没有互联网连接的情况,我按照本 教程进行操作 ,并构建了一个“网络状态侦听器”,如下所示:
private BroadcastReceiver mConnReceiver = new BroadcastReceiver()
{
@Override
public void onReceive(Context context, Intent intent)
{
boolean noConnectivity = intent.getBooleanExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, false);
if (noConnectivity == true)
{
Log.d(TAG, "No internet connection");
image.setVisibility(View.VISIBLE);
}
else
{
Log.d(TAG, "Interet connection is UP");
image.setVisibility(View.GONE);
add.loadAd(new AdRequest());
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState)
{
//other stuff
private ImageView image = (ImageView) findViewById(R.id.banner_main);
private AdView add = (AdView) findViewById(R.id.ad_main);
add.setAdListener(new AdListener());
}
@Override
protected void onResume()
{
registerReceiver(mConnReceiver, new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION));
super.onResume();
}
@Override
protected void onPause()
{
unregisterReceiver(mConnReceiver);
super.onPause();
}
registerReceiver 和 unregisterReceiver 必须分别在 onResume 和 onPause 中调用,如此处所述。
在您的布局 xml 中设置您自己选择的 AdView 和 ImageView,如下所示:
<com.google.ads.AdView xmlns:googleads="http://schemas.android.com/apk/lib/com.google.ads"
android:layout_alignParentBottom="true"
android:id="@+id/ad_main"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
googleads:adSize="BANNER"
googleads:adUnitId="@string/admob_id" />
<ImageView
android:id="@+id/banner_main"
android:layout_centerInParent="true"
android:layout_alignParentBottom="true"
android:layout_width="379dp"
android:layout_height="50dp"
android:visibility="gone"
android:background="@drawable/banner_en_final" />
现在,只要互联网连接可用,广告就会显示,而当它关闭时,ImageView 会弹出,反之亦然。这必须在您希望展示广告的每个活动中完成。
我确信这个答案不会完全受到某些开发人员的欢迎,但是请考虑如果您属于这一类别,那么您的应用可能不应该在应用商店中存在。请注意,这些都可以通过代码更改来实现,不需要黑客或间谍软件之类的行为。
基本上,改变你的应用程序的经济性。用户永远是对的——这是有史以来最成功的广告公司之一(谷歌)所采取的态度。如果您的广告被用户屏蔽,那是因为您很烂,而不是因为广告或广告拦截器很烂。
http://books.google.com/books/about/The_User_is_Always_Right.html?id=gLjPMUjVvs0C
我重申:以上所有更改都是您可以在代码中合法执行的操作,以防止反广告行为。出于安全原因和本能反应(主要是带宽和性能),广告被屏蔽,因此请确保您的广告不会在代码级别引发任何这些问题。
最后,我确实想谈谈 Borealid 所说的,我在上面重复了一遍;归根结底,这是一场“猫捉老鼠”的游戏,因为用户在法律和道德上对自己的财产拥有最终的权力和责任。用户可以做任何事情,包括直接修改代码。当然,您可以实施一些限制等,但总有办法解决这个问题。这是 DRM 的最终问题(技术上)(这是您想要做的)。与其在这款游戏上浪费时间和精力,还不如鼓励用户不停地投放广告;他们将免费成为您最好、最聪明的反广告拦截器。
除了检查是否可以解决 admob 之外,我所做的是提供一个页面,该页面基本上表明我检测到了一个 adblocker,声明我理解可能的原因,然后显示一些我自己的应用程序的内置广告并询问他们的种类支持持续发展。:)