Android用PhoneGap封裝webapp在android代碼中實現連按退出和loadingpage


用PhoneGap封裝后的程序有一些瑕疵,比如啟動時黑屏,菜單按鈕和返回按鈕不好控制等。

PhoneGap也在github提交的它的源碼(版本:2.8):

https://github.com/apache/cordova-android/tree/master/framework/src/org/apache/cordova

先說loadingpage,其實在phonegap提供的api中已經提供了設置的方法:

public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        super.setIntegerProperty("loadUrlTimeoutValue",30 * 1000);
        //設定loadingpage背景
        super.setIntegerProperty("splashscreen", R.drawable.bg);
        
        //判斷網絡是否可用,不可用直接轉到相關錯誤提示頁面
        ConnectivityManager cwjManager=(ConnectivityManager)getSystemService(CONNECTIVITY_SERVICE);
        NetworkInfo netInfo = cwjManager.getActiveNetworkInfo();
        if(null != netInfo && netInfo.isAvailable()){
            super.loadUrl("http://xx.com/index.html", 10000);
        }else{
            super.loadUrl("file:///android_asset/www/error.html", 3000);
        }
    }

注意在訪問網絡地址時,必須調用有2個參數的loadurl方法才會顯示背景圖,即:

super.loadUrl("http://xx.com/index.html", 10000);

通過看CordovaActivity(你的Activity需要集成的基礎Activity)的源碼知道2個參數和1個參數的loadurl內容是不一樣的。

這樣設置后,又出現了一個問題,第二個參數timeout表示背景圖顯示的時間,不管頁面是否加載完,總是會顯示給定的時間,哪怕你的應用1秒就已加載完成了。通過大量的觀察后,發現在logcat里面有這么一句:

06-24 15:17:35.060: D/DroidGap(30429): onMessage(onPageFinished,http://xx.com/index.html)

推測在頁面加載完成后,會調用CordovaActivity的onMessage方法,並且參數分別是onPageFinished和http://xx.com/index.html。在結合源碼,發現在onMessage中對有些參數id的動作有所處理,如“splashscreen”,“spinner”。但是沒有對“onPageFinished”的處理。

所以考慮在自己的activity中重寫該方法,對“onPageFinished”有所處理:

@Override
public Object onMessage(String id, Object data) {
        if(id.equals("onPageFinished")){
            this.removeSplashScreen();
            return null;
        }
        return super.onMessage(id, data);
    }

這樣loadingpage的顯示時間就會和加載時間相同了。

對於按鈕的控制:

通常會對app做"再按一次退出程序"的處理,但是發現用通常的重寫keydown事件的方法時,程序並不是那么聽話。在其他頁面時,會返回,不能在返回時就退出了。內嵌瀏覽器的痕跡明顯。通過觀察源碼也可以知道,在CordovaActivity中有一個繼承自WebView的CordovaWebView。在觀察CordovaWebView的源碼,發現它對程序的keydown和keyup的事件重寫了:

    @Override
    public boolean onKeyUp(int keyCode, KeyEvent event)
    {
        // If back key
        if (keyCode == KeyEvent.KEYCODE_BACK) {
            // A custom view is currently displayed  (e.g. playing a video)
            if(mCustomView != null) {
                this.hideCustomView();
            } else {
                // The webview is currently displayed
                // If back key is bound, then send event to JavaScript
                if (this.bound) {
                    this.loadUrl("javascript:cordova.fireDocumentEvent('backbutton');");
                    return true;
                } else {
                    // If not bound
                    // Go to previous page in webview if it is possible to go back
                    if (this.backHistory()) {
                        return true;
                    }
                    // If not, then invoke default behaviour
                    else {
                        //this.activityState = ACTIVITY_EXITING;
                        //return false;
                        // If they hit back button when app is initializing, app should exit instead of hang until initilazation (CB2-458)
                        this.cordova.getActivity().finish();
                    }
                }
            }
        }
        // Legacy
        else if (keyCode == KeyEvent.KEYCODE_MENU) {
            if (this.lastMenuEventTime < event.getEventTime()) {
                this.loadUrl("javascript:cordova.fireDocumentEvent('menubutton');");
            }
            this.lastMenuEventTime = event.getEventTime();
            return super.onKeyUp(keyCode, event);
        }
        // If search key
        else if (keyCode == KeyEvent.KEYCODE_SEARCH) {
            this.loadUrl("javascript:cordova.fireDocumentEvent('searchbutton');");
            return true;
        }
        else if(keyUpCodes.contains(keyCode))
        {
            //What the hell should this do?
            return super.onKeyUp(keyCode, event);
        }

        //Does webkit change this behavior?
        return super.onKeyUp(keyCode, event);
    }

//由於退出功能在onkeyup,所以只關心onkeyup

還是老辦法,自己實現一個繼承自CordovaWebView的webview,重寫onkeyup方法:

import java.util.Timer;
import java.util.TimerTask;

import org.apache.cordova.CordovaWebView;

import android.content.Context;
import android.util.AttributeSet;
import android.view.KeyEvent;
import android.widget.Toast;

/**
 * 當按下返回按鈕是提示再按退出,而不是返回
 * @author Lee
 */
public class NobackWebView extends CordovaWebView {

    public NobackWebView(Context context) {
        super(context);
    }

    public NobackWebView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }
    public NobackWebView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    public NobackWebView(Context context, AttributeSet attrs, int defStyle, boolean privateBrowsing) {
        super(context, attrs, defStyle, privateBrowsing);
    }
    
    @Override
    public boolean onKeyUp(int keyCode, KeyEvent event){
        
        if (keyCode == KeyEvent.KEYCODE_BACK) {
            exitBy2Click(); 
            return true;
        }else{
            return super.onKeyUp(keyCode, event);
        }
    }
    
    public void toastMessage(String msg, int duration) {
        Toast.makeText(this.getContext(), msg, duration).show();
    }
    
    private static Boolean isExit = false;  
    
    private void exitBy2Click() {  
        Timer tExit = null;  
        if (isExit == false) {  
            isExit = true; // 准備退出  
            toastMessage("再按一次退出程序", 2000);
            tExit = new Timer();  
            tExit.schedule(new TimerTask() {  
                @Override  
                public void run() {  
                    isExit = false; // 取消退出  
                }  
            }, 2000); // 如果2秒鍾內沒有按下返回鍵,則啟動定時器取消掉剛才執行的任務  
        } else {  
            System.exit(0);  
        }  
    } 
    
}

這樣在app中就可以實現"再按一次退出程序"的功能了。

還剩下最后一個步驟就是將CordovaActivity中的webview替換成自己的webview,老辦法,在自己的activity中重寫init方法:

    @Override
    public void init() {
        //只是把源碼中的CordovaWebView換成NobackWebView,其他還是源碼
        CordovaWebView webView = new NobackWebView(this);
        CordovaWebViewClient webViewClient;
        if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.HONEYCOMB) {
            webViewClient = new CordovaWebViewClient(this, webView);
        } else {
            webViewClient = new IceCreamCordovaWebViewClient(this, webView);
        }
        this.init(webView, webViewClient,
                new CordovaChromeClient(this, webView));
    }

這樣就大功告成了。菜單按鈕的操作也是類似的方法,就不介紹了,如果像實現返回按鈕還是執行返回動作,只是在首頁時才提示退出,可以參考源碼,在重寫的方法中調用返回方法,在首頁時退出。

 

以上的方法只是針對js不熟或不喜歡js處理的同學,因為PhoneGap在js代碼中提供的相似的功能,比如loadingpage的關閉可以在設備初始化后調用:navigator.splashscreen.hide();方法。菜單,返回按鈕的操作可以在js中注冊等,這些網上應該比較多,就不介紹了。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM