SELECT * FROM Vzakladke.net

Статьи об автоматизации и программировании

Android, JAVA и WebView - создаем приложение для работы с сайтом

 

 

Для начала, откройте уже загруженный Eclipse и создайте новый Android Application Project. Задайте ему имя и выберите версию Android, для которой хотите скомпилировать свое приложение. Кроме того, вы можете создать иконку для своего нового приложения, а также activity. В данном случае под activity понимается набор элементов пользовательского интерфейса, занимающих весь экран и необходимых для выполнения какого-либо действия. 

IDE автоматически создает множество файлов. Давайте посмотрим на некоторые из них:

1) AndroidManifest.xml – этот файл содержит информацию о вашем приложении и обо всем, что оно умеет делать. ОС Android считывает этот файл при установке и запуске приложения. Необходимо добавить в этот файл всю информацию о функциях андроид-устройств, которые вы бы хотели использовать (камера, список контактов и т.д.). Кроме того, в данном манифесте также указываются все пользовательские (UI) темы, контроллеры, а также фоновые сервисы. 
2) res/layout{qualifier}/{name_of_your_activity}.xml – этот файл содержит описание всех UI-элементов, которые вы собираетесь использовать для того или иного activity. Для нашего гибридного приложения необходимо всего одно activity и один UI-элемент (WebView). Если вы хотите добавить какие-либо нативные кнопки Android, они должны быть описаны в данном файле;
3) src – в этой папке размещаются все ваши Java-файлы;
4) res/drawable{qualifier} – содержит все ваши графические файлы;
5) bin – здесь находятся все ваши скомпилированные файлы;
6) assets – содержит все типы файлов, к которым вы хотите иметь доступ. Это могут быть статичные HTML-файлы или какие-либо CSS или JS-файлы, которые будут добавлены в .apk вашего приложения.

 

Итак поехали...

Создаем главное активити MainActivity.java и пишем там следующее:

import android.app.Activity;
import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.Uri;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.view.Menu;
import android.view.MenuItem;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.ProgressBar;
import android.view.View.OnClickListener;
import android.view.View;
import android.view.LayoutInflater;

public class MainActivity extends Activity {
	
	Context mContext=MainActivity.this; 
	SharedPreferences appPreferences; 
	boolean isAppInstalled = false; 
	
	
	private boolean isNetworkAvailable() {
	    ConnectivityManager connectivityManager 
	          = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
	    NetworkInfo activeNetworkInfo = connectivityManager.getActiveNetworkInfo();
	    return activeNetworkInfo != null && activeNetworkInfo.isConnected();
	}

	private void addShortcut() {
	    //Adding shortcut for MainActivity on Home screen
	    Intent shortcutIntent = new Intent(getApplicationContext(),
	            MainActivity.class);

	    shortcutIntent.setAction(Intent.ACTION_MAIN);

	    Intent addIntent = new Intent();
	    addIntent
	            .putExtra(Intent.EXTRA_SHORTCUT_INTENT, shortcutIntent);
	    addIntent.putExtra(Intent.EXTRA_SHORTCUT_NAME, "ASK SQL");
	    addIntent.putExtra(Intent.EXTRA_SHORTCUT_ICON_RESOURCE,
	            Intent.ShortcutIconResource.fromContext(getApplicationContext(),
	                    R.drawable.ic_launcher));

	    addIntent
	            .setAction("com.android.launcher.action.INSTALL_SHORTCUT");
	    getApplicationContext().sendBroadcast(addIntent);
	}
	
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.preloader);	
				
	
		appPreferences = PreferenceManager.getDefaultSharedPreferences(this); 
		isAppInstalled = appPreferences.getBoolean("isAppInstalled",false); 
		if(isAppInstalled==false){ 
		    // add shortcutIcon code here
			addShortcut();
		} 
		// finally isAppInstalled should be true. 
		SharedPreferences.Editor editor = appPreferences.edit(); 
		editor.putBoolean("isAppInstalled", true); 
		editor.commit(); 
		
		 
	  if (!isNetworkAvailable()) {
		setContentView(R.layout.main);	
		
	      (findViewById(R.id.btnWeb)).setOnClickListener(new OnClickListener() {
	          @Override
	          public void onClick(View v) {  
        	  
	        	  android.os.Process.killProcess(android.os.Process.myPid());      	  	        	  
	        	  System.exit(0);
	        	  moveTaskToBack(true);
	        	  finish();

	          }
	        });			
	  } else {
		
	        
	    setContentView(R.layout.browser);

        String url = "http://asksql.org/";
        WebView myWebView = (WebView) findViewById(R.id.webView);
         
        myWebView.getSettings().setAppCacheMaxSize( 5 * 1024 * 1024 ); // 5MB
        myWebView.getSettings().setAppCacheEnabled(true);
        
        myWebView.getSettings().setAllowFileAccess(true);
        myWebView.getSettings().setJavaScriptEnabled(true);
        
        // myWebView.getSettings().setCacheMode( WebSettings.LOAD_DEFAULT ); // load online by default

        myWebView.getSettings().setCacheMode( WebSettings.LOAD_CACHE_ELSE_NETWORK );

        myWebView.setScrollBarStyle(View.SCROLLBARS_INSIDE_OVERLAY);
        
        // need to open in WebView (not in browser)
        class HelloWebViewClient extends WebViewClient 
        {
            @Override
            public boolean shouldOverrideUrlLoading(WebView view, String url) 
            {
                view.loadUrl(url);
                return true;
            }
        }

        myWebView.setWebViewClient(new HelloWebViewClient());              
        myWebView.loadUrl(url);   

	  }	  
			  
	}

	
	
	
	@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) {
        int id = item.getItemId();
        
        if (id == R.id.action_website) {

        	String urlString="http://asksql.org/";
        	Intent intent=new Intent(Intent.ACTION_VIEW,Uri.parse(urlString));
        	intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        	intent.setPackage("com.android.chrome");
        	try {
    	   		startActivity(intent);
        	} catch (ActivityNotFoundException ex) {
        	    // Chrome browser presumably not installed so allow user to choose instead
        	    intent.setPackage(null);
        	    startActivity(intent);
        	}        	
            return true;
        }
    
        else if (id == R.id.action_calc) {
        	Intent intentcalc = new Intent(this, Calc.class);
            startActivity(intentcalc);
            return true;
        }
 
        return super.onOptionsItemSelected(item);
    }	
	

}

 

 

В манифесте  хотелось бы добавить следующие разрешения - доступ к интернету, проверке соединения, установки ярлыка в HOME и доступ к файловой системе:

 

    <uses-permission android:name="android.permission.INTERNET"/>
	<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
	<uses-permission android:name="com.android.launcher.permission.INSTALL_SHORTCUT" />
	<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>

 

Чтобы пользователь мог перемещать приложение на SD карту не забываем указывать:

android:installLocation="auto"

 

isNetworkAvailable - функция проверки соединения с интернетом (если интернет есть - показываем активити с браузером, иначе другое активити). Из листинга кода понятно что у нас есть два лэяута browser.xml и main.xml

btnWeb - это будет наша кнопка на лэяуте main.xml для выхода из приложения.

addShortcut - установка ярлыка в HOME (на рабочий стол приложения)


Мы переопределили метод: shouldOverrideUrlLoading класса WebViewClient (в class HelloWebViewClient extends WebViewClient) и заменили его в созданном WebView:
myWebView.setWebViewClient(new HelloWebViewClient());

 

Чтобы при нажатии кнопки назад на устройстве не выкидывало из клиента, а возвращалось на ранее просмотренную страницу

 

@Override
public void onBackPressed() {
  if(myWebView.canGoBack()) {
  myWebView.goBack();
  } else {
  super.onBackPressed();
  }
}

 

Представим ситуацию что нужно загружать файлы с WebView используя примерно такую форму:

<form method="POST" enctype="multipart/form-data">
File to upload: <input type="file" name="uploadfile">&nbsp;&nbsp;
<input type="submit" value="Press to Upload"> to upload the file!
</form>


Решение, которое работает на WebChromeClient:

WebView webview;

private ValueCallback<Uri> mUploadMessage;
private final static int FILECHOOSER_RESULTCODE = 1;

@Override
protected void onActivityResult(int requestCode, int resultCode,
        Intent intent) {
    if (requestCode == FILECHOOSER_RESULTCODE) {
        if (null == mUploadMessage)
            return;
        Uri result = intent == null || resultCode != RESULT_OK ? null
                : intent.getData();
        mUploadMessage.onReceiveValue(result);
        mUploadMessage = null;

    }
}

// Next part 

class MyWebChromeClient extends WebChromeClient {
    // The undocumented magic method override
    // Eclipse will swear at you if you try to put @Override here
    public void openFileChooser(ValueCallback<Uri> uploadMsg) {

        mUploadMessage = uploadMsg;
        Intent i = new Intent(Intent.ACTION_GET_CONTENT);
        i.addCategory(Intent.CATEGORY_OPENABLE);
        i.setType("image/*");
        Cv5appActivity.this.startActivityForResult(
                Intent.createChooser(i, "Image Browser"),
                FILECHOOSER_RESULTCODE);
    }
}

 

 

Дата публикации: 2015-05-31 21:14:36

JAVA, Android

0

Отзывы:

Василий
Чтобы можно было делать вложения через WebView надо писать так: //@Override protected void onActivityResult(int requestCode, int resultCode, Intent intent) { if (requestCode == FILECHOOSER_RESULTCODE) { if (null == mUploadMessage) return; Uri result = intent == null || resultCode != RESULT_OK ? null : intent.getData(); mUploadMessage.onReceiveValue(result); mUploadMessage = null; } } А потом: class MyWebChromeClient extends WebChromeClient { // The undocumented magic method override // Eclipse will swear at you if you try to put @Override here // For Android 3.0+ public void openFileChooser(ValueCallback<Uri> uploadMsg) { mUploadMessage = uploadMsg; Intent i = new Intent(Intent.ACTION_GET_CONTENT); i.addCategory(Intent.CATEGORY_OPENABLE); i.setType("image/*"); MainActivity.this.startActivityForResult(Intent.createChooser(i,"File Chooser"), FILECHOOSER_RESULTCODE); } // For Android 3.0+ public void openFileChooser( ValueCallback uploadMsg, String acceptType ) { mUploadMessage = uploadMsg; Intent i = new Intent(Intent.ACTION_GET_CONTENT); i.addCategory(Intent.CATEGORY_OPENABLE); i.setType("*/*"); MainActivity.this.startActivityForResult( Intent.createChooser(i, "File Browser"), FILECHOOSER_RESULTCODE); } //For Android 4.1 public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType, String capture){ mUploadMessage = uploadMsg; Intent i = new Intent(Intent.ACTION_GET_CONTENT); i.addCategory(Intent.CATEGORY_OPENABLE); i.setType("image/*"); MainActivity.this.startActivityForResult( Intent.createChooser( i, "File Chooser" ), MainActivity.FILECHOOSER_RESULTCODE ); } } myWebView.setWebChromeClient(new MyWebChromeClient()); вот и все
Евгений
Про манифест не забываем <uses-permission android:name="android.permission.CAMERA" /> <uses-permission android:name="android.permission.FLASHLIGHT" /> <uses-feature android:name="android.hardware.camera" android:required="false" /> <uses-feature android:name="android.hardware.camera.flash" android:required="false" /> И сделаем выборку между камерой и галереей: protected void onActivityResult(int requestCode, int resultCode, Intent intent) { switch (requestCode) { case CAPTURE_RESULTCODE: if (resultCode == RESULT_OK) { // Bitmap bitmapImage = (Bitmap) intent.getExtras().get("data"); if (null == mUploadMessage) return; Uri result = intent == null || resultCode != RESULT_OK ? null : intent.getData(); String mTempFile = getPath(result); File file = new File(mTempFile); if (file.exists()) { mUploadMessage.onReceiveValue(Uri.fromFile(file)); mUploadMessage = null; } else { mUploadMessage.onReceiveValue(result); mUploadMessage = null; } } break; case FILECHOOSER_RESULTCODE: if (resultCode == RESULT_OK) { if (null == mUploadMessage) return; Uri result = intent == null || resultCode != RESULT_OK ? null : intent.getData(); // mUploadMessage.onReceiveValue(result); // mUploadMessage = null; String mTempFile = getPath(result); File file = new File(mTempFile); if (file.exists()) { mUploadMessage.onReceiveValue(Uri.fromFile(file)); mUploadMessage = null; } else { mUploadMessage.onReceiveValue(result); mUploadMessage = null; } } break; И для myWebView.setWebChromeClient( в MyWebChromeClient надо указать: //For Android 4.1 public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType, String capture){ mUploadMessage = uploadMsg; final CharSequence[] items = { "Take Photo", "Choose from Library", "Cancel" }; AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this); builder.setTitle("Add Photo!"); builder.setItems(items, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int item) { if (items[item].equals("Take Photo")) { Intent intentcam = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); startActivityForResult(intentcam, CAPTURE_RESULTCODE); } else if (items[item].equals("Choose from Library")) { startActivityForResult(new Intent(Intent.ACTION_PICK,android.provider.MediaStore.Images.Media.INTERNAL_CONTENT_URI), FILECHOOSER_RESULTCODE); } else if (items[item].equals("Cancel")) { dialog.cancel(); } } }); // builder.show(); builder.setOnCancelListener(new DialogInterface.OnCancelListener() { @Override public void onCancel(DialogInterface dialog) { //here we have to handle BACK button/cancel if ( mUploadMessage!= null ){ mUploadMessage.onReceiveValue(null); } mUploadMessage = null; dialog.cancel(); } }); builder.create().show(); }
Евгений
А еще в openFileChooser можно было так написать: try{ Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); File externalDataDir = Environment.getExternalStoragePublicDirectory( Environment.DIRECTORY_DCIM); File cameraDataDir = new File(externalDataDir.getAbsolutePath() + File.separator + "browser-photos"); cameraDataDir.mkdirs(); String mCameraFilePath = cameraDataDir.getAbsolutePath() + File.separator + System.currentTimeMillis() + ".jpg"; mCapturedImageURI = Uri.fromFile(new File(mCameraFilePath)); cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, mCapturedImageURI); Intent i = new Intent(Intent.ACTION_GET_CONTENT); i.addCategory(Intent.CATEGORY_OPENABLE); i.setType("image/*"); Intent chooserIntent = Intent.createChooser(i, "Image Chooser"); chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, new Parcelable[] { cameraIntent }); startActivityForResult(chooserIntent, FILECHOOSER_RESULTCODE); } catch(Exception e){ Toast.makeText(getBaseContext(), "Camera Exception:"+e, Toast.LENGTH_LONG).show(); }
Виталик
В "креаторе" onCreate(Bundle savedInstanceState) надо еще добавить по уму myWebView.getSettings().setSupportMultipleWindows(true); А в class MyWebChromeClient extends WebChromeClient { добавить @Override public boolean onCreateWindow(WebView view, boolean dialog, boolean userGesture, android.os.Message resultMsg) { WebView.HitTestResult result = view.getHitTestResult(); String data = result.getExtra(); Context context = view.getContext(); Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(data)); context.startActivity(browserIntent); return false; } И тогда внешние ссылки target=_blank будут открываться в новом интенте.
Виталик
А еще добавлю на стаковерфлоу видел скрипт такой, который позволяет правильно реагировать вебвьющке на ссылки типа майлту и телефон: @Override public boolean shouldOverrideUrlLoading(WebView view, String url) { if( url.startsWith("http:") || url.startsWith("https:") ) { return false; } // Otherwise allow the OS to handle it else if (url.startsWith("tel:")) { Intent tel = new Intent(Intent.ACTION_DIAL, Uri.parse(url)); startActivity(tel); return true; } else if (url.startsWith("mailto:")) { String body = "Enter your Question, Enquiry or Feedback below:\n\n"; Intent mail = new Intent(Intent.ACTION_SEND); mail.setType("application/octet-stream"); mail.putExtra(Intent.EXTRA_EMAIL, new String[]{"email address"}); mail.putExtra(Intent.EXTRA_SUBJECT, "Subject"); mail.putExtra(Intent.EXTRA_TEXT, body); startActivity(mail); return true; } return true; }
Связной
А про кнопку назад ничего не сказали! @Override public boolean onKeyDown(int keyCode, KeyEvent event) { if (keyCode == KeyEvent.KEYCODE_BACK){ if(((WebView)findViewById(R.id.webView)).canGoBack()){ ((WebView)findViewById(R.id.webView)).goBack(); return true; } } return super.onKeyDown(keyCode, event); }
Жора Джордж
Если ты из такого приложения захочешь перейти по внешней ссылке из меню, то приложение будет предлагать открыть его в вебвью - поэтому можно предугадать что у пользователя браузер хром и сразу направить его туда по это ссылке . А если такого браузера нет, то Андроид предложит альтернативный вариант: @Override public boolean onOptionsItemSelected(MenuItem item) { int id = item.getItemId(); if (id == R.id.action_website) { String urlString="http://asksql.org/articles/49"; Intent intent=new Intent(Intent.ACTION_VIEW,Uri.parse(urlString)); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); intent.setPackage("com.android.chrome"); try { startActivity(intent); } catch (ActivityNotFoundException ex) { // Chrome browser presumably not installed so allow user to choose instead intent.setPackage(null); startActivity(intent); } return true; }

Ваше имя:

Ваш e-mail (необязательно):

Сообщение:

Captcha