Is there a way to block ads in an Android WebView? I am building app that lets users browse web pages, but need to block ads. Its basically a custom browser, but I need to get rid of ads.
What is my best option?
Based on: https://github.com/adblockplus/adblockplusandroid
saw this:
https://gist.github.com/rjeschke/eb1bb76128c5e9a9e7bc
import java.io.File;
import java.util.regex.Pattern;
import org.adblockplus.android.ABPEngine;
import org.adblockplus.libadblockplus.FilterEngine.ContentType;
import android.content.Context;
import android.webkit.WebResourceResponse;
import android.webkit.WebView;
import android.webkit.WebViewClient;
public class BlockingWebViewClient extends WebViewClient
{
private ABPEngine engine;
private static final Pattern RE_JS = Pattern.compile("\\.js$", Pattern.CASE_INSENSITIVE);
private static final Pattern RE_CSS = Pattern.compile("\\.css$", Pattern.CASE_INSENSITIVE);
private static final Pattern RE_IMAGE = Pattern.compile("\\.(?:gif|png|jpe?g|bmp|ico)$", Pattern.CASE_INSENSITIVE);
private static final Pattern RE_FONT = Pattern.compile("\\.(?:ttf|woff)$", Pattern.CASE_INSENSITIVE);
private static final Pattern RE_HTML = Pattern.compile("\\.html?$", Pattern.CASE_INSENSITIVE);
public void start(Context context)
{
final File basePath = context.getFilesDir();
this.engine = ABPEngine.create(context, ABPEngine.generateAppInfo(context),
basePath.getAbsolutePath());
// Additional steps may be required here, i.e. :
// - subscription selection or updating
// - maybe also setting other options (like AcceptableAds)
// It might also be a good idea to delay the first calls until
// everything is loaded, have a look at AndroidFilterChangeCallback
// and ABPEngine.create()
}
#Override
public WebResourceResponse shouldInterceptRequest(WebView view, String url)
{
// Determine the content
ContentType contentType = null;
if (RE_JS.matcher(url).find())
{
contentType = ContentType.SCRIPT;
}
else if (RE_CSS.matcher(url).find())
{
contentType = ContentType.STYLESHEET;
}
else if (RE_IMAGE.matcher(url).find())
{
contentType = ContentType.IMAGE;
}
else if (RE_FONT.matcher(url).find())
{
contentType = ContentType.FONT;
}
else if (RE_HTML.matcher(url).find())
{
contentType = ContentType.SUBDOCUMENT;
}
else
{
contentType = ContentType.OTHER;
}
// Check if we should block ... we sadly do not have the referrer chain here,
// might also be hard to get as we do not have HTTP headers here
if (engine.matches(url, contentType, new String[0]))
{
// If we should block, return empty response which results in a 404
return new WebResourceResponse("text/plain", "UTF-8", null);
}
// Otherwise, continue by returning null
return null;
}
}
It is done already:
https://github.com/adblockplus/libadblockplus-android
You can put it at xml:
<org.adblockplus.libadblockplus.android.webview.AdblockWebView
android:id="#+id/main_webview"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
Related
I am trying to make a dictionary application using Oxford Dictionary api. There is something wrong with my code JSON. Can anyone tell me how do I extract only the definition of the searched word, rather getting the whole JSON file
import android.os.AsyncTask;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
import com.squareup.okhttp.Callback;
import com.squareup.okhttp.OkHttpClient;
import com.squareup.okhttp.Request;
import com.squareup.okhttp.Response;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;
import javax.net.ssl.HttpsURLConnection;
public class MainActivity extends AppCompatActivity {
private static final String APP_ID= "59028fc6";
private static final String API_KEY = "ad3e310307d7b2f8bf474c45e1efd01f";
private static final String TAG = MainActivity.class.getSimpleName();
private OkHttpClient okHttpClient;
private EditText textInput;
private Button submitButton;
private TextView definitionView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// initialize ok http
okHttpClient = new OkHttpClient();
textInput = findViewById(R.id.textInput);
submitButton = findViewById(R.id.submitButton);
definitionView = findViewById(R.id.textMeaning);
submitButton.setOnClickListener(
new View.OnClickListener() {
#Override
public void onClick(View view) {
findMeaningOfEnteredWord();
}
});
}
private void findMeaningOfEnteredWord() {
String word = textInput.getText().toString();
if (word.isEmpty()) {
Toast.makeText(this, "Nothing entered", Toast.LENGTH_SHORT).show();
return;
}
// create url from the word
String lowerCaseWord = word.toLowerCase();
String httpRequestUrl = "https://od-api.oxforddictionaries.com:443/api/v1/entries/en/" + lowerCaseWord;
// make request with REST url
new RequestAsyncTask().execute(httpRequestUrl);
}
private class RequestAsyncTask extends AsyncTask<String, Integer, String> {
#Override
protected String doInBackground(String... params) {
String requestUrl = params[0];
Request request = new Request.Builder()
.url(requestUrl)
.addHeader("Accept", "application/json")
.addHeader("app_id", APP_ID)
.addHeader("app_key", API_KEY)
.build();
Response response = null;
try {
response = okHttpClient.newCall(request).execute();
return response.body().string();
} catch (IOException ex) {
Log.e(TAG, "caught error: " + ex.getMessage());
}
return "";
}
#Override
protected void onPostExecute(String result) {
try {
JSONObject responseAsJson = new JSONObject(result);
JSONArray results = responseAsJson.getJSONArray("results");
if (results.length() > 0) { // valid definitions were found
String lexicalEntries = results.getJSONObject(0).getString("lexicalEntries");
definitionView.setText(lexicalEntries);
}
Log.d(TAG, " " + responseAsJson.toString());
} catch (Exception ex) {
Log.d(TAG, "exception during json parsing: " + ex.getMessage());
}
}
}
}
JSON:
{"id":"aeroplane",
"language":"en",
"lexicalEntries": [
{
"entries": [{"etymologies":["late 19th century: from French aéroplane, from aéro- ‘air’ + Greek -planos ‘wandering’"],
"grammaticalFeatures":[{"text":"Singular","type":"Number"}],
"homographNumber":"000",
"senses":[{"crossReferenceMarkers":["North American term airplane"],
"crossReferences":[{"id":"airplane","text":"airplane","type":"see also"}],
"definitions":["a powered flying vehicle with fixed wings and a weight greater than that of the air it displaces."],
"domains":["Aviation"],
"id":"m_en_gbus0013220.005",
"regions":["British"],
"short_definitions":["powered flying vehicle with fixed wings"],
"thesaurusLinks":[{"entry_id":"plane","sense_id":"t_en_gb0011151.001"}]}]}],"language":"en","lexicalCategory":"Noun","pronunciations":[{"audioFile":"http:\/\/audio.oxforddictionaries.com\/en\/mp3\/aeroplane_gb_2.mp3","dialects":["British English"],"phoneticNotation":"IPA","phoneticSpelling":"ˈɛːrəpleɪn"}],"text":"aeroplane"}],
"type":"headword","word":"aeroplane"
}
Modify these lines :
String lexicalEntries = results.getJSONObject(0).getString("lexicalEntries");
definitionView.setText(lexicalEntries);
to :
String definition = results.getJSONObject(0).getString("lexicalEntries")
.getJSONArray("entries").getJSONObject(0).getJSONArray("senses")
.getJSONObject(0).getJSONArray("definitions").getString(0);
definitionView.setText(definition);
Of course you may need to modify your UI based on the number of definitions a word has.
Also, you should probably consider using POJOs instead of directly dealing with the JSON response.
I'd recommend Jackson or GSON for doing this.
String definitions=results.getJSONArray("lexicalEntries")
.getJSONObject(0)
.getJSONArray("entries")
.getJSONObject(0)
.getJSONArray("senses")
.getJSONArray("definitions")
.get(0)
So , The thing is , There are a lot of gaps in the JSON for different words .
Which means a word may have an array of "synonyms" but others don't , So in your code you are trying to reach something that doesn't actually exist (a NULL value) which is likely to throw an exception every time you search for a word that the JSON returned doesn't match the JSON you are expecting , Because there are missing (NULL) values .
The app I made using oxford dictionary required a lot of work just to make sure there is no thrown exception .
I used retrofit with moshi converter factory , And then Do the following :
1-In your custom classes , Make sure you annotate every data member with
#Json and provide the name of the keys in the JSON of oxford
2-make sure that every declared type is nullable , including both List and the type inside of it
You'll then be able to get the result , And Now comes the part where you handle evey call that may be null
I know this is a bit old question , But It happened that I struggled with this api once , So I hope this may help someone :)
I am trying to verify a JWT that I am receiving from Google using GoogleAuthUtil. I am trying to use the code at the bottom of this page. Here is my exact source code:
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.util.Arrays;
import java.util.List;
import com.google.api.client.googleapis.auth.oauth2.GoogleIdToken;
import com.google.api.client.googleapis.auth.oauth2.GoogleIdTokenVerifier;
import com.google.api.client.http.javanet.NetHttpTransport;
import com.google.api.client.json.JsonFactory;
public class Checker {
private final List mClientIDs;
private final String mAudience;
private final GoogleIdTokenVerifier mVerifier;
private final JsonFactory mJFactory;
private String mProblem = "Verification failed. (Time-out?)";
public Checker(String[] clientIDs, String audience) {
mClientIDs = Arrays.asList(clientIDs);
mAudience = audience;
NetHttpTransport transport = new NetHttpTransport();
mJFactory = new JsonFactory();
mVerifier = new GoogleIdTokenVerifier(transport, mJFactory);
}
public GoogleIdToken.Payload check(String tokenString) {
GoogleIdToken.Payload payload = null;
try {
GoogleIdToken token = GoogleIdToken.parse(mJFactory, tokenString);
if (mVerifier.verify(token)) {
GoogleIdToken.Payload tempPayload = token.getPayload();
if (!tempPayload.getAudience().equals(mAudience))
mProblem = "Audience mismatch";
else if (!mClientIDs.contains(tempPayload.getIssuee()))
mProblem = "Client ID mismatch";
else
payload = tempPayload;
}
} catch (GeneralSecurityException e) {
mProblem = "Security issue: " + e.getLocalizedMessage();
} catch (IOException e) {
mProblem = "Network problem: " + e.getLocalizedMessage();
}
return payload;
}
public String problem() {
return mProblem;
}
}
The issue that I'm having is in this line: mJFactory = new JsonFactory();, where I am getting the error Cannot instantiate the type JsonFactory. I'm pretty sure I'm calling the constructor properly and I have all of the libraries imported properly so I don't know why I'm getting this error. If anyone can help me out, that would be great! Let me know if theres any additional info that would be helpful.
EDIT:
Here's the link to the Javadoc
Okay the issue was that I made a small mistake copying the code. JsonFactory is an abstract class, so you need to use the subclass GsonFactory to provide an implementation.
For Android CookieManager class there is a method -- getCookie(String url).
For this we need to know correct url.
Is there a way to get all cookies in CookieManager and get the urls .
some thing like getCookies ??
This is just to double check if i am giving anything wrong in my url for getCookie(String url) call.
I am not getting the cookie when i call the same.
I am passing complete IP address here in url. Something like this : "xx.x.x.x"
Thanks
Mia
I used the CookieManager with the java.net package in my Android Application and it works like a charm. Here is a code snippet :
import java.net.CookieHandler;
import java.net.CookieManager;
import java.net.CookiePolicy;
import java.net.HttpCookie;
import java.util.List;
private class MyCookieManager
{
private CookieManager mCookieManager = null;
MyCookieManager() {
mCookieManager = new CookieManager();
mCookieManager.setCookiePolicy(CookiePolicy.ACCEPT_ALL);
CookieHandler.setDefault(mCookieManager);
}
private List<HttpCookie> getCookies() {
if(mCookieManager == null)
return null;
else
return mCookieManager.getCookieStore().getCookies();
}
public void clearCookies() {
if(mCookieManager != null)
mCookieManager.getCookieStore().removeAll();
}
public boolean isCookieManagerEmpty() {
if(mCookieManager == null)
return true;
else
return mCookieManager.getCookieStore().getCookies().isEmpty();
}
public String getCookieValue() {
String cookieValue = new String();
if(!isCookieManagerEmpty()) {
for (HttpCookie eachCookie : getCookies())
cookieValue = cookieValue + String.format("%s=%s; ", eachCookie.getName(), eachCookie.getValue());
}
return cookieValue;
}
}
You can use reflection to see the cookie map. It's called mCookieMap in 4.0.3 (and probably in earlier releases as well). The type is Map>.
This isn't a great way of doing it because you'll risk breaking on different devices or OS versions if they don't use mCookieMap, but CookieManager doesn't offer a public way of knowing which URLs it's visited.
I have a Phonegap/Jquery mobile app that i am trying to wrap for Android, but the target SDK I am using is not allowing Ajax/Cross-domain requests.
In short, the requests work fine with Android 4.0.3 (API 15), the most current, but not for Android 2.3.3 ( API 10), which is what i need to be compatible for a Galaxy Tablet.
I am having a hard time debugging this as I can't see the actual error since I am wrapped in phonegap and cant user Firebug/Chrome web tools. and I haven't had any luck over at developer.android.com.
I have tried the steps located at http://jquerymobile.com/test/docs/pages/phonegap.html, including
$.mobile.allowCrossDomainPages = true;
$.support.cors = true.
This didn't work either.
Can anyone help me out, I don't know what else to try.
Thanks!
Here is the a quick example of code. note that it returns success = true but hits the 'Response is not an XML element' error:
return $.soapRequest({
url: url,
namespace: 'testns',
returnJson: false,
shortMethod: 'methodname',
method: 'longmethodname',
params: params || {},
success: function(data) {
if (data && data.documentElement) {
// hits this on Android SDK 15
if (successFn) {
return successFn(data.documentElement);
}
}
else {
// hits this on Android SDK 10
return fail("Response is not an XML element!");
}
},
error: function(str) {
return fail(str);
}
try to write httpConnection with phonegap pluggin. it cound CrossDomain
httpPlugin.java
package com.android.test;
import org.apache.cordova.api.Plugin;
import org.apache.cordova.api.PluginResult;
import org.apache.cordova.api.PluginResult.Status;
import org.json.JSONArray;
import org.json.JSONException;
import android.util.Log;
import com.android.connection.HTTPConnect;
public class HttpPlugin extends Plugin {
public final String ACTION_SEND_MESSAGE = "SendCommand";
private HTTPConnect httpConnect;
public HttpPlugin() {
// TODO Auto-generated constructor stub
httpConnect = new HTTPConnect();
}
#Override
public PluginResult execute(String action, JSONArray arg1, String callbackId) {
PluginResult result = new PluginResult(Status.INVALID_ACTION);
if (action.equals(ACTION_SEND_MESSAGE)) {
try {
String message = arg1.getString(0);
String receiveString = httpConnect.setURL(message);
if(receiveString == null){
//show error result
result = new PluginResult(Status.ERROR,"kakaka");
}else{
Log.v("MAN", "data received");
result = new PluginResult(Status.OK);
}
result = new PluginResult(Status.OK);
} catch (JSONException ex) {
// TODO Auto-generated catch block
result = new PluginResult(Status.JSON_EXCEPTION, ex.getMessage());
}
}
return result;
}
}
plugin.xml file
Httpplugin .js
var Httpplugin = function () {};
Httpplugin.prototype.post = function (message, successCallback, failureCallback) {
// navigator.notification.alert("OMG");
return cordova.exec(successCallback, failureCallback, 'Httpplugin', 'SendCommand', [message]);
};
PhoneGap.addConstructor(function() {
PhoneGap.addPlugin("http", new Httpplugin());
});
Where can I find a simple, working and easy code example for testing on Android with the ProviderTestCase2?
Best would be an OpenSource project actually using it - on the other hand, in the complexity of a real project it can become hard to realize the actual functionality, so any good example is welcome. The Google Android docs are not very specific and contain no proper example.
In this example I'm testing a ContentProvider named 'DataLayer' which exists in the app being tested; below, I've begun testing the ContentProvider interface to a table called 'ActiveUser'.
If anyone knows how to use newResolverWithContentProviderFromSql
please enlighten me!
package com.example.android.app.test;
import android.content.ContentUris;
import android.content.ContentValues;
import android.database.Cursor;
import android.net.Uri;
import android.provider.BaseColumns;
import android.test.ProviderTestCase2;
import android.test.mock.MockContentResolver;
import android.util.Log;
import com.example.android.app.Constants;
import com.example.android.app.DataLayer;
import com.example.android.app.provider.contract.ActiveUserContract;
public class DataLayerTests extends ProviderTestCase2<DataLayer> {
private static final String TAG = DataLayerTests.class.getSimpleName();
MockContentResolver mMockResolver;
public DataLayerTests() {
super(DataLayer.class, Constants.DATA_LAYER_AUTHORITY);
}
#Override
protected void setUp() throws Exception {
super.setUp();
Log.d(TAG, "setUp: ");
mMockResolver = getMockContentResolver();
}
#Override
protected void tearDown() throws Exception {
super.tearDown();
Log.d(TAG, "tearDown:");
}
public void testActiveUserInsert__inserts_a_valid_record() {
Uri uri = mMockResolver.insert(ActiveUserContract.CONTENT_URI, getFullActiveUserContentValues());
assertEquals(1L, ContentUris.parseId(uri));
}
public void testActiveUserInsert__cursor_contains_valid_data() {
mMockResolver.insert(ActiveUserContract.CONTENT_URI, getFullActiveUserContentValues());
Cursor cursor = mMockResolver.query(ActiveUserContract.CONTENT_URI, null, null, new String[] {}, null);
assertNotNull(cursor);
assertEquals(1, cursor.getCount());
assertTrue(cursor.moveToFirst());
assertEquals(VALID_USERNAME, cursor.getString(cursor.getColumnIndex(ActiveUserContract.Columns.USERNAME)));
assertEquals(VALID_COMPANY_CODE, cursor.getString(cursor.getColumnIndex(ActiveUserContract.Columns.COMPANY_CODE)));
assertEquals(VALID_COMPANY_LETTER, cursor.getString(cursor.getColumnIndex(ActiveUserContract.Columns.COMPANY_LETTER)));
assertEquals(VALID_DRIVER_CODE, cursor.getString(cursor.getColumnIndex(ActiveUserContract.Columns.DRIVER_CODE)));
assertEquals(VALID_SITE_NUMBER, cursor.getString(cursor.getColumnIndex(ActiveUserContract.Columns.SITE_NUMBER)));
assertEquals(VALID_FIRST_NAME, cursor.getString(cursor.getColumnIndex(ActiveUserContract.Columns.FIRST_NAME)));
assertEquals(VALID_SURNAME, cursor.getString(cursor.getColumnIndex(ActiveUserContract.Columns.SURNAME)));
}
public void testActiveUserInsert__throws_SQLiteConstraintException_when_NOT_NULL_constraint_not_met() {
try {
mMockResolver.insert(ActiveUserContract.CONTENT_URI, getActiveUserContentValuesWithNullCompanyCode());
fail("SQLiteConstraintException should have been thrown!");
} catch (SQLiteConstraintException e) {
assertEquals("active_user.comp_code may not be NULL (code 19)", e.getMessage());
}
}
/** #return a ContentValues object with a value set for each ActiveUser column */
public static ContentValues getFullActiveUserContentValues() {
ContentValues v = new ContentValues(7);
v.put(ActiveUserContract.Columns.USERNAME, VALID_USERNAME);
v.put(ActiveUserContract.Columns.COMPANY_CODE, VALID_COMPANY_CODE);
v.put(ActiveUserContract.Columns.COMPANY_LETTER, VALID_COMPANY_LETTER);
v.put(ActiveUserContract.Columns.DRIVER_CODE, VALID_DRIVER_CODE);
v.put(ActiveUserContract.Columns.SITE_NUMBER, VALID_SITE_NUMBER);
v.put(ActiveUserContract.Columns.FIRST_NAME, VALID_FIRST_NAME);
v.put(ActiveUserContract.Columns.SURNAME, VALID_SURNAME);
return v;
}
public static ContentValues getActiveUserContentValuesWithNullCompanyCode() {
ContentValues v = new ContentValues(7);
v.put(ActiveUserContract.Columns.USERNAME, VALID_USERNAME);
v.putNull(ActiveUserContract.Columns.COMPANY_CODE);
v.put(ActiveUserContract.Columns.COMPANY_LETTER, VALID_COMPANY_LETTER);
v.put(ActiveUserContract.Columns.DRIVER_CODE, VALID_DRIVER_CODE);
v.put(ActiveUserContract.Columns.SITE_NUMBER, VALID_SITE_NUMBER);
v.put(ActiveUserContract.Columns.FIRST_NAME, VALID_FIRST_NAME);
v.put(ActiveUserContract.Columns.SURNAME, VALID_SURNAME);
return v;
}
private static final String VALID_SURNAME = "Brin";
private static final String VALID_FIRST_NAME = "Sergey";
private static final String VALID_SITE_NUMBER = "9";
private static final String VALID_DRIVER_CODE = "SergB201";
private static final String VALID_COMPANY_LETTER = "G";
private static final String VALID_COMPANY_CODE = "GOOGLE!";
private static final String VALID_USERNAME = "123456";
}
Android uses it internally to test its providers. For examples see here and here.
Google Code Search is great for this stuff :)
There is a pretty good example in the Android SDK Notepad sample project. Specifically NotePadProviderTest. Just make sure you have the samples installed via the SDK mamanger and you're good to go.