├── README.md ├── app.apk ├── main ├── AndroidManifest.xml ├── assets │ ├── about.htm │ └── logo.png ├── java │ └── com │ │ └── hty │ │ └── browser │ │ ├── DBHelper.java │ │ ├── FavoriteActivity.java │ │ ├── MainActivity.java │ │ └── SettingsActivity.java └── res │ ├── drawable-hdpi │ ├── exitfullscreen.jpg │ ├── ic_launcher.png │ ├── network.png │ └── play.png │ ├── drawable-mdpi │ ├── folder_download.png │ └── ic_launcher.png │ ├── drawable-xhdpi │ └── ic_launcher.png │ ├── drawable-xxhdpi │ ├── arrow.png │ ├── ic_launcher.png │ └── link.png │ ├── drawable │ ├── border.xml │ └── progressbar_color.xml │ ├── layout │ ├── activity_favorite.xml │ ├── activity_main.xml │ ├── dialog_download.xml │ └── favorite_row.xml │ ├── values │ └── strings.xml │ └── xml │ └── preference.xml ├── preview.png └── version /README.md: -------------------------------------------------------------------------------- 1 | # Android:海天鹰浏览器 2 | 基于 Android WebView 的多窗口浏览器,支持收藏夹、图片广告过滤、视频独立播放。 3 | ### 主界面 4 | ![alt](preview.png) -------------------------------------------------------------------------------- /app.apk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sonichy/HTYBrowser_Android/df3f62afed2f9826268eb0dc52736099c428568a/app.apk -------------------------------------------------------------------------------- /main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 11 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 40 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /main/assets/about.htm: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 海天鹰浏览器 6 | 10 | 11 | 12 |


海天鹰浏览器 V4.18

13 |

内置扩展的浏览器。

14 |

扩展:链接关键字过滤,链接关键字高亮,图片自定义过滤,视频独立播放。

15 |

作者:海天鹰

16 |

源码:https://github.com/sonichy/Android_HTYBrowser

17 |

E-mail:sonichy@163.com

18 |

参考:

19 |

多窗口管理

20 |

链接的 target=_blank 在新窗口中打开

21 |

Android WebView 三种文件下载方式

22 |

自动安装apk包

23 |

获取网页图标

24 |

字符串转Bitmap

25 |

更新日志:

26 |

V4.19 (2021-06-27)

  1. 增加请求电脑版网页。
27 |

V4.18 (2021-06-01)

  1. 增加动态权限请求。
28 |

V4.17 (2021-03-02)

  1. 允许HTTPS、HTTP混合内容,解决微信网页视频无法播放的问题。
29 |

V4.16 (2020-10-14)

  1. 取消引起崩溃的复制图片。
30 |

V4.15 (2020-10-01)

  1. 优化猜测下载文件名。
31 |

V4.14 (2020-09-20)

  1. 优化下载对话框百度网页图片文件名填充,支持修改下载文件名。
32 |

V4.13 (2020-08-30)

  1. 图片查看改为在新窗口中打开。
  2. 修复修改、删除收藏不能记忆位置问题。
33 |

V4.12 (2020-07-17)

  1. 适配全面屏导航栏背景色。
  2. 收藏夹无标题栏自定义菜单改成标题栏菜单。
34 |

V4.11 (2020-03-03)

  1. 收藏夹增加数目统计。
  2. 收藏夹增加菜单,导出HTML、CSV。
35 |

V4.10 (2019-12-17)

  1. 优化视频独立播放。
36 |

V4.9 (2019-11-06)

  1. 收藏夹网址增加分享功能。
37 |

V4.8 (2019-10-25)

  1. 协议过滤:去除淘宝跳转,增加ftp。
  2. 修复:退出前未反注册广播。
38 |

V4.7 (2019-08-14)

  1. 增加:清除缓存菜单。
  2. target="_blank"是用户触发才在新窗口中打开。
39 |

V4.6 (2019-07-16)

  1. 修复:移动数据连接不能下载。
40 |

V4.5 (2019-06-19)

  1. 增加:视频截图。
  2. 简化:视频独立播放。
41 |

V4.4 (2019-05-02)

  1. 增加扩展和设置开关:图片宽度超过父容器宽度,图片缩小到父容器宽度。
42 |

V4.3 (2019-04-11)

  1. 收藏夹删除收藏时记住位置。
43 |

V4.2 (2019-03-29)

  1. 下载弹出确认窗口,避免自动下载。
44 |

V4.1 (2019-03-05)

  1. 链接的 target=_blank 在新窗口中打开。
  2. 淘宝协议自动跳转淘宝APP。
45 |

V4.0 (2019-03-02)

  1. 实现多窗口。
46 |

V3.12 (2019-02-27)

  1. 支持跨域。
  2. 获取网页图标。
  3. 屏蔽百度首页视频百度好看跳转下载。
  4. Android API 19 以上开启调试,运行 adb devices 连接手机,Chrome 浏览器 chrome://inspect 查看。
  5. 增加标题按钮,点击标题按钮显示地址栏,点击网页隐藏地址栏。
47 |

V3.11 (2019-02-13)

  1. 链接中的关键字屏蔽、高亮可设置。
48 |

V3.10 (2019-02-10)

  1. 增加:收藏前修改,收藏后修改,修改校验。
49 |

V3.9 (2018-12-20)

  1. 视频独立播放JS读不到iframe里的video,使用跳转iframe代替。
50 |

V3.8 (2018-07-14)

  1. 增加定位权限。
51 |

V3.7 (2018-06-13)

  1. 增加自动更新。
52 |

V3.6 (2018-05-30)

  1. 修复从收藏夹返回输入法不能自动隐藏的问题。
53 |

V3.5 (2018-04-25)

  1. 收藏夹支持搜索。
54 |

V3.4 (2018-03-13)

  1. 增加视频独立播放。
  2. 使用系统下载取代浏览器跳转下载、图片下载,并增加链接下载
55 |

V3.3 (2018-01)

  1. 增加分享菜单。
  2. 增加:视频全屏禁用屏幕休眠。
  3. 解决网页跳转APP协议问题。
56 |

V3.2 (2017-12-17)

  1. 修复:关闭查找框,高亮不消失的问题。
  2. 增加过滤iframe。
  3. 修复:EditTextPreference没有设置defaultValue,引起第一次运行点击主页菜单崩溃。
57 |

V3.1 (2017-09-16)

  1. 修复:增加设置主页后,从打开方式打开仍然打开主页而不是打开文件的问题。
  2. 增加全屏菜单。
58 |

V3.0 (2017-08-31)

  1. 增加广告图片自定义过滤。
59 |

V2.15 (2017-08-27)

  1. 增加设置页面,增加主页设置。
60 |

V2.14 (2017-03-05)

  1. 按钮设置空背景去除边框,使按钮更小,从而使导航栏高度更小,下面的网页更大;更换主菜单图标。
61 |

V2.13 (2016-10-07)

  1. 下载图片后自动添加到图库中。
62 |

V2.12 (2016-08-17)

  1. 优化移动端关于页面。
63 |

V2.11 (2016-05-08)

  1. 增加显示网页源码。
  2. 增加查找功能。
  3. 自定义搜索栏,代替搜索对话框,支持搜索上一个、下一个。
  4. 适配无虚拟键盘的 Android X86。
  5. 网址收藏数据库存储到扩展存储上,以免重装应用时数据库被删除。
64 |

V2.10 (2016-04-28)

  1. 设置前进、后退按钮可用、禁用逻辑。
  2. 点击返回键无历史网页可退时,无动作而不是退到后台。
65 |

V2.9 (2016-04-13)

  1. 浏览器添加到HTML文件打开方式选择列表。
66 |

V2.8 (2016-03-11)

  1. 文字按钮改为图片按钮。
  2. 适配平板,取消沉浸模式,增加前进、后退、菜单按钮,点击菜单按钮弹出菜单,适配无物理按键。
  3. 修复图片无扩展名无法保存的问题。
67 |

V2.7 (2016-02-25)

  1. 网址收藏排除[about:blank]。
  2. 取消恢复前台自动播放视频,因为会引起解锁时新浪微博视频自动播放。
  3. 全屏暂停时显示播放按钮。
68 |

V2.6 (2016-02-21)

  1. 浏览器退到后台暂停视频播放。
69 |

V2.5 (2016-02-14)

  1. 增加onConsoleMessage。
  2. 测试视频全屏,MIUI显示控件,LEUI不显示控件,是手机系统问题,因为回退键已做好退出退出全屏功能,取消显示退出全屏按钮。
70 |

V2.4 (2016-02-12)

  1. 视频全屏适用iqiyi.com。
  2. 点击返回键优先退出全屏,返回上一页次之,最后moveTaskToback。
71 |

V2.3 (2016-02-09)

  1. 修复网络未连接,反复请求百度搜索的问题。
72 |

V2.2 (2016-02-03)

  1. 触摸WebView隐藏地址栏输入法。
  2. 自定义进度条。
73 |

V2.1 (2016-02-01)

  1. 增加保存图片功能。
74 |

V2.0 (2016-01-31)

  1. 改用SQLite数据库收藏网址。
  2. 完善收藏夹的显示、添加、删除、点击跳转菜单。
75 |

V1.5 (2016-01-28)

  1. 增加使用localStorage技术的收藏夹。
76 |

V1.4 (2016-01-26)

  1. 修复中文网址打不开时,跳转百度搜索乱码。
  2. 增加图片长按菜单。
77 |

V1.3 (2016-01-25)

  1. 菜单键增加前进菜单项。
  2. 增加输入法回车打开网址。
  3. 改用Holo主题。
  4. 增加网址补齐[http://]。
  5. 找不到网站时到百度网搜索。
  6. 增加进度条。
78 |

V1.2 (2016-01-23)

  1. 支持自适应屏幕,支持缩放。
79 |

V1.1 (2016-01-22)

  1. 增加支持网页input.file转安卓文件选择器。
  2. 点击加载按钮隐藏输入法。
  3. 增加支持使用内部浏览器下载文件。
80 |

V1.0 (2016-01-21)

  1. 实现基本的浏览器界面。
  2. 实现第一个扩展[链接转图片]。
  3. 网页JS.alert转安卓Toast。
81 | 82 | -------------------------------------------------------------------------------- /main/assets/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sonichy/HTYBrowser_Android/df3f62afed2f9826268eb0dc52736099c428568a/main/assets/logo.png -------------------------------------------------------------------------------- /main/java/com/hty/browser/DBHelper.java: -------------------------------------------------------------------------------- 1 | package com.hty.browser; 2 | 3 | import java.io.File; 4 | 5 | import android.content.ContentValues; 6 | import android.content.Context; 7 | import android.database.Cursor; 8 | import android.database.sqlite.SQLiteDatabase; 9 | import android.database.sqlite.SQLiteOpenHelper; 10 | 11 | public class DBHelper extends SQLiteOpenHelper { 12 | 13 | public static final String DATABASE_NAME = MainActivity.dir + File.separator + "webfav.db"; 14 | private final static int VERSION = 1; 15 | static String TableName = "webfav"; 16 | private SQLiteDatabase db; 17 | private static DBHelper mInstance = null; 18 | 19 | public DBHelper(Context context) { 20 | super(context, DATABASE_NAME, null, VERSION); 21 | } 22 | 23 | public static synchronized DBHelper getInstance(Context context) { 24 | if (mInstance == null) { 25 | mInstance = new DBHelper(context); 26 | } 27 | return mInstance; 28 | } 29 | 30 | @Override 31 | public void onCreate(SQLiteDatabase db) { 32 | this.db = db; 33 | db.execSQL("CREATE TABLE webfav (_id INTEGER PRIMARY KEY , website TEXT, title TEXT)"); 34 | } 35 | 36 | @Override 37 | public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { 38 | // db.execSQL("DROP TABLE IF EXISTS battery"); 39 | // onCreate(db); 40 | switch (newVersion) { 41 | case 6: 42 | break; 43 | } 44 | } 45 | 46 | public void insert(ContentValues values) { 47 | db = getWritableDatabase(); 48 | db.insert(TableName, null, values); 49 | db.close(); 50 | } 51 | 52 | public Cursor query(String s) { 53 | db = getWritableDatabase(); 54 | Cursor c = null; 55 | if (s.equals("")) { 56 | c = db.query(TableName, null, null, null, null, null, "_id desc"); 57 | } else { 58 | c = db.query(TableName, null, "website LIKE '%" + s + "%' or title LIKE '%" + s + "%'", null, null, null, "_id desc"); 59 | } 60 | return c; 61 | } 62 | 63 | public void del(int id) { 64 | if (db == null) 65 | db = getWritableDatabase(); 66 | db.delete(TableName, "_id=?", new String[] { String.valueOf(id) }); 67 | // Log.e("id", id + ""); 68 | // db.ExecuteNonQuery(CommandType.Text, "VACUUM"); 69 | } 70 | 71 | @Override 72 | public void close() { 73 | if (db != null) 74 | db.close(); 75 | } 76 | } -------------------------------------------------------------------------------- /main/java/com/hty/browser/FavoriteActivity.java: -------------------------------------------------------------------------------- 1 | package com.hty.browser; 2 | 3 | import android.app.Activity; 4 | import android.app.AlertDialog; 5 | import android.content.ClipData; 6 | import android.content.ClipboardManager; 7 | import android.content.ContentValues; 8 | import android.content.Context; 9 | import android.content.DialogInterface; 10 | import android.content.Intent; 11 | import android.database.Cursor; 12 | import android.database.sqlite.SQLiteDatabase; 13 | import android.os.Bundle; 14 | import android.text.Editable; 15 | import android.text.TextWatcher; 16 | import android.util.Log; 17 | import android.view.ContextMenu; 18 | import android.view.ContextMenu.ContextMenuInfo; 19 | import android.view.Menu; 20 | import android.view.MenuItem; 21 | import android.view.MotionEvent; 22 | import android.view.View; 23 | import android.view.View.OnCreateContextMenuListener; 24 | import android.view.WindowManager; 25 | import android.view.inputmethod.InputMethodManager; 26 | import android.widget.AdapterView; 27 | import android.widget.AdapterView.AdapterContextMenuInfo; 28 | import android.widget.AdapterView.OnItemClickListener; 29 | import android.widget.EditText; 30 | import android.widget.ImageButton; 31 | import android.widget.ImageView; 32 | import android.widget.LinearLayout; 33 | import android.widget.ListView; 34 | import android.widget.SimpleCursorAdapter; 35 | import android.widget.TextView; 36 | import android.widget.Toast; 37 | 38 | import java.io.BufferedWriter; 39 | import java.io.File; 40 | import java.io.FileWriter; 41 | import java.lang.reflect.Field; 42 | 43 | public class FavoriteActivity extends Activity { 44 | EditText editText; 45 | ImageButton imageButton_clear; 46 | InputMethodManager IMM; 47 | ListView listView; 48 | SimpleCursorAdapter adapter; 49 | int position = 0; 50 | 51 | @Override 52 | protected void onCreate(Bundle savedInstanceState) { 53 | super.onCreate(savedInstanceState); 54 | setContentView(R.layout.activity_favorite); 55 | getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN); 56 | IMM = (InputMethodManager) getApplicationContext().getSystemService(Context.INPUT_METHOD_SERVICE); 57 | imageButton_clear = (ImageButton) findViewById(R.id.imageButton_clear); 58 | imageButton_clear.setOnClickListener(new OnClickListener()); 59 | imageButton_clear.setVisibility(View.GONE); 60 | editText = (EditText) findViewById(R.id.editText); 61 | editText.addTextChangedListener(new EditChangedListener()); 62 | listView = (ListView) findViewById(R.id.listView1); 63 | listView.setOnItemClickListener(new OnItemClickListener() { 64 | @Override 65 | public void onItemClick(AdapterView arg0, View arg1, int arg2, long arg3) { 66 | String url = ((TextView) arg1.findViewById(R.id.website)).getText().toString(); 67 | Intent intent = new Intent(FavoriteActivity.this, MainActivity.class); 68 | intent.putExtra("url", url); 69 | setResult(RESULT_OK, intent); 70 | IMM.hideSoftInputFromWindow(editText.getWindowToken(), 0); 71 | finish(); 72 | } 73 | }); 74 | listView.setOnCreateContextMenuListener(new OnCreateContextMenuListener() { 75 | @Override 76 | public void onCreateContextMenu(ContextMenu menu, View view, ContextMenuInfo menuInfo) { 77 | AdapterContextMenuInfo info = (AdapterContextMenuInfo) menuInfo; 78 | String title = ((TextView) info.targetView.findViewById(R.id.title)).getText().toString(); 79 | menu.setHeaderTitle(title); 80 | menu.add(0, 0, 0, "复制链接"); 81 | menu.add(0, 1, 1, "删除"); 82 | menu.add(0, 2, 2, "修改"); 83 | menu.add(0, 3, 3, "分享"); 84 | } 85 | }); 86 | listView.setOnTouchListener(new View.OnTouchListener() { 87 | @Override 88 | public boolean onTouch(View v, MotionEvent event) { 89 | IMM.hideSoftInputFromWindow(editText.getWindowToken(), 0); 90 | return false; 91 | } 92 | }); 93 | search(editText.getText().toString()); 94 | } 95 | 96 | 97 | 98 | @Override 99 | public boolean onCreateOptionsMenu(Menu menu) { 100 | String[] sm = { "导出HTML", "导出CSV" }; 101 | for (int i=0; i\n收藏夹\n\n\n\n

收藏夹" + adapter.getCount() + "

\n\n\n"; 113 | for (int i=0; i\n"; 118 | } 119 | s += "
标题网址
" + textView_title.getText().toString() + "" + textView_website.getText().toString() + "
\n\n"; 120 | writeFile("webfav.htm", s); 121 | break; 122 | case 1: 123 | s = ""; 124 | for (int i=0; i list_webView = new ArrayList<>(); 121 | int currentPage; 122 | int FILECHOOSER_DOWNLOAD_PATH = 3; 123 | DownloadCompleteReceiver receiver; 124 | private static String[] PERMISSIONS = { 125 | Manifest.permission.READ_EXTERNAL_STORAGE, 126 | Manifest.permission.WRITE_EXTERNAL_STORAGE }; 127 | private static int REQUEST_PERMISSION_CODE = 1; 128 | 129 | @Override 130 | protected void onCreate(Bundle savedInstanceState) { 131 | super.onCreate(savedInstanceState); 132 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { 133 | //Log.e(Thread.currentThread().getStackTrace()[2] + "", "checkSelfPermission: " + checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE)); 134 | if (checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED && checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { 135 | requestPermissions(PERMISSIONS, REQUEST_PERMISSION_CODE); 136 | } 137 | } 138 | 139 | sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this); 140 | IMM = (InputMethodManager) getApplicationContext().getSystemService(Context.INPUT_METHOD_SERVICE); 141 | String path = Environment.getExternalStorageDirectory().getPath() + File.separator + "HTYBrowser"; 142 | dir = new File(path); 143 | if (!dir.exists()) { 144 | dir.mkdirs(); 145 | } 146 | 147 | setContentView(R.layout.activity_main); 148 | getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN); 149 | 150 | LinearLayout1 = (LinearLayout) findViewById(R.id.LinearLayout1); 151 | LinearLayout2 = (LinearLayout) findViewById(R.id.LinearLayout2); 152 | webViewLayout = (FrameLayout) findViewById(R.id.webViewLayout); 153 | videoLayout = (FrameLayout) findViewById(R.id.videoLayout); 154 | searchBar = (FrameLayout) findViewById(R.id.searchBar); 155 | searchBar.setVisibility(View.GONE); 156 | pgb1 = (ProgressBar) findViewById(R.id.progressBar1); 157 | button_go = (ImageButton) findViewById(R.id.button_go); 158 | button_back = (ImageButton) findViewById(R.id.button_back); 159 | button_forward = (ImageButton) findViewById(R.id.button_forward); 160 | button_menu = (ImageButton) findViewById(R.id.button_menu); 161 | button_play = (ImageButton) findViewById(R.id.button_play); 162 | button_play.setVisibility(View.GONE); 163 | editText_search = (EditText) findViewById(R.id.editText_search); 164 | textView_searchCount = (TextView) findViewById(R.id.textView_search_count); 165 | button_search_prev = (ImageButton) findViewById(R.id.button_search_prev); 166 | button_search_next = (ImageButton) findViewById(R.id.button_search_next); 167 | button_search_close = (ImageButton) findViewById(R.id.button_search_close); 168 | button_info = (ImageButton) findViewById(R.id.imageButton_info); 169 | button_title = (Button) findViewById(R.id.button_title); 170 | button_page = (Button) findViewById(R.id.button_page); 171 | button_title.setOnClickListener(new ButtonListener()); 172 | button_page.setOnClickListener(new ButtonListener()); 173 | button_go.setOnClickListener(new ButtonListener()); 174 | button_back.setOnClickListener(new ButtonListener()); 175 | button_forward.setOnClickListener(new ButtonListener()); 176 | button_menu.setOnClickListener(new ButtonListener()); 177 | button_play.setOnClickListener(new ButtonListener()); 178 | button_search_prev.setOnClickListener(new ButtonListener()); 179 | button_search_next.setOnClickListener(new ButtonListener()); 180 | button_search_close.setOnClickListener(new ButtonListener()); 181 | editText_url = (EditText) findViewById(R.id.editText_url); 182 | editText_url.setVisibility(View.GONE); 183 | WebIconDatabase.getInstance().open(getDir("icons", MODE_PRIVATE).getPath()); //获取图标数据库路径 184 | getDataFromIntent(getIntent()); 185 | 186 | editText_url.setOnEditorActionListener(new TextView.OnEditorActionListener() { 187 | @Override 188 | public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { 189 | if (actionId == EditorInfo.IME_ACTION_GO) { 190 | loadPage(editText_url.getText().toString()); 191 | return true; 192 | } 193 | return false; 194 | } 195 | }); 196 | 197 | editText_search.setOnEditorActionListener(new TextView.OnEditorActionListener() { 198 | @Override 199 | public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { 200 | if (actionId == EditorInfo.IME_ACTION_SEARCH) { 201 | list_webView.get(currentPage).findAllAsync(editText_search.getText().toString()); 202 | IMM.hideSoftInputFromWindow(editText_search.getWindowToken(), 0); 203 | return true; 204 | } 205 | return false; 206 | } 207 | }); 208 | 209 | editText_search.addTextChangedListener(new TextWatcher() { 210 | @Override 211 | public void onTextChanged(CharSequence text, int start, int before, int count) { 212 | // text 输入框中改变后的字符串信息 213 | // start 输入框中改变后的字符串的起始位置 214 | // before 输入框中改变前的字符串的位置 默认为0 215 | // count 输入框中改变后的一共输入字符串的数量 216 | list_webView.get(currentPage).findAllAsync(text.toString()); 217 | } 218 | 219 | @Override 220 | public void beforeTextChanged(CharSequence text, int start, int count, int after) { 221 | // text 输入框中改变前的字符串信息 222 | // start 输入框中改变前的字符串的起始位置 223 | // count 输入框中改变前后的字符串改变数量一般为0 224 | // after 输入框中改变后的字符串与起始位置的偏移量 225 | } 226 | 227 | @Override 228 | public void afterTextChanged(Editable edit) { 229 | // edit 输入结束呈现在输入框中的信息 230 | } 231 | }); 232 | 233 | CU = new Thread() { 234 | @Override 235 | public void run() { 236 | checkUpdate(); 237 | } 238 | }; 239 | new Thread(CU).start(); 240 | 241 | receiver = new DownloadCompleteReceiver(); 242 | IntentFilter intentFilter = new IntentFilter(); 243 | intentFilter.addAction(DownloadManager.ACTION_DOWNLOAD_COMPLETE); 244 | registerReceiver(receiver, intentFilter); 245 | } 246 | 247 | private void setFullScreen() { 248 | // RelativeLayout1.setVisibility(View.GONE); 249 | LinearLayout1.setVisibility(View.GONE); 250 | videoLayout.setVisibility(View.VISIBLE); 251 | // imageView1.setVisibility(View.VISIBLE); 252 | // 横屏显示 253 | setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); 254 | // 设置全屏的相关属性,获取当前的屏幕状态,然后设置全屏 255 | getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); 256 | // 全屏下的状态码:1098974464 257 | // 窗口下的状态吗:1098973440 258 | isFullScreen = true; 259 | } 260 | 261 | // 退出全屏 262 | private void quitFullScreen() { 263 | if (customViewCallback != null) { 264 | customViewCallback.onCustomViewHidden(); // 隐藏 265 | } 266 | // RelativeLayout1.setVisibility(View.VISIBLE); 267 | LinearLayout1.setVisibility(View.VISIBLE); 268 | LinearLayout2.setVisibility(View.VISIBLE); 269 | pgb1.setVisibility(View.VISIBLE); 270 | videoLayout.setVisibility(View.GONE); 271 | // imageView1.setVisibility(View.GONE); 272 | // 用户当前的首选方向 273 | setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_USER); 274 | // 声明当前屏幕状态的参数并获取 275 | final WindowManager.LayoutParams attrs = getWindow().getAttributes(); 276 | attrs.flags &= (~WindowManager.LayoutParams.FLAG_FULLSCREEN); 277 | getWindow().setAttributes(attrs); 278 | getWindow().clearFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS); 279 | isFullScreen = false; 280 | } 281 | 282 | public ValueCallback mUploadMessage; 283 | public ValueCallback mUploadMessageForAndroid5; 284 | public final static int FILECHOOSER_RESULTCODE = 1; 285 | public final static int FILECHOOSER_RESULTCODE_FOR_ANDROID_5 = 2; 286 | 287 | private void openFileChooserImplForAndroid5(ValueCallback uploadMsg) { 288 | mUploadMessageForAndroid5 = uploadMsg; 289 | Intent contentSelectionIntent = new Intent(Intent.ACTION_GET_CONTENT); 290 | contentSelectionIntent.addCategory(Intent.CATEGORY_OPENABLE); 291 | contentSelectionIntent.setType("*/*"); 292 | Intent chooserIntent = new Intent(Intent.ACTION_CHOOSER); 293 | chooserIntent.putExtra(Intent.EXTRA_INTENT, contentSelectionIntent); 294 | chooserIntent.putExtra(Intent.EXTRA_TITLE, "Image Chooser"); 295 | startActivityForResult(chooserIntent, FILECHOOSER_RESULTCODE_FOR_ANDROID_5); 296 | } 297 | 298 | class ButtonListener implements OnClickListener { 299 | @Override 300 | public void onClick(View v) { 301 | switch (v.getId()) { 302 | case R.id.button_title: 303 | button_title.setVisibility(View.GONE); 304 | editText_url.setVisibility(View.VISIBLE); 305 | break; 306 | case R.id.button_page: 307 | List list_title = new ArrayList<>(); 308 | for (int i = 0 ; i < list_webView.size() ; i++) { 309 | list_title.add(i + 1 + "." + list_webView.get(i).getTitle()); 310 | } 311 | String[] titles = list_title.toArray(new String[list_title.size()]); 312 | AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this); 313 | builder.setTitle("窗口"); 314 | builder.setIcon(android.R.drawable.ic_menu_slideshow); 315 | builder.setItems(titles, new DialogInterface.OnClickListener() { 316 | @Override 317 | public void onClick(DialogInterface dialog, int which) { 318 | dialog.dismiss(); 319 | if(which != currentPage) { 320 | webViewLayout.removeAllViews(); 321 | WebView webView = list_webView.get(which); 322 | webViewLayout.addView(webView); 323 | button_page.setText(which + 1 + ""); 324 | button_title.setText(webView.getTitle()); 325 | editText_url.setText(webView.getUrl()); 326 | button_info.setImageBitmap(webView.getFavicon()); 327 | currentPage = which; 328 | } 329 | } 330 | }); 331 | builder.create().show(); 332 | break; 333 | case R.id.button_go: 334 | //loadPage(editText1.getText().toString()); 335 | list_webView.get(currentPage).loadUrl(editText_url.getText().toString()); 336 | break; 337 | case R.id.button_back: 338 | if (list_webView.get(currentPage).canGoBack()) { 339 | list_webView.get(currentPage).goBack(); 340 | button_forward.setEnabled(true); 341 | } else { 342 | button_back.setEnabled(false); 343 | } 344 | break; 345 | case R.id.button_forward: 346 | if (list_webView.get(currentPage).canGoForward()) { 347 | list_webView.get(currentPage).goForward(); 348 | button_back.setEnabled(true); 349 | } else { 350 | button_forward.setEnabled(false); 351 | } 352 | break; 353 | case R.id.button_menu: 354 | MenuDialog(); 355 | break; 356 | case R.id.button_play: 357 | playVideo(); 358 | button_play.setVisibility(View.GONE); 359 | break; 360 | case R.id.button_search_prev: 361 | list_webView.get(currentPage).findNext(false); 362 | break; 363 | case R.id.button_search_next: 364 | list_webView.get(currentPage).findNext(true); 365 | break; 366 | case R.id.button_search_close: 367 | editText_search.setText(""); 368 | IMM.hideSoftInputFromWindow(editText_search.getWindowToken(), 0); 369 | searchBar.setVisibility(View.GONE); 370 | break; 371 | } 372 | } 373 | } 374 | 375 | private class MyWebViewDownLoadListener implements DownloadListener { 376 | @Override 377 | public void onDownloadStart(String url, String userAgent, String contentDisposition, String mimeType, long contentLength) { 378 | Log.e(Thread.currentThread().getStackTrace()[2] + ": ", url + ", " + userAgent + "," + contentDisposition + ", " + mimeType + ", " + contentLength); 379 | dialog_download(url, contentDisposition, mimeType, contentLength); 380 | } 381 | } 382 | 383 | @Override 384 | public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) { 385 | super.onCreateContextMenu(menu, v, menuInfo); 386 | WebView w = (WebView) v; 387 | HitTestResult result = w.getHitTestResult(); 388 | HTRE = result.getExtra(); 389 | Log.e(Thread.currentThread().getStackTrace()[2] + " ", HTRE + ""); 390 | menu.setHeaderTitle(HTRE); 391 | if (result.getType() == HitTestResult.IMAGE_TYPE || result.getType() == HitTestResult.SRC_IMAGE_ANCHOR_TYPE) { 392 | menu.setHeaderIcon(android.R.drawable.ic_menu_gallery); 393 | menu.add(0, 0, 0, "查看图片"); 394 | //menu.add(0, 1, 1, "复制图片"); 395 | menu.add(0, 2, 2, "保存图片").setIcon(android.R.drawable.ic_menu_save); // Context menu items do not support icons 396 | menu.add(0, 3, 3, "复制链接"); 397 | menu.add(0, 4, 4, "屏蔽图片"); 398 | menu.add(0, 5, 5, "隐藏图片"); 399 | } else if (result.getType() == HitTestResult.SRC_ANCHOR_TYPE) { 400 | menu.setHeaderIcon(R.drawable.link); 401 | menu.add(0, 0, 0, "在新窗口打开链接"); 402 | menu.add(0, 2, 2, "下载"); 403 | menu.add(0, 3, 3, "复制链接"); 404 | } 405 | } 406 | 407 | @Override 408 | public boolean onContextItemSelected(MenuItem item) { 409 | switch (item.getItemId()) { 410 | case 0: 411 | newWindow(HTRE); 412 | break; 413 | case 1: 414 | ClipboardManager clipboardManager = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE); 415 | ContentValues values = new ContentValues(2); 416 | values.put(MediaStore.Images.Media.MIME_TYPE, "image/*"); 417 | values.put(MediaStore.Images.Media.DATA, HTRE); 418 | Uri imageUri = getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values); 419 | ClipData clipData = ClipData.newUri(getContentResolver(), "Image", imageUri); 420 | clipboardManager.setPrimaryClip(clipData); 421 | break; 422 | case 2: 423 | String mime = URLConnection.getFileNameMap().getContentTypeFor(HTRE); 424 | Log.e(Thread.currentThread().getStackTrace()[2] + " ", "" + mime); 425 | if (mime == null) mime = ""; 426 | dialog_download(HTRE, "", mime, 0); 427 | break; 428 | case 3: 429 | clipboardManager = (ClipboardManager) getSystemService(CLIPBOARD_SERVICE); 430 | clipboardManager.setPrimaryClip(ClipData.newPlainText("link", HTRE)); 431 | Toast.makeText(getApplicationContext(), "链接已复制", Toast.LENGTH_SHORT).show(); 432 | break; 433 | case 4: 434 | DialogBlock(HTRE); 435 | break; 436 | case 5: 437 | String js = "javascript:var imgs=document.getElementsByTagName('img');for(i=0;i { 542 | @Override 543 | protected String doInBackground(String... params) { 544 | String result = ""; 545 | String imgurl = HTRE; 546 | try { 547 | String sdcard = Environment.getExternalStorageDirectory().toString(); 548 | File file = new File(sdcard + "/Download"); 549 | if (!file.exists()) { 550 | file.mkdirs(); 551 | } 552 | int idx = imgurl.lastIndexOf("/"); 553 | String filename = imgurl.substring(idx); 554 | String filepath = sdcard + "/Download/" + filename; 555 | file = new File(filepath); 556 | InputStream inputStream = null; 557 | URL url = new URL(imgurl); 558 | HttpURLConnection conn = (HttpURLConnection) url.openConnection(); 559 | conn.setRequestMethod("GET"); 560 | conn.setConnectTimeout(20000); 561 | if (conn.getResponseCode() == 200) { 562 | inputStream = conn.getInputStream(); 563 | } 564 | byte[] buffer = new byte[4096]; 565 | int len = 0; 566 | FileOutputStream outStream = new FileOutputStream(file); 567 | while ((len = inputStream.read(buffer)) != -1) { 568 | outStream.write(buffer, 0, len); 569 | } 570 | outStream.close(); 571 | result = "图片已保存至:" + file.getAbsolutePath(); 572 | MediaScannerConnection.scanFile(MainActivity.this, new String[] { filepath }, null, null); 573 | } catch (Exception e) { 574 | result = "保存失败!" + e.getLocalizedMessage(); 575 | } 576 | return result; 577 | } 578 | 579 | @Override 580 | protected void onPostExecute(String result) { 581 | Toast.makeText(getApplicationContext(), result, Toast.LENGTH_SHORT).show(); 582 | } 583 | } 584 | 585 | boolean isNetworkConnected() { 586 | ConnectivityManager mConnectivityManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE); 587 | NetworkInfo mNetworkInfo = mConnectivityManager.getActiveNetworkInfo(); 588 | if (mNetworkInfo != null) { 589 | return mNetworkInfo.isAvailable(); 590 | } 591 | return false; 592 | } 593 | 594 | @Override 595 | public void onConfigurationChanged(Configuration newConfig) { 596 | super.onConfigurationChanged(newConfig); 597 | // if (this.getResources().getConfiguration().orientation == 598 | // Configuration.ORIENTATION_LANDSCAPE) { 599 | // Toast.makeText(getApplicationContext(), "横屏", Toast.LENGTH_SHORT) 600 | // .show(); 601 | // } else if (this.getResources().getConfiguration().orientation == 602 | // Configuration.ORIENTATION_PORTRAIT) { 603 | // Toast.makeText(getApplicationContext(), "竖屏", Toast.LENGTH_SHORT) 604 | // .show(); 605 | // } 606 | } 607 | 608 | @Override 609 | protected void onPause() { 610 | Log.e(Thread.currentThread().getStackTrace()[2] + "", "onPause"); 611 | // Log.e(Thread.currentThread().getStackTrace()[2] + "", "pauseVideo = " + sharedPreferences.getBoolean("switch_pasueVideoOnPause", true)); 612 | // if (sharedPreferences.getBoolean("switch_pasueVideoOnPause", true)) { 613 | // pauseVideo(); 614 | // } else { 615 | // playVideo(); 616 | // } 617 | if (isFullScreen) { 618 | button_play.setVisibility(View.VISIBLE); 619 | } 620 | super.onPause(); 621 | } 622 | 623 | @Override 624 | protected void onResume() { 625 | super.onResume(); 626 | } 627 | 628 | void pauseVideo() { 629 | String js = "javascript:var obj = document.getElementsByTagName('video');for (var i = 0; i < obj.length; i++) { obj[i].pause();}"; 630 | list_webView.get(currentPage).loadUrl(js); 631 | } 632 | 633 | void playVideo() { 634 | String js = "javascript:var obj = document.getElementsByTagName('video');for (var i = 0; i < obj.length; i++) { obj[i].play();}"; 635 | list_webView.get(currentPage).loadUrl(js); 636 | } 637 | 638 | private void MenuDialog() { 639 | String[] items = { "新建窗口", "关闭当前窗口", "收藏当前页", "收藏夹", "查找", "分享", "视频独立播放", "视频截图", "视频在播放器中打开", "查看源码", "主页", "全屏", "广告过滤规则", "设置", "检查更新", "关于", "退出", "清除缓存" }; 640 | AlertDialog.Builder builder = new AlertDialog.Builder(this); 641 | builder.setTitle("菜单"); 642 | //builder.setIcon(android.R.drawable.ic_menu_preferences); 643 | builder.setIcon(R.drawable.ic_launcher); 644 | builder.setItems(items, new DialogInterface.OnClickListener() { 645 | @Override 646 | public void onClick(DialogInterface dialog, int which) { 647 | dialog.dismiss(); 648 | switch (which) { 649 | case 0: 650 | newWindow(sharedPreferences.getString("homepage", "http://www.baidu.com")); 651 | break; 652 | case 1: 653 | list_webView.remove(currentPage); 654 | if(list_webView.size() == 0){ 655 | newWindow(sharedPreferences.getString("homepage","http://www.baidu.com")); 656 | }else{ 657 | currentPage--; 658 | if (currentPage < 0) currentPage = 0; 659 | button_page.setText(currentPage + 1 + ""); 660 | webViewLayout.removeAllViews(); 661 | WebView webView = list_webView.get(currentPage); 662 | webViewLayout.addView(webView); 663 | button_title.setText(webView.getTitle()); 664 | editText_url.setText(webView.getUrl()); 665 | button_info.setImageBitmap(webView.getFavicon()); 666 | } 667 | break; 668 | case 2: 669 | LinearLayout layout = new LinearLayout(MainActivity.this); 670 | layout.setOrientation(LinearLayout.VERTICAL); 671 | final EditText ET_title = new EditText(MainActivity.this); 672 | ET_title.setHint("标题"); 673 | ET_title.setText(list_webView.get(currentPage).getTitle()); 674 | layout.addView(ET_title); 675 | final EditText ET_url = new EditText(MainActivity.this); 676 | ET_title.setHint("网址"); 677 | ET_url.setText(list_webView.get(currentPage).getUrl()); 678 | layout.addView(ET_url); 679 | AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this); 680 | Bitmap icon = list_webView.get(currentPage).getFavicon(); 681 | if(icon == null) icon = BitmapFactory.decodeResource(getResources(), R.drawable.network); 682 | Matrix matrix = new Matrix(); 683 | matrix.postScale((float)100/icon.getWidth(), (float)100/icon.getHeight()); 684 | Bitmap bitmap = Bitmap.createBitmap(icon, 0, 0, icon.getWidth(), icon.getHeight(), matrix, true); 685 | BitmapDrawable drawable = new BitmapDrawable(getResources(), bitmap); 686 | builder.setIcon(drawable); 687 | builder.setTitle("添加收藏"); 688 | builder.setView(layout); 689 | builder.setPositiveButton("确定", new DialogInterface.OnClickListener() { 690 | @Override 691 | public void onClick(DialogInterface dialog, int which) { 692 | String stitle = ET_title.getText().toString(); 693 | String surl = ET_url.getText().toString(); 694 | Field field = null; 695 | try { 696 | //通过反射获取dialog中的私有属性mShowing 697 | field = dialog.getClass().getSuperclass().getDeclaredField("mShowing"); 698 | field.setAccessible(true);//设置该属性可以访问 699 | } catch (Exception ex) { 700 | 701 | } 702 | if (!stitle.equals("") && (surl.startsWith("http") || surl.startsWith("file:///"))) { 703 | DBHelper helper = new DBHelper(getApplicationContext()); 704 | Cursor c = helper.query(surl); 705 | if (c.getCount() == 0) { 706 | ContentValues values = new ContentValues(); 707 | values.put("website", surl); 708 | values.put("title", stitle); 709 | helper.insert(values); 710 | IMM.hideSoftInputFromWindow(ET_title.getWindowToken(), 0); 711 | } else { 712 | Toast.makeText(getApplicationContext(), "网址已存在", Toast.LENGTH_SHORT).show(); 713 | } 714 | try { 715 | //关闭 716 | field.set(dialog, true); 717 | dialog.dismiss(); 718 | } catch (Exception ex) { 719 | } 720 | } else { 721 | if (stitle.equals("")){ 722 | ET_title.setError("标题不能为空!"); 723 | } 724 | if (!surl.startsWith("http") || !surl.startsWith("file:///")){ 725 | ET_url.setError("网址错误!"); 726 | } 727 | try { 728 | //设置dialog不可关闭 729 | field.set(dialog, false); 730 | dialog.dismiss(); 731 | } catch (Exception ex) { 732 | } 733 | } 734 | } 735 | }); 736 | builder.setNegativeButton("取消", new DialogInterface.OnClickListener() { 737 | @Override 738 | public void onClick(DialogInterface dialog, int which) { 739 | IMM.hideSoftInputFromWindow(ET_title.getWindowToken(), 0); 740 | Field field = null; 741 | try { 742 | //通过反射获取dialog中的私有属性mShowing 743 | field = dialog.getClass().getSuperclass().getDeclaredField("mShowing"); 744 | field.setAccessible(true);//设置该属性可以访问 745 | } catch (Exception ex) { 746 | } 747 | try { 748 | field.set(dialog, true); 749 | dialog.dismiss(); 750 | } catch (Exception ex) { 751 | } 752 | } 753 | }); 754 | builder.create().show(); 755 | break; 756 | case 3: 757 | Intent intent = new Intent(MainActivity.this, FavoriteActivity.class); 758 | startActivityForResult(intent, 0); 759 | break; 760 | case 4: 761 | searchBar.setVisibility(View.VISIBLE); 762 | editText_search.requestFocus(); 763 | list_webView.get(currentPage).findAllAsync(editText_search.getText().toString()); 764 | break; 765 | case 5: 766 | intent = new Intent(); 767 | intent.setAction(Intent.ACTION_SEND); 768 | intent.putExtra(Intent.EXTRA_TEXT, list_webView.get(currentPage).getUrl()); 769 | intent.setType("text/plain"); 770 | startActivity(Intent.createChooser(intent, "分享")); 771 | break; 772 | case 6: 773 | String js = "javascript:var videos=document.getElementsByTagName('video'); if(videos.length!=0){ var url=videos[0].src;window.location.href=url; } else { var iframes=document.getElementsByTagName('iframe'); if(iframes.length!=0) window.location.href=iframes[0].src; }"; 774 | list_webView.get(currentPage).loadUrl(js); 775 | break; 776 | case 7: 777 | js = "javascript:function capture(){var videos=document.getElementsByTagName('video');if(videos.length==0){var iframe=document.getElementsByTagName('iframe');videos=iframe[0].contentWindow.document.getElementsByTagName('video');}var canvas=document.createElement('canvas');videos[0].crossOrigin='*';canvas.width=videos[0].videoWidth;canvas.height=videos[0].videoHeight;canvas.getContext('2d').drawImage(videos[0],0,0,canvas.width,canvas.height);var s = canvas.toDataURL('image/jpeg',1.0); return s;}"; 778 | list_webView.get(currentPage).loadUrl(js); 779 | list_webView.get(currentPage).evaluateJavascript("javascript:capture()", new ValueCallback() { 780 | @Override 781 | public void onReceiveValue(String value) { 782 | Log.e(Thread.currentThread().getStackTrace()[2] + "", value); 783 | if(!"null".equals(value)){ 784 | //字符串转Bitmap,https://www.jianshu.com/p/c9a18050a249 785 | byte[] bitmapArray = Base64.decode(value.split(",")[1], Base64.DEFAULT); 786 | final Bitmap bitmap = BitmapFactory.decodeByteArray(bitmapArray, 0, bitmapArray.length); 787 | LinearLayout layout = new LinearLayout(MainActivity.this); 788 | layout.setOrientation(LinearLayout.VERTICAL); 789 | ImageView imageView = new ImageView(MainActivity.this); 790 | imageView.setImageBitmap(bitmap); 791 | layout.addView(imageView); 792 | AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this); 793 | builder.setTitle("视频截图(" + bitmap.getWidth() + "X" + bitmap.getHeight() + ")"); 794 | builder.setView(layout); 795 | builder.setPositiveButton("保存", new DialogInterface.OnClickListener() { 796 | @Override 797 | public void onClick(DialogInterface dialog, int which) { 798 | String dir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM).toString() + File.separator + "Screenshots"; 799 | File temp = new File(dir); // 如果文件夹不存在则创建 800 | if (!temp.exists()) { 801 | temp.mkdir(); 802 | } 803 | Date date = new Date(); 804 | SimpleDateFormat SDF = new SimpleDateFormat("yyyyMMddHHmmss"); 805 | String stime = SDF.format(date); 806 | String path = dir + stime + ".jpg"; 807 | File file = new File(path); 808 | BufferedOutputStream BOS = null; 809 | try { 810 | BOS = new BufferedOutputStream(new FileOutputStream(file)); 811 | }catch (FileNotFoundException e){ 812 | Log.e(Thread.currentThread().getStackTrace()[2] + "", "" + e); 813 | } 814 | bitmap.compress(Bitmap.CompressFormat.JPEG, 100, BOS); 815 | try { 816 | BOS.flush(); 817 | } catch (IOException e) { 818 | e.printStackTrace(); 819 | } 820 | try { 821 | BOS.close(); 822 | }catch (IOException e) { 823 | e.printStackTrace(); 824 | } 825 | Toast.makeText(getApplicationContext(), "保存到:"+path, Toast.LENGTH_SHORT).show(); 826 | MediaScannerConnection.scanFile(MainActivity.this, new String[] { path }, null, null); 827 | } 828 | }); 829 | builder.setNegativeButton("关闭", new DialogInterface.OnClickListener() { 830 | @Override 831 | public void onClick(DialogInterface dialog, int which) { 832 | } 833 | }); 834 | builder.create().show(); 835 | }else{ 836 | Toast.makeText(getApplicationContext(), "请先播放视频或把视频独立播放", Toast.LENGTH_SHORT).show(); 837 | } 838 | } 839 | }); 840 | break; 841 | case 8: 842 | //网址正确,运行崩溃,本地播放器没有注册网络视频类型? 843 | js = "javascript:function getVideoUrl(){var video_url='';var videos=document.getElementsByTagName('video');if(videos.length==0){var iframe=document.getElementsByTagName('iframe');videos=iframe[0].contentWindow.document.getElementsByTagName('video');}else{video_url=videos[0].src;}return video_url;}"; 844 | list_webView.get(currentPage).loadUrl(js); 845 | list_webView.get(currentPage).evaluateJavascript("javascript:getVideoUrl()", new ValueCallback() { 846 | @Override 847 | public void onReceiveValue(String value) { 848 | Log.e(Thread.currentThread().getStackTrace()[2] + "", "" + value); 849 | if(!"null".equals(value)) { 850 | try { 851 | Intent intent1 = new Intent(Intent.ACTION_VIEW); 852 | String type = "video/*"; 853 | Uri uri = Uri.parse(value); 854 | intent1.setDataAndType(uri, type); 855 | startActivity(intent1); 856 | } catch (ActivityNotFoundException e) { 857 | Log.e(Thread.currentThread().getStackTrace()[2] + "", "" + e); 858 | Toast.makeText(getApplicationContext(), "系统默认播放器不能打开视频", Toast.LENGTH_SHORT).show(); 859 | } 860 | } 861 | } 862 | }); 863 | break; 864 | case 9://改多标签后失效 865 | js = "javascript:var s=''+document.getElementsByTagName('html')[0].innerHTML+''; document.body.innerHTML=''; var pre=document.createElement('pre'); document.body.appendChild(pre); pre.textContent=s;"; 866 | list_webView.get(currentPage).loadUrl(js); 867 | break; 868 | case 10: 869 | list_webView.get(currentPage).loadUrl(sharedPreferences.getString("homepage","")); 870 | break; 871 | case 11: 872 | getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); 873 | LinearLayout2.setVisibility(View.GONE); 874 | pgb1.setVisibility(View.GONE); 875 | isFullScreen = true; 876 | break; 877 | case 12: 878 | DialogBlockList(); 879 | break; 880 | case 13: 881 | startActivity(new Intent(MainActivity.this, SettingsActivity.class)); 882 | break; 883 | case 14: 884 | isManualCheckUpdate = true; 885 | new Thread(CU).start(); 886 | break; 887 | case 15: 888 | newWindow("file:///android_asset/about.htm"); 889 | break; 890 | case 16: 891 | unregisterReceiver(receiver); 892 | MainActivity.this.finish(); 893 | break; 894 | case 17: 895 | list_webView.get(currentPage).clearCache(true); 896 | break; 897 | } 898 | } 899 | }); 900 | builder.create().show(); 901 | } 902 | 903 | void DialogBlock(String content){ 904 | final EditText ETrule = new EditText(this); 905 | ETrule.setText(content); 906 | final AlertDialog dialogRule = new AlertDialog.Builder(this).setIcon(R.drawable.ic_launcher).setTitle("屏蔽规则").setView(ETrule).setCancelable(false).setPositiveButton("添加",null).setNeutralButton("删除",null).setNegativeButton("取消",null).create(); 907 | dialogRule.show(); 908 | dialogRule.getButton(AlertDialog.BUTTON_POSITIVE) 909 | .setOnClickListener(new View.OnClickListener() { 910 | @Override 911 | public void onClick(View v) { 912 | boolean exist = false; 913 | String rule = ETrule.getText().toString(); 914 | List rulelist = new ArrayList(Arrays.asList(ReadFile("blockrules").split("\n"))); 915 | for(int i=0;i rulelist = new ArrayList(Arrays.asList(ReadFile("blockrules").split("\n"))); 935 | for(int i=0;i adapter=new ArrayAdapter(this, android.R.layout.simple_list_item_1, datas); 987 | AlertDialog.Builder builder = new AlertDialog.Builder(this); 988 | builder.setIcon(R.drawable.ic_launcher); 989 | builder.setTitle("屏蔽规则列表:"); 990 | builder.setAdapter(adapter, new DialogInterface.OnClickListener() { 991 | @Override 992 | public void onClick(DialogInterface dialog, int which) { 993 | DialogBlock(datas[which]); 994 | //Toast.makeText(MainActivity.this, "你点击了第" + which + "个item", Toast.LENGTH_SHORT).show(); 995 | } 996 | }); 997 | builder.setPositiveButton("确定", new DialogInterface.OnClickListener() { 998 | @Override 999 | public void onClick(DialogInterface dialog, int which) { 1000 | 1001 | } 1002 | }); 1003 | builder.setNeutralButton("清空", new DialogInterface.OnClickListener() { 1004 | @Override 1005 | public void onClick(DialogInterface dialog, int which) { 1006 | AlertDialog.Builder builder1 = new AlertDialog.Builder(MainActivity.this); 1007 | builder1.setMessage("操作不可逆,确认清空吗?"); 1008 | builder1.setIcon(R.drawable.ic_launcher); 1009 | builder1.setTitle("警告"); 1010 | builder1.setPositiveButton("确认", new DialogInterface.OnClickListener() { 1011 | public void onClick(DialogInterface dialog, int which) { 1012 | String filepath = getFilesDir().getAbsolutePath() + "/blockrules"; 1013 | File file = new File(filepath); 1014 | //if(file.isFile() && file.exists()) { 1015 | Log.e(Thread.currentThread().getStackTrace()[2] + "", String.valueOf(file.delete())); 1016 | //} 1017 | } 1018 | }); 1019 | builder1.setNegativeButton("取消", new DialogInterface.OnClickListener() { 1020 | public void onClick(DialogInterface dialog, int which) { 1021 | 1022 | } 1023 | }); 1024 | builder1.create().show(); 1025 | } 1026 | }); 1027 | builder.setNegativeButton("取消", new DialogInterface.OnClickListener() { 1028 | @Override 1029 | public void onClick(DialogInterface dialog, int which) { 1030 | 1031 | } 1032 | }); 1033 | builder.show(); 1034 | } 1035 | 1036 | String ReadFile(String filename) { 1037 | String s = ""; 1038 | FileInputStream istream; 1039 | try { 1040 | istream = MainActivity.this.openFileInput(filename); 1041 | byte[] buffer = new byte[1024]; 1042 | ByteArrayOutputStream ostream = new ByteArrayOutputStream(); 1043 | int len; 1044 | while ((len = istream.read(buffer)) != -1) { 1045 | ostream.write(buffer, 0, len); 1046 | } 1047 | s = new String(ostream.toByteArray()); 1048 | istream.close(); 1049 | ostream.close(); 1050 | return s; 1051 | } catch (FileNotFoundException e) { 1052 | Log.e(Thread.currentThread().getStackTrace()[2] + "", "" + e); 1053 | String path = getFilesDir().getAbsolutePath() + "/blockrules"; 1054 | File file = new File(path); 1055 | try { 1056 | file.createNewFile(); 1057 | } catch (IOException e1) { 1058 | Log.e(Thread.currentThread().getStackTrace()[2] + "", "" + e1); 1059 | } 1060 | return s; 1061 | } catch (IOException e) { 1062 | Log.e(Thread.currentThread().getStackTrace()[2] + "", "" + e); 1063 | return s; 1064 | } 1065 | } 1066 | 1067 | void ADBlock(){ 1068 | String s = ReadFile("blockrules"); 1069 | //Log.e(Thread.currentThread().getStackTrace()[2] + "", "" + s); 1070 | if(!"".equals(s)) { 1071 | String rules = s.replace("\n", ","); 1072 | if (rules.endsWith(",")) { 1073 | rules = rules.substring(0, rules.length() - 1); 1074 | } 1075 | String js = "javascript:var rules='" + rules + "';var rule=new Array();rule=rules.split(',');var img=document.getElementsByTagName('img');for(i=0;i " + versionL + " ?"); 1127 | String[] AVersionS = versionS.split("\\."); 1128 | String[] AVersionL = versionL.split("\\."); 1129 | Log.e(Thread.currentThread().getStackTrace()[2] + "", "(" + AVersionS[0] + " > " + AVersionL[0] + ") && (" + AVersionS[1] + " > " + AVersionL[1] + ")"); 1130 | if ((Integer.parseInt(AVersionS[0]) > Integer.parseInt(AVersionL[0])) || (Integer.parseInt(AVersionS[0]) == Integer.parseInt(AVersionL[0]) && Integer.parseInt(AVersionS[1]) > Integer.parseInt(AVersionL[1]))) { 1131 | Looper.prepare(); 1132 | AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this); 1133 | builder.setIcon(R.drawable.ic_launcher); 1134 | builder.setTitle("升级"); 1135 | builder.setMessage("发现新版本 " + versionS + " ,当前版本 " + versionL + " ,是否升级?"); 1136 | builder.setPositiveButton("确定", new DialogInterface.OnClickListener() { 1137 | @Override 1138 | public void onClick(DialogInterface dialog, int which) { 1139 | downloadBySystem(urlUpdate, "", "", "", "HTYBrowser.apk"); 1140 | } 1141 | }); 1142 | builder.setNegativeButton("取消", new DialogInterface.OnClickListener() { 1143 | @Override 1144 | public void onClick(DialogInterface dialog, int which) { 1145 | } 1146 | }); 1147 | AlertDialog dialog = builder.create(); 1148 | dialog.show(); 1149 | Looper.myLooper().loop(); 1150 | } else { 1151 | if(isManualCheckUpdate) { 1152 | Looper.prepare(); 1153 | Toast.makeText(getApplicationContext(), "当前版本 " + versionL + " >= 服务器版本 "+ versionS + ",是最新的版本", Toast.LENGTH_SHORT).show(); 1154 | Looper.myLooper().loop(); 1155 | } 1156 | Log.e("检查更新: ", "当前版本是最新的版本"); 1157 | } 1158 | //} 1159 | } catch (PackageManager.NameNotFoundException e) { 1160 | e.printStackTrace(); 1161 | } catch (IOException e) { 1162 | e.printStackTrace(); 1163 | } 1164 | } 1165 | 1166 | private class DownloadCompleteReceiver extends BroadcastReceiver { 1167 | @Override 1168 | public void onReceive(Context context, Intent intent) { 1169 | Log.e(Thread.currentThread().getStackTrace()[2] + "", intent != null ? intent.toUri(0) : null); 1170 | if (intent != null) { 1171 | if (DownloadManager.ACTION_DOWNLOAD_COMPLETE.equals(intent.getAction())) { 1172 | long downloadId = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1); 1173 | Log.e(Thread.currentThread().getStackTrace()[2] + "", downloadId + ""); 1174 | DownloadManager downloadManager = (DownloadManager) context.getSystemService(DOWNLOAD_SERVICE); 1175 | if (downloadId == downloadIdUpdate) { 1176 | Uri uri = downloadManager.getUriForDownloadedFile(downloadId); 1177 | Log.e(Thread.currentThread().getStackTrace()[2] + "", uri.toString()); 1178 | Intent intent1 = new Intent(Intent.ACTION_VIEW); 1179 | intent1.setDataAndType(uri, "application/vnd.android.package-archive"); 1180 | startActivity(intent1); 1181 | } 1182 | } 1183 | } 1184 | } 1185 | } 1186 | 1187 | void newWindow(String surl) { 1188 | WebView webView = new WebView(MainActivity.this); 1189 | settingWebView(webView); 1190 | webView.loadUrl(surl); 1191 | webViewLayout.removeAllViews(); 1192 | webViewLayout.addView(webView); 1193 | list_webView.add(webView); 1194 | currentPage = list_webView.size() - 1; 1195 | button_page.setText(currentPage + 1 + ""); 1196 | } 1197 | 1198 | void settingWebView(WebView webView) { 1199 | registerForContextMenu(webView); // 注册菜单 1200 | webView.requestFocusFromTouch(); // 请求触摸焦点 1201 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { 1202 | webView.setWebContentsDebuggingEnabled(true); // 允许调试 1203 | } 1204 | 1205 | WebSettings webSettings = webView.getSettings(); 1206 | webSettings.setJavaScriptEnabled(true); // 开启JS 1207 | webSettings.setJavaScriptCanOpenWindowsAutomatically(true); // 允许JS打开窗口 1208 | webSettings.setCacheMode(WebSettings.LOAD_DEFAULT); // 开启缓存 1209 | // 自适应屏幕 1210 | webSettings.setUseWideViewPort(true); 1211 | webSettings.setLoadWithOverviewMode(true); 1212 | webSettings.setSupportZoom(true); // 支持缩放 1213 | webSettings.setBuiltInZoomControls(true); // 启用内置缩放控件 1214 | webSettings.setDisplayZoomControls(false); // 隐藏缩放控件 1215 | webSettings.setAllowFileAccess(true); // 开启文件访问 1216 | webSettings.setDatabaseEnabled(true); // 开启数据库 1217 | webSettings.setDomStorageEnabled(true); // 开启localStorage 1218 | webSettings.setGeolocationEnabled(true); // 开启定位 1219 | webSettings.setSupportMultipleWindows(true); // 支持多窗口 1220 | webSettings.setAllowUniversalAccessFromFileURLs(true); // 允许跨域 1221 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { 1222 | webSettings.setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW); // 允许HTTPS、HTTP混合内容 1223 | } 1224 | if (sharedPreferences.getBoolean("switch_pcmode", false)) { 1225 | webSettings.setUserAgentString("Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.134 Safari/537.36"); 1226 | } 1227 | 1228 | webView.setWebViewClient(new WebViewClient() { 1229 | @Override 1230 | public boolean shouldOverrideUrlLoading(WebView view, String url) { 1231 | Log.e(Thread.currentThread().getStackTrace()[2] + "", url); 1232 | // 协议过滤 1233 | if (url.startsWith("http") || url.startsWith("ftp://") && !url.startsWith("https://cdn-haokanapk.baidu.com/")) { 1234 | if (url.startsWith("https://baiduyunbo.com/?id=")) { 1235 | String id = url.replace("https://baiduyunbo.com/?id=",""); 1236 | view.loadUrl("https://m3u8.cdnpan.com/"+ id + ".m3u8"); 1237 | } else { 1238 | view.loadUrl(url); 1239 | } 1240 | return false; 1241 | } 1242 | return true; //不跳转 1243 | } 1244 | 1245 | @Override 1246 | public void onPageStarted(WebView view, String url, Bitmap favicon) { 1247 | //super.onPageStarted(view, url, favicon); 1248 | //Log.e(Thread.currentThread().getStackTrace()[2] + "", url); 1249 | button_title.setText(url); 1250 | button_title.setVisibility(View.VISIBLE); 1251 | editText_url.setText(url); 1252 | editText_url.setVisibility(View.GONE); 1253 | urln = url; 1254 | button_back.setEnabled(true); 1255 | IMM.hideSoftInputFromWindow(editText_url.getWindowToken(), 0); 1256 | pgb1.setVisibility(View.VISIBLE); 1257 | button_info.setImageResource(android.R.drawable.ic_menu_info_details); 1258 | // if(favicon != null) { 1259 | // imageButton_info.setImageBitmap(favicon); 1260 | // } 1261 | } 1262 | 1263 | @Override 1264 | public void onPageFinished(WebView view, String url) { 1265 | super.onPageFinished(view, url); 1266 | pgb1.setVisibility(View.INVISIBLE); 1267 | } 1268 | 1269 | @Override 1270 | public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) { 1271 | super.onReceivedError(view, errorCode, description, failingUrl); 1272 | Toast.makeText(getApplicationContext(), "ReceivedError:" + errorCode, Toast.LENGTH_SHORT).show(); 1273 | if (isNetworkConnected()) { 1274 | switch (errorCode) { 1275 | case WebViewClient.ERROR_HOST_LOOKUP: // 找不到主机,跳转百度搜索 1276 | Log.e(Thread.currentThread().getStackTrace()[2] + "", failingUrl); 1277 | String url = "http://m.baidu.com/s?word=" + urlo; 1278 | editText_url.setText(url); 1279 | view.loadUrl(url); 1280 | urln = url; 1281 | break; 1282 | case WebViewClient.ERROR_UNSUPPORTED_SCHEME: 1283 | Log.e(Thread.currentThread().getStackTrace()[2] + "",failingUrl); 1284 | } 1285 | } else { 1286 | view.loadDataWithBaseURL( 1287 | "", 1288 | "网络未连接

网络未连接

", 1289 | "text/html", "utf-8", ""); 1290 | } 1291 | } 1292 | 1293 | }); 1294 | 1295 | webView.setFindListener(new FindListener() { 1296 | @Override 1297 | public void onFindResultReceived(int activeMatchOrdinal, int numberOfMatches, boolean isDoneCounting) { 1298 | if(numberOfMatches == 0){ 1299 | textView_searchCount.setText(activeMatchOrdinal + "/" + numberOfMatches); 1300 | }else{ 1301 | textView_searchCount.setText(activeMatchOrdinal + 1 + "/" + numberOfMatches); 1302 | } 1303 | } 1304 | }); 1305 | 1306 | webView.setDownloadListener(new MyWebViewDownLoadListener()); 1307 | 1308 | webView.setOnTouchListener(new OnTouchListener() { 1309 | @Override 1310 | public boolean onTouch(View v, MotionEvent event) { 1311 | button_title.requestFocus(); 1312 | button_title.setVisibility(View.VISIBLE); 1313 | editText_url.setVisibility(View.GONE); 1314 | IMM.hideSoftInputFromWindow(editText_url.getWindowToken(), 0); 1315 | return false; 1316 | } 1317 | }); 1318 | 1319 | webView.setWebChromeClient(new MyWebChromeClient()); 1320 | } 1321 | 1322 | 1323 | class MyWebChromeClient extends WebChromeClient { 1324 | 1325 | // JS的alert('')提示信息转换成安卓控件提示信息 1326 | @Override 1327 | public boolean onJsAlert(WebView view, String url, String message, final JsResult result) { 1328 | Toast.makeText(getApplicationContext(), message, Toast.LENGTH_SHORT).show(); 1329 | result.confirm(); 1330 | return true; 1331 | } 1332 | 1333 | // HTML5.input.file转换为安卓文件选择器 1334 | @Override 1335 | public boolean onShowFileChooser(WebView webView, ValueCallback uploadMsg, WebChromeClient.FileChooserParams fileChooserParams) { 1336 | openFileChooserImplForAndroid5(uploadMsg); 1337 | return true; 1338 | } 1339 | 1340 | // 进度条 1341 | @Override 1342 | public void onProgressChanged(WebView view, int newProgress) { 1343 | super.onProgressChanged(view, newProgress); 1344 | pgb1.setProgress(newProgress); 1345 | if (sharedPreferences.getBoolean("switch_adBlock", false)) { 1346 | ADBlock(); 1347 | } 1348 | if (sharedPreferences.getBoolean("switch_iframeBlock", false)) { 1349 | if (view.getUrl() != null) { 1350 | if (!view.getUrl().contains("baidu.com")) { 1351 | iframeBlock(); 1352 | } 1353 | } 1354 | } 1355 | // 链接关键字屏蔽 1356 | if(sharedPreferences.getBoolean("switch_filter", false)){ 1357 | String sf = sharedPreferences.getString("filter", ""); 1358 | //Log.e(Thread.currentThread().getStackTrace()[2] + "", "" + sf); 1359 | if(!sf.equals("")) { 1360 | String js = "javascript:var s='" + sf + "';var sl=s.split(';');var a=document.getElementsByTagName('a');for(var i=0;i 2 | 3 | 4 | 5 | 6 | 9 | 10 | 15 | 16 | -------------------------------------------------------------------------------- /main/res/drawable/progressbar_color.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /main/res/layout/activity_favorite.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 16 | 17 | 30 | 31 | 40 | 41 | 42 | 50 | 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 12 | 13 | 14 | 20 | 21 | 28 | 29 | 35 | 36 | 42 | 43 |