views:

79

answers:

2

I was reading over http://android-developers.blogspot.com/2009/04/backward-compatibility-for-android.html But I'm really not grasping how to ignore certain lines of code. I have this Activity (posted below) and it's a simple webview. However, I want to have geolocation enabled(even if it is only for 2.0 and up phones), since these methods weren't introduced until SDK 5 (android 2.0) and I would like the webview to be able to at the very least be able to load on a 1.5 phone rather than just crashing. Could someone possibly show me how to take this code and make it ignore the lines of code that i pointed out with the starred comments when the users phone SDK is LESS than SDK 5?

package com.my.app;

import com.facebook.android.R;
//NEEDS TO BE IGNORED**********************************************************
import android.webkit.GeolocationPermissions;
import android.webkit.GeolocationPermissions.Callback;
//END**************************************************************************
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;
import android.view.KeyEvent; 
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.webkit.CookieSyncManager;
import android.webkit.WebChromeClient;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.Toast;

//GeolocationPermissionsCallback NEEDS TO BE IGNORED**********************************************************
public class Places extends Activity implements GeolocationPermissions.Callback{ 
        private ProgressDialog progressBar;
        public WebView webview;

        private static final String TAG = "Main";


        String geoWebsiteURL = "http://google.com";

        @Override 
         public void onStart()
        {
           super.onStart();


           CookieSyncManager.getInstance().sync();

        }




    public void onCreate(Bundle savedInstanceState) { 
        super.onCreate(savedInstanceState); 
        setContentView(R.layout.main);
        CookieSyncManager.createInstance(this);
        CookieSyncManager.getInstance().startSync();

        webview = (WebView) findViewById(R.id.webview);
        webview.setWebViewClient(new testClient());
        webview.getSettings().setJavaScriptEnabled(true);
        webview.getSettings().setPluginsEnabled(true);
        webview.loadUrl("http://google.com");

        progressBar = ProgressDialog.show(Places.this, "", "Loading Page...");

        //THIS NEEDS TO BE IGNORED************************************************************
        webview.getSettings().setGeolocationEnabled(true);



        GeoClient geo = new GeoClient();
        webview.setWebChromeClient(geo);        

    }

    public void invoke(String origin, boolean allow, boolean remember) {

    }

    final class GeoClient extends WebChromeClient {


    @Override
    public void onGeolocationPermissionsShowPrompt(String origin,
    Callback callback) {
    super.onGeolocationPermissionsShowPrompt(origin, callback);
    callback.invoke(origin, true, false);
    }
//END OF CODE THAT NEEDS TO BE IGNORED************************************************
    }


    private class testClient extends WebViewClient { 
        @Override 
        public boolean shouldOverrideUrlLoading(WebView view, String url) {
            Log.i(TAG, "Processing webview url click...");
            view.loadUrl(url);
            return true;  



        }





        public void onPageFinished(WebView view, String url) {
            Log.i(TAG, "Finished loading URL: " +url);
            if (progressBar.isShowing()) {
                progressBar.dismiss();
            }

            if (url.startsWith("mailto:") || url.startsWith("geo:") ||
                    url.startsWith("tel:")) {
                                                Intent intent = new Intent
                    (Intent.ACTION_VIEW, Uri.parse(url));
                                                startActivity(intent);
                    }
        }
    }



        public boolean onKeyDown(int keyCode, KeyEvent event) { 
            if ((keyCode == KeyEvent.KEYCODE_BACK) && webview.canGoBack()) { 
                webview.goBack(); 
                return true; 
            }
                if (keyCode == KeyEvent.KEYCODE_SEARCH) {

                    Intent z = new Intent(this, Search.class);
                    startActivity(z);

                  }  
            return super.onKeyDown(keyCode, event);  
            }




        public boolean onCreateOptionsMenu (Menu menu) {
            super.onCreateOptionsMenu(menu);
            MenuInflater inflater = getMenuInflater();
            inflater.inflate(R.menu.menu, menu);
            return true;
        }

    @Override
    public boolean onOptionsItemSelected (MenuItem item) {
            switch (item.getItemId()) {
            case R.id.home:
                Intent m = new Intent(this, Home.class);
                startActivity(m);
                return true;

            case R.id.refresh:
                webview.reload();
                Toast.makeText(this, "Refreshing...", Toast.LENGTH_SHORT).show();
                return true;


    }
    return false;
        }

    public void onStop()
    {
       super.onStop();

       CookieSyncManager.getInstance().sync();

        }




} 
+2  A: 

There are (at least) two possible solutions for your problem:

  1. Different versions for different OS - create different builds of your software for different OS. This is a common approach, a lot of open source projects offer different builds for linux, windows, mac os. Your case is similiar, you could create different builds for android 1.5, 2.0, ...

  2. One version for all Android OS - If you can find a way to detect the version of the OS at runtime, then you can redesign your code to run on different OS. You can add special classes for android 1.6 and 2.0 and make sure, that only the correct classes are loaded.

A quick example for your code:

public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 

    // ... 

    progressBar = ProgressDialog.show(Places.this, "", "Loading Page...");

    if (isGeolocationAvailable()) {
       Android20Util.enableGeolocation(webview);
    }        
}

Android20Util contains some static methods, like:

public static void enableGeolocation(WebView webview) {
    webview.getSettings().setGeolocationEnabled(true);
    webview.setWebChromeClient(new GeoClient());
}
Andreas_D
I basically just need the Class to at least be capable of loading on a 1.5 phone. I don't necessarily need it to have the geolocation functioning. How could I go about doing option 2? Is there a way I could just make two different classes and then have it only load this class for 2.0 and up phones? and then load the alternative class for 1.5 1.6?
brybam
@brybam - with solution 2 you would distribute all classes to each android. So the application for an 1.5 android would have some incompatible classes, but they will never be loaded/used. That's the tradeoff: you don't have to do separate builds but you add some unused data to the application. [Here is a similiar problem with some solutions](http://stackoverflow.com/questions/3530721/dynamic-class-loading-to-target-multiple-android-versions)
Andreas_D
A: 

If it's possible to have missing classes, then you can do something like:

private static boolean geoLocationPresent = false;
static {
  try {
      Class.forName("some.geo.GeoLocation");
      geoLocationPresent = true;
  } catch (Exception ex) {}
}


private static class GeoLocationManager {
     public void handleGeoLocation() {
         // geolocation code here
     }
}

public void generalMethod() {
    // general flow here
    if (geoLocationPresent) {
         new GeoLocationManager().handleGeoLocation();
    }
}
Bozho