Пишем полноценный браузер под Aндроид

от автора

Изучать программирование под Андроид я начал не так давно. После того, как Eclips выдал мой первый Hello Word, сразу захотелось большего: возникло много планов и грандиозных идей. Одной такой идеей было написание своего Браузера. Думаю, у многих начинающих программистов возникало такое желание. Вот какие требования были мной поставлены и что получилось в итоге.

  • Программа должна открывать ссылки глобальной сети, свободно переходить по страничкам вперёд и назад;
  • Иметь возможность скачивать файлы и загружать обратно в сеть;
  • Создавать закладки и сохранять их;
  • Иметь возможность загружать ссылки, отправленные с других приложений;
  • Должна быть кнопка домашней страницы, меню с различными настройками и т.д.

В общем, полноценный браузер своими руками. Воплотим это в код.

Программа написана на основе стандартного webview, входящего в Android. В качестве стартовой страницы использую Яндекс, это дело вкуса. В качестве основного Activity будет MainActivity.

Первым делом задаём разметку xml файла -activity_main.xml. В качестве главного контейнера используем LinearLayout — в него заворачиваем ProgressBar для отображения процесса загрузки. Далее создаём ещё один контейнер LinearLayout — в него заворачиваем наш Webview и FrameLayout (его используем для растягивания воспроизводимого видео на весь экран).

Посмотреть код

LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"              xmlns:tools="http://schemas.android.com/tools"              android:layout_width="match_parent"              android:layout_height="match_parent"              android:orientation="vertical"              tools:context=".MainActivity">                        <ProgressBar         android:id="@+id/progress1"         android:layout_width="wrap_content"         android:layout_height="wrap_content"         android:layout_marginLeft="20dip"         android:indeterminateDrawable="@drawable/spinner_png"         android:indeterminateOnly="true"         android:layout_gravity="center_horizontal"/>               <LinearLayout          android:layout_width="fill_parent"          android:layout_height="fill_parent"          android:orientation="vertical">          <WebView             android:id="@+id/web_view"             android:layout_width="match_parent"             android:layout_height="match_parent" />         <FrameLayout             android:id="@+id/fullscreen_container"             android:layout_width="match_parent"             android:layout_height="match_parent"             android:background="@android:color/black"             android:visibility="gone"/>                </LinearLayout>  </LinearLayout> 

Начнём писать код в MainActivity

Полный код MainActivity.

Посмотреть полный код

import java.io.File;  import android.R.menu; import android.annotation.SuppressLint; import android.app.ActionBar; import android.app.Activity; import android.app.AlertDialog; import android.app.DownloadManager; import android.app.DownloadManager.Request; import android.app.KeyguardManager; import android.app.SearchManager; import android.content.BroadcastReceiver; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.content.IntentFilter; import android.content.SharedPreferences; import android.net.Uri; import android.os.Bundle; import android.os.Environment; import android.os.Parcelable; import android.os.PowerManager; import android.preference.PreferenceManager; import android.provider.MediaStore; import android.util.Log; import android.view.KeyEvent; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.view.WindowManager; import android.webkit.ConsoleMessage; import android.webkit.DownloadListener; import android.webkit.ValueCallback; import android.webkit.WebBackForwardList; import android.webkit.WebChromeClient; import android.webkit.WebView; import android.webkit.WebViewClient; import android.widget.FrameLayout; import android.widget.SearchView; import android.widget.Toast; import android.graphics.Bitmap; import android.webkit.URLUtil;  public class MainActivity extends Activity {   	//Логическая переменная для статуса соединения 	 Boolean isInternetPresent = false; 	 ConnectionDetector cd; 	 	     private WebChromeClient.CustomViewCallback mFullscreenViewCallback;     private FrameLayout mFullScreenContainer;     private View mFullScreenView;     private WebView mWebView;          String urload;          int cache = 1;          SharedPreferences sPref;          final Activity activity = this;     public Uri imageUri;      private static final int FILECHOOSER_RESULTCODE = 2888;     private ValueCallback<Uri> mUploadMessage;     private Uri mCapturedImageURI = null;        private DownloadManager downloadManager;                    @Override     protected  void onCreate(Bundle savedInstanceState) {         super.onCreate(savedInstanceState);         setContentView(R.layout.activity_main);                                                   //Создаем пример класса connection detector:         cd = new ConnectionDetector(getApplicationContext());                          // создаём кнопу home         final ActionBar actionBar = getActionBar();         actionBar.setHomeButtonEnabled(true);         actionBar.setDisplayHomeAsUpEnabled(true);                                    //  ловим intent что файл загружен и оповещаем         BroadcastReceiver receiver = new BroadcastReceiver() {             @Override             public void onReceive(Context context, Intent intent) {                 String action = intent.getAction();                 if (DownloadManager.ACTION_DOWNLOAD_COMPLETE.equals(action)) {                     loadEnd();                  }             }         };          //  ловим intent что файл загружен         registerReceiver(receiver, new IntentFilter(                 DownloadManager.ACTION_DOWNLOAD_COMPLETE));                  mWebView = (WebView) findViewById(R.id.web_view);         mFullScreenContainer = (FrameLayout) findViewById(R.id.fullscreen_container);         mWebView.setWebChromeClient(mWebChromeClient);                mWebView.loadUrl("http://yandex.ru");                  handleIntent(getIntent());                  class HelloWebViewClient extends WebViewClient {         	         	 @Override              public  void onPageStarted(WebView view, String url, Bitmap favicon) {                   super.onPageStarted(view, url, favicon);                  findViewById(R.id.progress1).setVisibility(View.VISIBLE);                  setTitle(url);                  urload=mWebView.getUrl();                  ConnectingToInternet ();              }               @Override              public boolean shouldOverrideUrlLoading(WebView view, String url) {                                     view.loadUrl(url);                                    // запускаем ссылки на маркет                   Uri uri = Uri.parse(url);                    if (uri.getScheme().equals("market")) {                      Intent i = new Intent(android.content.Intent.ACTION_VIEW);                      i.setData(uri);                      i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);                      startActivity(i);                       mWebView.canGoBack();                      {                          mWebView.goBack();                      }                  }                                // запускаем email                  if (uri.getScheme().equals("mailto")) {                      Intent i = new Intent(android.content.Intent.ACTION_SEND);                      i.setType("text/html");                      i.putExtra(Intent.EXTRA_SUBJECT, "Введите тему");                      i.putExtra(Intent.EXTRA_TEXT, "Введите текст");                      i.putExtra(Intent.EXTRA_EMAIL, new String[]{url});                      startActivity(i);                      mWebView.canGoBack();                      {                          mWebView.goBack();                      }                  }                             // запускаем звонилку                   if (uri.getScheme().equals("tel")) {                      Intent i = new Intent(android.content.Intent.ACTION_DIAL);                      i.setData(uri);                      startActivity(i);                       mWebView.canGoBack();                      {                          mWebView.goBack();                      }                  }                             // запускаем лoкцию                   if (uri.getScheme().equals("geo")) {                      Intent i = new Intent(android.content.Intent.ACTION_VIEW);                      i.setData(uri);                      startActivity(i);                       mWebView.canGoBack();                      {                          mWebView.goBack();                      }                  }                                 return true;              }                                          @Override              public void onPageFinished(WebView view, String url) {                  findViewById(R.id.progress1).setVisibility(View.GONE);               }               @Override              public void onReceivedError(WebView view, int errorCode,                                          String description, String failingUrl) {              	 ConnectingToInternet ();                  mWebView.loadUrl("file:///android_asset/error.png");               }                     }         mWebView.setWebViewClient(new HelloWebViewClient());                         // загрузка файлов на устройство                  mWebView.setDownloadListener(new DownloadListener() {             @Override             public void onDownloadStart(  final String url, String userAgent, String contentDisposition,  String mimetype, long contentLength) {              	final String fileName = URLUtil.guessFileName(url, contentDisposition, mimetype);             	                 final AlertDialog.Builder downloadDialog = new AlertDialog.Builder(MainActivity.this);                  downloadDialog.setTitle("Менеджер загрузок");                 downloadDialog.setMessage("Загрузить этот файл в папку Donwload ?" + '\n' + mimetype + '\n' + url);                 downloadDialog.setPositiveButton("Да", new DialogInterface.OnClickListener() {                     public void onClick(DialogInterface dialogInterface, int i) {                       	doDownload( url, fileName);                           dialogInterface.dismiss();                     }                 });                 downloadDialog.setNegativeButton("Нет", new DialogInterface.OnClickListener() {                     public void onClick(DialogInterface dialogInterface, int i) {                     }                 });                  downloadDialog.show();               }           });      }     // ****************************************     //*****************************************     //*****************************************          public void  ConnectingToInternet (){     	          //Получаем статус Интернет соединения           isInternetPresent = cd.ConnectingToInternet();                    //Проверяем Интернет статус:           if (isInternetPresent) {           //Интернет соединение есть           //делаем HTTP запросы:                     } else {           //Интернет соединения нет           	Toast.makeText(this, " Интернет отвалился !!!", Toast.LENGTH_SHORT).show();           }     	     }                    @SuppressLint("SetJavaScriptEnabled") 	@Override           // настройки     public void onResume(){         super.onResume();         SharedPreferences sPref =                 PreferenceManager.getDefaultSharedPreferences(this);          if (sPref.getBoolean("img", false)) {                         mWebView.getSettings().setLoadsImagesAutomatically(false);         } else {                          mWebView.getSettings().setLoadsImagesAutomatically(true);         }                  if (sPref.getBoolean("js", false)) {                          mWebView.getSettings().setJavaScriptEnabled(false);         } else {                      	mWebView.getSettings().setJavaScriptEnabled(true);         }          if (sPref.getBoolean("cache", false)) {             cache = 2;         } else {             cache = 1;         }      }     // пишем закладку          public void saveBm(String urlPage1, String urlTitle1) {          Intent intent = new Intent(this, SaveBmActivity.class);         intent.putExtra("urlTitle", urlTitle1);         intent.putExtra("urlPage", urlPage1);          startActivity(intent);     }               public void pref() {    //  настройки         Intent intent = new Intent(this, PreferencesActivity.class);         startActivity(intent);     }          // чистим кэш и историю private void clCache(){ 	clearCache(activity);         mWebView.clearCache(true);                mWebView.clearHistory();          Toast.makeText(this, "Кеш и История очищены", Toast.LENGTH_SHORT).show();     }      @Override     protected void onUserLeaveHint() {         super.onUserLeaveHint();       }      @Override     public boolean onKeyDown(int keyCode, KeyEvent event) {// кнопка назад         if ((keyCode == KeyEvent.KEYCODE_BACK)) {          	 mWebView.canGoBack();              {                  mWebView.goBack();              }                     return true;             }         return super.onKeyDown(keyCode, event);                     }          // ловим url запустившей программы          private boolean handleIntent(Intent intent) {                 String action = intent.getAction();          if (Intent.ACTION_VIEW.equals(action)) {              String url = intent.getDataString();             Toast.makeText(this, url, Toast.LENGTH_SHORT).show();              mWebView.loadUrl(url);// грузим страницу              return true;         }           return false;     }          // менеджер загрузки      private void doDownload(String url,String fileName) {         Uri uriOriginal = Uri.parse(url);          try {          	 			 			Toast.makeText(MainActivity.this, "Downloading " + fileName, Toast.LENGTH_LONG).show(); 			 			Request request = new DownloadManager.Request(Uri.parse(url)); 			request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, fileName); 			 			final DownloadManager dm = (DownloadManager) getSystemService(Context.DOWNLOAD_SERVICE); 			dm.enqueue(request);           } catch (Exception e) {              Toast.makeText(this, "Ошибка", Toast.LENGTH_SHORT).show();             Log.e("", "Problem downloading: " + uriOriginal, e);          }       }              // тянем видео на весь экран     private final WebChromeClient mWebChromeClient = new WebChromeClient() {         @Override         @SuppressWarnings("deprecation")         public void onShowCustomView(View view, int requestedOrientation, CustomViewCallback callback) {             onShowCustomView(view, callback);         }          @Override         public void onShowCustomView(View view, CustomViewCallback callback) {             if (mFullScreenView != null) {                 callback.onCustomViewHidden();                 return;             }              mFullScreenView = view;             mWebView.setVisibility(View.GONE);              mFullScreenContainer.setVisibility(View.VISIBLE);             mFullScreenContainer.addView(view);             mFullscreenViewCallback = callback;                     }          @Override         public void onHideCustomView() {             super.onHideCustomView();             if (mFullScreenView == null) {                 return;             }             mWebView.setVisibility(View.VISIBLE);             mFullScreenView.setVisibility(View.GONE);             mFullScreenContainer.setVisibility(View.GONE);             mFullScreenContainer.removeView(mFullScreenView);             mFullscreenViewCallback.onCustomViewHidden();             mFullScreenView = null;         }          // ********************************************* грузим файлы в сеть     // openFileChooser for Android 3.0+     public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType) {          // Сообщение об обновлении         mUploadMessage = uploadMsg;          try {              // Создать AndroidExampleFolder в sdcard              File imageStorageDir = new File(                     Environment.getExternalStoragePublicDirectory(                             Environment.DIRECTORY_PICTURES)                     , "AndroidExampleFolder");              if (!imageStorageDir.exists()) {                 // Создать AndroidExampleFolder в sdcard                 imageStorageDir.mkdirs();             }              // Создать камеру захваченное изображение путь к файлу и имя             File file = new File(                     imageStorageDir + File.separator + "IMG_"                             + String.valueOf(System.currentTimeMillis())                             + ".jpg");              mCapturedImageURI = Uri.fromFile(file);              // Камера захвата изображения  intent             final Intent captureIntent = new Intent(                     MediaStore.ACTION_IMAGE_CAPTURE);              captureIntent.putExtra(MediaStore.EXTRA_OUTPUT, mCapturedImageURI);              Intent i = new Intent(Intent.ACTION_GET_CONTENT);             i.addCategory(Intent.CATEGORY_OPENABLE);             i.setType("image/*");              // Создать файл селектора intent             Intent chooserIntent = Intent.createChooser(i, "Image Chooser");              // Установить камеры намерении выбора файлов             chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS                     , new Parcelable[]{captureIntent});              // На выбор изображения обхода метода onactivityresult вызов метода активности             startActivityForResult(chooserIntent, FILECHOOSER_RESULTCODE);          } catch (Exception e) {             Toast.makeText(getBaseContext(), "Exception:" + e,                     Toast.LENGTH_LONG).show();         }      }      // openFileChooser for Android < 3.0     @SuppressWarnings("unused") 	public void openFileChooser(ValueCallback<Uri> uploadMsg) {         openFileChooser(uploadMsg, "");     }      //     @SuppressWarnings("unused") 	public void openFileChooser(ValueCallback<Uri> uploadMsg,                                 String acceptType,                                 String capture) {          openFileChooser(uploadMsg, acceptType);     }           public boolean onConsoleMessage(ConsoleMessage cm) {          onConsoleMessage(cm.message(), cm.lineNumber(), cm.sourceId());         return true;     }      public void onConsoleMessage(String message, int lineNumber, String sourceID) {         //Log.d("androidruntime", "Show console messages, Used for debugging: " + message);      };      };// End setWebChromeClient      // Получаем результат   	@SuppressWarnings("unused") 	private Object data;    @Override     protected void onActivityResult(int requestCode, int resultCode, Intent data)             { 		if (data == null) {             return;         } 		String urlPage2 = data.getStringExtra("urlPage2");         mWebView.loadUrl(urlPage2);          if (requestCode == FILECHOOSER_RESULTCODE) {              if (null == this.mUploadMessage) {                 return;              }              Uri result = null;              try {                 if (resultCode != RESULT_OK) {                      result = null;                  } else {                      // извлечь из собственной переменной, если намерение состоит в нуль                     result = data == null ? mCapturedImageURI : data.getData();                 }             } catch (Exception e) {                 Toast.makeText(getApplicationContext(), "activity :" + e,                         Toast.LENGTH_LONG).show();             }              mUploadMessage.onReceiveValue(result);             mUploadMessage = null;                                                             }      }     //*****************************               public void loadEnd () {         Toast.makeText(this, "Файл Загружен в папку Donwload", Toast.LENGTH_SHORT).show();     }                    //  меню      @Override     public boolean onCreateOptionsMenu(Menu menu) {         // Inflate the menu; this adds items to the action bar if it is present.         getMenuInflater().inflate(R.menu.main, menu);         return true;     }     // *******************************************************     @Override     public boolean onOptionsItemSelected(MenuItem item) {           switch (item.getItemId()) {                               case android.R.id.home:// кнопка home                      mWebView.loadUrl("http://yandex.ru");                                       return true;             case R.id.item1:// назад                                     mWebView.canGoBack();                     {                         mWebView.goBack();                     }                                  return true;             case R.id.item2:                               // вперёд                     mWebView.canGoForward();                     {                          mWebView.goForward();                     }                                   return true;             case R.id.item3:                 // перезагрузка                     mWebView.reload();                     {                         mWebView.reload();                     }                                                     return true;             case R.id.item4:// чистим кеш             	 mWebView.clearCache(true);             	 clearCache(activity);                                   Toast.makeText(this, "Кэш чист.", Toast.LENGTH_SHORT).show();                                 return true;             case R.id.item5:             	 mWebView.clearHistory();// чистим историю             	                    Toast.makeText(this, "История чиста.", Toast.LENGTH_SHORT).show();                 return true;             case R.id.item6:                             	saveBm(mWebView.getUrl(),  mWebView.getTitle());// пишим закладку                  return true;             case R.id.item7:// панель закладок              	 Intent intent1 = new Intent(this, SaveBmActivity.class);                  startActivityForResult(intent1, 1);                  return true;             case R.id.item8:  // стоп загрузка                                 mWebView.stopLoading();                   return true;             case R.id.item9:                             	pref();// настройки                 return true;             case R.id.item10:             	   // пока пусто                 return true;             case R.id.item11:// выход                              	 if (cache == 2) {                      clCache();                  }              	 finish();             	                   return true;             default:                 return super.onOptionsItemSelected(item);         }     }     @SuppressWarnings("deprecation") 	@Override     public void onDestroy() {         super.onDestroy();         mWebView.stopLoading();         mWebView.clearCache(true);         mWebView.clearView();         mWebView.freeMemory();         mWebView.destroy();         mWebView = null;              }     // чистим кеш     void clearCache(Context context)     {         clearCacheFolder(context.getCacheDir());     }      void clearCacheFolder(final File dir)      {               if (dir!= null && dir.isDirectory())          {                      try              {                              for (File child:dir.listFiles())                  {                                      //рекурсивно чистим сначала каталоги                                      if (child.isDirectory())                          clearCacheFolder(child);                     else //потом собственно файлы                         child.delete();                  }                      }                      catch(Exception e)              {                                                 }              }          } }  

Проект можно скачать отсюда.

ссылка на оригинал статьи https://habrahabr.ru/post/276113/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *