How to make an app that syncs via internet for Android - android

I need a bit of help phrased in easy to understand terms. I've tried asking this question on multiple forums, but keep getting answers back that assume some knowledge even though I specified that I have only rudimentary skills in Android building and Java.
The user Skynet was very helpful when I asked my initial question here, but the research he/she prompted me to do proved difficult to follow up on.
https://stackoverflow.com/questions/28403243/how-to-make-an-app-that-syncs-via-internet
I want to make an app with a textview that updates via internet everytime the user open the app.
What is the best way to do this? And what would I have to do to do it?
Thank you in advance!
To get an idea of how new to this I am, here's an app I've published: https://play.google.com/store/apps/details?id=theveshtheva.debatebreaker
EDIT: I'm trying something but it doesn't seem to work. Could someone tell me what I'm doing wrong?
The webpage I'm trying to pull data from is here:
http://ktjdaily.blogspot.com/2015/02/menu-of-day.html
Here's my activity java file:
package theveshtheva.practice;
import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import android.widget.TextView;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.protocol.BasicHttpContext;
import org.apache.http.protocol.HttpContext;
public class onlinetext extends ActionBarActivity {
private String HTML;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_onlinetext);
/*FROM HERE*/
TextView outtext = (TextView) findViewById(R.id.textView);
try {
getHTML();
} catch (Exception e) {
e.printStackTrace();
}
outtext.setText("" + HTML);
/*TO HERE*/
}
private void getHTML() throws IOException
{
HttpClient httpClient = new DefaultHttpClient();
HttpContext localContext = new BasicHttpContext();
HttpGet httpGet = new HttpGet("http://ktjdaily.blogspot.com/2015/02/menu-of-day.html"); //URL!
HttpResponse response = httpClient.execute(httpGet, localContext);
String result = "";
BufferedReader reader = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
String line;
while ((line = reader.readLine()) != null) {
result += line + "\n";
HTML = result;
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_onlinetext, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
And here's the Manifest file, where I've set permissions:
<?xml version="1.0" encoding="utf-8" ?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="theveshtheva.practice">
<uses-permission android:name="android.permission.INTERNET" />
<application android:allowBackup="true" android:icon="#drawable/ic_launcher" android:label="#string/app_name" android:theme="#style/AppTheme">
<activity android:name=".onlinetext" android:label="#string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>

There are HTTP apis already in Android that do this. There's like an Earthquake monitor sample application that pulls XML via HTTP in a background service.
Start there.

I feel like there is a lot of questions on how to sync android apps with online services or backend systems in general. So basically, I will try to expose here some ways you may have of doing so and I will try to keep it as simple as possible:
1)The world outside your mobile application
Ok, so you want to make an app that sends and retrieves information from through the internet...fine! But first of all, before even thinking about your app, have you thought about your server? the online service that holds the info your app should manipulate? So, yes! Your server/service should be ready and working when you start to think about writing an application that will do any online sync. By the way, a reasonable advice would be to start facing the term "application" as your whole service environment , including mobile apps and everything, not just one single mobile application per say.
If you have your own online service good to go or you just need to use 3rd party online services that are also ready, then that's the end of step 1.
2)Communicating with the outside world
Here you already have your functional online service. Now you need to set ways of communicating with it. Think as the "communication part" as a different project. Don't think it as just a bridge between your mobile app and your backend system. Think it as a bridge for any application from any environment to your system. A unique way that apps can reach your system and your system can reach them, exchanging valuable information for what they concern. We have some options here, but I will stick with the RESTApi. I won't describe here what is a RESTApi and how you actually write code around it(I guess that must be one of your biggest concerns), because someone already did in this epic SO question.
What you really need to understand here is the whole concept and then later you can checkout some frameworks(there are a lot) to actually implement it(you'll see that is the easiest part). To end the step 2, here is a REALLY simple diagram to show it (not the best, I know):
3) Finally, your android app
As using RESTApi , we're going to handle http requests. In order to do so, we have many ways of doing it in our android application. I will provide some code using the built-in HttpClient for better understanding : RestClient.java . This class is a real basic rest client that will do POST and GET http requests by just:
RestClient client = new RestClient();
client.execute("http://youronlineservice.com:3430/api/somegetrequest",RequestMethod.GET);
client.execute("http://youronlineservice.com:3430/api/somepostrequest",RequestMethod.POST);
Now, when dealing with the android environment, be careful with NetworkOnMainThreadException:
The exception that is thrown when an application attempts to perform a networking operation on its main thread.
Therefore, I strong recommend the use of AsyncTask when dealing with simple http requests, because:
AsyncTask enables proper and easy use of the UI thread. This class allows to perform background operations and publish results on the UI thread without having to manipulate threads and/or handlers.
AsyncTask is designed to be a helper class around Thread and Handler and does not constitute a generic threading framework. AsyncTasks should ideally be used for short operations (a few seconds at the most.) If you need to keep threads running for long periods of time, it is highly recommended you use the various APIs provided by the java.util.concurrent package such as Executor, ThreadPoolExecutor and FutureTask.
An asynchronous task is defined by a computation that runs on a background thread and whose result is published on the UI thread. An asynchronous task is defined by 3 generic types, called Params, Progress and Result, and 4 steps, called onPreExecute, doInBackground, onProgressUpdate and onPostExecute.
For ending, as you may be wondering, when you do a http request for your api you have to handle the response that will come. As you will figure out, there will be various types you can treat responses depending on the format you designed your api to work.
Mainly, you'll probably work with XML or JSON. But don't worry! There are plenty of stuff on how working with these formats in your android applications, including some awesome frameworks that you better discover yourself to see what fits you best.
After you're done with this, you may want to check some other stuff to increase the sync experience in your app, such as:
http://developer.android.com/training/sync-adapters/creating-sync-adapter.html
http://developer.android.com/reference/android/app/Service.html
And keep in mind that the best references you can get are here: http://developer.android.com/training/index.html
Hope it can help you and others!

Related

jsoup not working on android

I have a problem with jsoup on android. I have seen the other posts and tried solutions that were suggested there ( re-adding the jars, calling android fix tool, etc.)
I have added the jsoup jar to my android project (using build path), and added the required
internet permission to my manifest.
<uses-permission android:name="android.permission.INTERNET" />
but when I am trying to run my application I am getting
Could not find method org.jsoup.Jsoup.connect, referenced from method com.example.test.MainActivity.onCreate
I have tried to use the android fix tool but it did not solve the problem.
All I have is a main activity and I am trying to call
Document doc = Jsoup.connect("http://en.wikipedia.org/").get();
attached is part of my code
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
try {
Document doc = Jsoup.connect("http://en.wikipedia.org/").get();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
You are trying to run your connection in your main thread. Use AsyncTask and it will work.
I.E.
public class JsoupParser extends AsyncTask...
Why you have to use AsyncTask for network connections in android?
AsyncTask is an abstract helper class that enables you to use the UI thread correctly, while performing background operations in a different thread, without having to really handle threads or controllers. Since android is implemented using a single thread model, each time you launch an application, a new thread will be created.
Imagine you have a single thread model where you at a button click will parse a website using Jsoup. This would have worked fine in earler android versions, though you would have had a non-responsive screen until the network operation is done. The AsyncTask will run in the background enabling your screen to still be responsive while another thread takes care of the network communication.
Take a look in the API:
AsyncTask
NetworkOnMainThreadException
Delete all statements like:
System.out.println(something);
It worked for me, realizing this took me 2 hours.
In you normal activity
use this
public static int SDK_INT = android.os.Build.VERSION.SDK_INT;
and before fetching Document
write this inside try block
if (SDK_INT >= 10) {
ThreadPolicy tp = ThreadPolicy.LAX;
StrictMode.setThreadPolicy(tp);
}
it worked for me

Mobile backend starter continuous query never returns

I've written an Android client for a mobile backend starter app according to this tutorial. Everything works up to the section implementing Continuous Queries.
I've written a query and I'm calling it from the correct place in the code (onPostCreate()), however the query never returns any data.
I don't believe this is an authentication problem because I'm able to make other calls successfully.
Here is the code which never returns a result:
CloudCallbackHandler<List<CloudEntity>> handler = new CloudCallbackHandler<List<CloudEntity>>() {
#Override
public void onComplete(List<CloudEntity> results) {
for (CloudEntity entity : results) {
UserLocation loc = new UserLocation(entity);
mUserLocations.remove(loc);
mUserLocations.add(loc);
drawMarkers();
}
}
#Override
public void onError(IOException e) {
Toast.makeText(getApplicationContext(), e.getMessage(),
Toast.LENGTH_LONG).show();
}
};
CloudQuery query = new CloudQuery("UserLocation");
query.setLimit(50);
query.setSort(CloudEntity.PROP_UPDATED_AT, Order.DESC);
query.setScope(Scope.FUTURE_AND_PAST);
getCloudBackend().list(query, handler);
With the debugger I've verified that the getCloudBackend().list() line executes, but the onComplete() method is never hit, and neither is onError().
Here is an example of a call that works perfectly:
UserLocation self = new UserLocation(super.getAccountName(),
gh.encode(mCurrentLocation));
getCloudBackend().update(self.asEntity(), updateHandler);
Essentially, getCloudBackend().update() works, while getCloudBackend().list() does not.
I should also add that I've downloaded the full source from the github repo linked in the tutorial, and the same problem exists with that code.
I've also tried re-deploying the backend server multiple times.
Ok so I have finally fixed the problem! The issue is both in the manifest and in the class GCMIntentService.java
In the manifest the GCM is registered as a service and belongs to a package. By default this service is a part of the default package com.google.cloud.backend.android. When you create a new package and have all your client code in there, you need to move the GCMIntentService.java class into that new package and in the manifest modify the service and broadcast receiver
<service android:name="yourpackagename.GCMIntentService" />
<receiver
android:name="com.google.android.gcm.GCMBroadcastReceiver"
android:permission="com.google.android.c2dm.permission.SEND" >
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
<action android:name="com.google.android.c2dm.intent.REGISTRATION" />
<category android:name="yourpackagename" />
</intent-filter>
</receiver>
Any other permission that comes with the default package name should also be updated to the main package name. This doesn't need to be modified if you're only going to use that one default package that comes with the mobile backend starter.
Regarding the GoogleAuthIOException I received that as well initially. So I redid all the steps to enable GCM and authentication. Things to keep in mind though are that I still followed the tutorial and went with Web Application -> Generic when registering the GCM server key and Web Client ID. Also another key thing to keep in mind when registering for the Android Client ID is that with your SHA1 fingerprint it also needs a package name. Again the package name has to be your main client package if you're using more than one package for your project. You can get the project number that goes in the Consts.java (and it's required to register GCM) from the old Google API console and the project ID from the new cloud console. The Web client ID also goes in the Consts.java file and also in that same file you have to enable auth by changing
public static final boolean IS_AUTH_ENABLED = false;
to
public static final boolean IS_AUTH_ENABLED = true;
Hope this helps.
So I am also getting the SAME EXACT problem you are. getCloudBackend().update() works for me, and not only with the geohasher class, I also tried to send updates to the cloud with myLocation.toString() where myLocation is a LatLng and it gets updated fine.
Sorry for not giving you the actual solution to your problem. It's a really odd situation that the same exact code worked in the Google I/O demo but not when we (and I followed the tutorial very thoroughly) actually try it out. I feel that this is a server problem if anything.
Thanks for reporting this -- sorry you are having a problem. THe most likely problem is in configuring GCM. Can you verify you have GCM enabled on the project and all the setup steps where done correctly? Maybe try to send a message and see if that works?

Detect if an android app is running on background

I want to check if my app is running on a background mode.
The problem is that i have many activities(list activities, map activities etc.). Initially I have tried in the life cycle's resume and pause(or the onUserLeaveHint) methods to set a static boolean as true or false and work with this way. But this obviously can't work because when I move from one activity to another, the previous one get paused.
Also, I've read here on stackoverflow that the getRunningTasks() should be used only for debugging purposes. I did a huge research but I can't find a solution. All I want to do is to be able to detect if a the app is running on a background. Can anyone propose me a way, or express any thought on how can I do that?
You can try the same mechanism (a boolean attribute) but on application side rather than activity side. Create a class which extends Application, declare it in the manifest file under <application android:name=YourClassApp>.
EDIT: I assume you know that activities aren't intended for background processing, if not you should take a look at the Services.
I don't know if this will help but you can use
getApplicaton().registerActivityLifecycleCallbacks(yourClass);
To get a birds eye view of how your activities are displayed in the FG. (For older s/w you can use this)
If your Application has a Service you could have a static get/set which accesses a static variable. Do not do this in Activities though, it causes mem leaks.
But realistically speaking there is no tidy way of tracking if your application is running or not.
I had the same problemen when overwriting the Firebase push messaging default behavior (show notifications only when in the background) I checked how Firebase did this by looking in the .class file com.google.firebase.messaging.zzb:53 (firebase-messaging:19.0.1) which appears to us getRunningAppProcesses. Mind you FireBase is created by Google them self. So I'm assuming it's pretty save to use. Cleaned up version:
List<ActivityManager.RunningAppProcessInfo> runningApps;
boolean isInForeground =false;
if ((runningApps = ((ActivityManager)this.getApplication().getSystemService(Context.ACTIVITY_SERVICE)).getRunningAppProcesses()) != null) {
Iterator runningApp = runningApps.iterator();
int myPid = Process.myPid();
while(runningApp.hasNext()) {
ActivityManager.RunningAppProcessInfo processInfo;
if ((processInfo = (ActivityManager.RunningAppProcessInfo)runningApp.next()).pid == myPid) {
isInForeground = processInfo.importance == 100;
break;
}
}
}

Android HTTP Client Problems

I'm hoping someone can find this problem. I had an app that was fully working in server communications. Unfortunately, I somehow lost my Eclipse workspace when moving to the Windows 8 CP. I still had the .apk, and using Dex2jar and jd-gui, I was able to salvage a lot of code. I've got it all back into working condition, but this. I'm attempting to send a URL to a server, and get back a string response. Here's the code:
import org.apache.http.client.HttpClient;
import org.apache.http.client.ResponseHandler;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.BasicResponseHandler;
import org.apache.http.impl.client.DefaultHttpClient;
public class login extends Activity{
<code>
public void pushLogin(View paramView){
try{
HttpClient client = new DefaultHttpClient();
HttpGet request = new HttpGet(loginFinal);
ResponseHandler<String> responseHandler = new BasicResponseHandler();
errorTextView.setText(loginFinal);
//code gets here
String response = client.execute(request, responseHandler);
//does not get here
errorTextView.setText(response);
}
My TextView always contains the string loginFinal, I cannot get it to display the response. To check this, I moved the errorTextView.setText(loginFinal); to the line after attempting to get the String response. It didn't run at that point either. I'm tearing my hair out, and I'm sure it's something simple. I've got the internet permission, I even found my original code for this portion of the app on this site as I posted it asking a separate question. This code is, as far as I can tell, identical. The only thing I can think of that changed is I moved my build target from Froyo to Honeycomb, as I decided I want to focus on tablets.
The best part is that LogCat does absolutely nothing when I press the button, triggering pushLogin. It doesn't seem to be triggering the client.execute(request, responseHandler) at all.
You are probably call pushLogin() on UI thread, Note that the thread policy has been changed since API Level 11 (HONEYCOMB), which in short, does not allow network operation (include HttpClient and HttpUrlConnection) get executed on UI thread, otherwise you get NetworkOnMainThreadException. The correct strategy is to call pushLogin() on background thread (AsycnTask as a good example).
Hope this help.

How to prevent ad blocker from blocking ads on an app

One of my users let the cat out of the bag and told me they were using one of my free apps, which is monetized by ads, but they were blocking the ads with an ad blocker. They told me this mockingly, as if I can't do anything about it.
Can I do something about it? Is there a way to detect that ads are being blocked?
I am aware of one way that ad blocking works (on any computer really), they edit the hosts file to point to localhost for all known ad servers. For android this is located in the "etc/hosts" file.
For example, I use admob ads and a host file that I have taken from custom rom lists the folowing admob entries:
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
Now anytime a process tries to resolve the above addresses they are routed to the address listed to the left of them (localhost) in this case.
What I do in my apps is check this host file and look for any admob entries, if I find any I notify the user that I've detected ad blocking and tell them to remove admob entries from there and do't allow them use of the app.
After all what good does it do me if they're not seeing ads? No point in letting them use the app for free.
Here is a code snippet of how I achieve that:
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;
}
}
}
I vow that all ad supported apps should check this file. You do not need to be root in order to access it, but writing to it might be a different story.
Also, not sure if there is any other files that act the same on a linux based OS, but at any rate we can always check all of those files.
Any suggestions on improving this are welcome.
Also the app called "Ad Free android" needs root access, meaning that it most likely changes the hosts file in order to achieve its goal.
My code for this issue is thusly: -
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
Hope that helps.
As developers, we need to do the difficult job of empathizing with the users and find a middle ground between punishing the few who try to take advantage and the many who play by the rules. Mobile advertising is a reasonable way to allow someone to use a functional piece of software for free. The users who employ ad blocking techniques could be considered lost revenue, but if you take a look at the big picture, can also be those who spread the word about your application if they like it. A more gentle approach to running on systems with ads blocked is to display your own "house" ad. Create one or more banner images and display them in the same spot as your normal ad with an ImageView of the same height (e.g. 50dp). If you successfully receive an ad, then set your ImageView's visibility to View.GONE. You can even create a timer to cycle through several house ads to get the user's attention. Clicking on your ad can take the user to the market page to buy the full version.
Can you check to see if the ad loaded in your app?
Ad blockers work by preventing your app from downloading data. You could check the content length of the data in your ad frame to make sure there is data there.
If there is no data throw up a message and exit or warn you with an email.
It might not be as big an issue as you think since only a small percentage of people block ads.
The top two answers help you with only a particular (if, probably, the most popular) method of blocking ads. Root users can also block ads with a firewall on the device. WiFi users can block ads with an upstream firewall.
I suggest:
Don't reward ad-blocking users. Ensure that your layout reserves part of the display for an ad even if one can't be loaded. Or if you have a full-screen ad that plays for a bit, ensure that your app waits for a bit even if the ad can't be played. If you use notifications as adverts (you scum), notify the user when you fail to get such an advert. This could be read as "annoy all of your users", but your normal users know what they're getting, and your ad-blocking 'users' aren't wanted.
Ask ad-blockers to stop. The less proftable an industry that supplies what a user wants, the less that industry will supply what the user had wanted. An individual developer will find that he makes more money serving other users. You know this, and your users will think it obvious after you tell them, but it's still an economic argument - it's not intuitive. Have a backup ad that says something like, "This is my job. If you don't pay me, I'll get another one, and you won't get more apps like this from me."
There is nothing you can do that your users can't do better.
The only thing that comes to mind as remotely effective is to make the ads an inextricable part of the program, so that if they're blocked the user cannot make sense of/interact with the application.
Rather than checking for individual software installed or modified hosts file, my approach is using an AdListener like this and, if the ad fails to load due to NETWORK_ERROR, I just fetch some random always-online page (for the kicks, apple.com) and check if the pages loads successfully.
If so, boom goes the app.
To add some code, listener class would be something like:
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();
}
And then each activity with an adView would do something like:
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();
}
});
I think it depends on the content provider for the ads. I know the AdMob SDK provides a callback when an ad request fails. I suspect that you might be able to register for this, then check for a connection in the callback - if there is a connection and you did not receive an ad - take note, if it happens more than once or twice, chances are likely your ads are being blocked. I have not worked with the AdSense for Mobile toolset from Google but it wouldn't surprise me if there was a similar callback mechanism.
There are two ways for a user to by pass a advertisement:
1) Use app without internet on.
2) With rooted phone and modified host file.
I made two tools that you can implement, see code below.
checkifonline(); is for problem 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();
}
}
adblockcheck(); is for problem 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();
}
}
This is an extension of a previous answer. The user has informed me that the app they are using is called AdFree Android. It can be found on the market. The app says it works by "nullifying requests to known hostnames serving ads."
I suggest that if you monetize any of your apps with ads, you check at startup for this program and give the user a nasty message, then terminate your app.
First, let me say that I believe that Ad Blocking, when it comes to applications, is actually a form of piracy. These apps are supported by the ads, and sometimes, a "paid license" to turn off ads and/or add features. By blocking ads, users are stealing potential revenue from the developer that took the time to create the app that you are using.
Anyhow, I want to add a way to help prevent the use of Ad Blockers. I use this method and I do not allow users to use the app if I detect an ad blocker. People get very angry and will give you poor ratings for it. But I also state very clearly in my applications descriptions that you will not be able to use the app if you have an adblocker.
I use the package manager to check if a specific package is installed. While this will not get all of the adblockers, if you keep "up to date" on some of the popular ones, you can get most of them.
PackageManager pm = activity.getPackageManager ();
Intent intent = pm.getLaunchIntentForPackage ( "de.ub0r.android.adBlock" );
if ( Reflection.isPackageInstalled ( activity, intent ) ) {
// they have adblock installed
}
Give your users a way to use the app without the ads. I personally find ads one of the most annoying things that could possibly happen on my computer, and I will gladly pay for an application if it spares me the insult of having ads thrown into my face. And I'm sure I'm not the only one.
I'm sure this answer won't be entirely popular with certain segments of developers, however consider if you fall into this category that perhaps your app doesn't deserve to exist on the app store. Please note that these are all implementable as code changes, no hackery or spyware like behavior required.
Basically, change the economics of your app. The User is Always Right - this is the attitude taken by one of the most successful advertising companies ever (Google). If your ads are being blocked by users, its because you suck, not because ads or ad-blockers suck.
http://books.google.com/books/about/The_User_is_Always_Right.html?id=gLjPMUjVvs0C
Make ads less annoying and in-your-face. Users react to poor/annoying advertisement, and the seedier your app looks and becomes, the more likely they are to ditch it anyways. I don't mind apps with ads in them as long as they aren't significantly impeding the functionality, and even better I like ads which are relevant to me. (http://www.nngroup.com/articles/most-hated-advertising-techniques/)
To detect that ads aren't being loaded, its not necessary to implement the spyware like activities mentioned by previous posters. Load an ad that has a confirmation code, and every once in awhile, insert a prompt asking for the confirmation code. The code doesn't have to be long or annoying, in fact it'd be enough to implement a captcha service with 3 or 4 letters/numbers.
(http://textcaptcha.com/api)
In addition to detecting failure of ads to load, make better ads. Instead of using an API like mobads (Do you even realize how seedy that sounds? Mobs? Really? Are we developers, the Russian Mafia?), enter a partnership with an ad company that allows you to embed ads directly from your app. It will make your overall app larger to install, and no, you can't guard against manual modification, but the changes suggested above don't guard against that either. And this will better support any paid versions of your app, which will be much more lightweight (and faster).
Thoroughly vet the ads you are displaying to the user, be open and transparent about your ad policies, and even allow users to inspect your ads and ad sources. The primary reason I'm ever concerned about ads is not because I hate ads, but because I worry that the poor quality developer responsible for this app is letting in viruses or other malware as well. Ask that an exception be made to the installed adblocker. Team up with ad blockers like AdBlock to get on their exceptions list. If you are a legit application, this shouldn't be a problem.
(http://www.cio.com/article/699970/6_Ways_to_Defend_Against_Drive_by_Downloads?page=1&taxonomyId=3089)
I re-iterate: all of the above changes are things you can legitimately do in code to prevent anti-ad behaviors. Ads are blocked for security reasons and visceral reactions, primarily, and sometimes bandwidth and performance, so make sure your ads don't invoke any of these problems, at the code level.
Finally I did want to touch on what Borealid said, which I re-iterated above; in the end it is a 'cat and mouse' game, because the user has ultimate authority and responsibility, both legally and morally, over their own property. A user can do whatever, including directly modify code on the fly. Of course, there are restrictions you can implement etc. but there are always ways to get around the problem. This is the ultimate problem (technically) with DRM (which is what you're trying to do). Rather than waste time and effort on this game, it is better to encourage users to keep ads around; they'll become your best, smartest anti-ad-blockers, for free.
For the case when there is no internet connection, I have followed this
tutorial
and I've build a "network state listener" like so:
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 and unregisterReceiver have to be called in onResume and onPause respectively, as described here.
In your layout xml set up the AdView and an ImageView of your own choice, like so:
<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" />
Now, whenever the internet connection is available the ad will display and when its off the ImageView will pop-up, and vice-versa. This must be done in every activity in which you want ads to display.
As well as checking if admob can be resolved, what I do is present a page that basically advises that I have detected an adblocker, state that i understand the possible reasons why, then show some inbuilt ads of my own apps and ask for their kind support for continued development. :)

Categories

Resources