SpinachMedia

情報ポータル SpinachMedia です。

鴻鵠の志をまるで知らない。SpinachMedia
Develop
Network
Design

Android の WebView 、画像を取得する代わりにローカル画像を表示


個人的な解釈が含まれております。
SpinachMediaは本ページの情報をあなたが利用することによって生ずるいかなる損害に対しても一切の責任を負いません。


MVNOのmineoを使ってみたのですが、月々1GBの通信に抑えるのは厳しいので

余計な画像や広告を取得しないようなブラウザはないものか、とちょっと作ってみました。

仕様

①png、jpeg、gifのhttpリクエストを遮断

②代わりにローカルのダミー画像を表示する。

③ダミー画像をタップすることで本来表示されるべきだった画像を取得する。

 

実装

調べてみたらAndroidのWebViewクラスに、以下のメソッドがありました。
shouldInterceptRequest(WebView view,String url) ;

 HTTPリクエストを行う直前に処理を挟めるみたいです。

これをオーバーライドして以下のように処理を変更。

 拡張子をみてリクエストを遮断、代わりにローカル画像を表示

 


    @Override
	public WebResourceResponse shouldInterceptRequest(WebView view,String url) {
		if (url.endsWith(".jpg") || url.endsWith(".png")|| url.endsWith(".gif")) {
		    // URLの頭に「a」が付いている場合は、正しい画像を取得する。
			if (url.substring(0, 1).equals("a")) {
				url = url.replaceAll("^a", "");
				Log.d("this", url);
				URL urlData;
				InputStream in = null;
				try {
					urlData = new URL(url);
					in = urlData.openStream();
				} catch (MalformedURLException e) {
				} catch (IOException e) {
				}
				WebResourceResponse webResourceResponse = new WebResourceResponse("image/jpeg", null, in);
				return webResourceResponse;
			}

			// ローカルの画像を返す。
			InputStream inputStream = res.openRawResource(R.drawable.noimage);
			WebResourceResponse webResourceResponse = new WebResourceResponse("image/jpeg", null, inputStream);
			return webResourceResponse;
		} else {
			return super.shouldInterceptRequest(view, url);
		}
	}    

 ブックマークレットを実行する処理を追加

 imgタグにクリックイベントを追加します。

myWebView.loadUrl("javascript:" +
		"var a=document.querySelectorAll('img');" + 
		"   for(i=0;i < a.length;i++){" + 
		"    a[i].addEventListener('click', " + 
		"      function(event) {" + 
		"       this.src = 'a' + this.src;" + 
		"      },false);" + 
		"   }"
	);    

 

こんな感じになりました。

 


SpinachMedia WebViewに対してブックマークレットを実行 - YouTube

 

 

以下、ソース。

 

package com.example.jp.spinach.packet.save.browser;

import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;

import android.app.Activity;
import android.content.res.Resources;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.webkit.JsResult;
import android.webkit.WebChromeClient;
import android.webkit.WebResourceResponse;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.Toast;

public class MainActivity extends Activity {

	WebView myWebView;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);

		final Resources res = getResources();

		// レイアウトで指定したWebViewのIDを指定する。
		myWebView = (WebView) findViewById(R.id.webView1);

		// リンクをタップしたときに標準ブラウザを起動させない
		myWebView.setWebViewClient(new WebViewClient() {
			@Override
			public WebResourceResponse shouldInterceptRequest(WebView view,
					String url) {
				if (url.endsWith(".jpg") || url.endsWith(".png")
						|| url.endsWith(".gif")) {

					// URLの頭に「a」が付いている場合は、正しい画像を取得する。
					if (url.substring(0, 1).equals("a")) {
						url = url.replaceAll("^a", "");
						Log.d("this", url);
						URL urlData;
						InputStream in = null;
						try {
							urlData = new URL(url);
							in = urlData.openStream();
						} catch (MalformedURLException e) {
						} catch (IOException e) {
						}

						WebResourceResponse webResourceResponse = new WebResourceResponse(
								"image/jpeg", null, in);
						return webResourceResponse;
					}

					// ローカルの画像を返す。
					InputStream inputStream = res
							.openRawResource(R.drawable.noimage);
					WebResourceResponse webResourceResponse = new WebResourceResponse(
							"image/jpeg", null, inputStream);
					return webResourceResponse;
				} else {
					return super.shouldInterceptRequest(view, url);
				}
			}
		});

		WebSettings settings = myWebView.getSettings();
		settings.setJavaScriptEnabled(true);

		myWebView.setWebChromeClient(new WebChromeClient() {
			public boolean onJsAlert(final WebView view, final String url,
					final String message, JsResult result) {
				Toast.makeText(MainActivity.this, message, 3000).show();
				result.confirm();
				return true;
			}
		});

		// 最初にYahoo! Japanのページを表示する。
		myWebView.loadUrl("http://www.spinachmedia.info/entry/2014/09/14/230449");

	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		getMenuInflater().inflate(R.menu.main, menu);
		return true;
	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		int id = item.getItemId();
		if (id == R.id.action_settings) {
			Log.d("test", "javascript");
			myWebView.loadUrl("javascript:" +
					"var a=document.querySelectorAll('img');" + 
					"   for(i=0;i < a.length;i++){" + 
					"    a[i].addEventListener('click', " + 
					"      function(event) {" + 
					"       this.src = 'a' + this.src;" + 
					"      },false);" + 
					"   }"
					);
			return true;
		}
		return super.onOptionsItemSelected(item);
	}
}