Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android開發心得——網頁通過webview調用Android的圖片或文件選擇

Android開發心得——網頁通過webview調用Android的圖片或文件選擇

編輯:關於Android編程

前段時間因為客戶需求,做一個客戶端結合web微網站的應用。其中,這個應用設計到了要修改頭像,但是這個頁面卻是在微網站上實現的,意味著網站要調用到Android的打開文件的方法,那麼這個通過webview是怎麼實現的呢?   經過跟服務器的同事討論發現,方法都是跟pc上是一樣的,都是調用一個叫input type=file的屬性,於是我就開始找,webview是怎麼響應這個屬性的了。   於是翻網站找到資料,不難查到,想要適用php上調用打開文件的方法,webview就要重寫一個名為openFileChooser的方法。   但是這個方法的使用卻不簡單,這個方法是要調用webview的setWebChromeClient方法,然後重寫一個WebChromeClient類。來到這一步,相信有點開發經驗的同行都不難解決。問題的關鍵就在於,當你重寫WebChromeClient這個類的時候會發現,根本就沒有openFileChooser這個方法,那要怎麼重寫呢?是不是意味著這個方法其實行不通?於是再次翻查資料,發現原來這個方法居然是隱藏方法,並不不存在顯性的繼承重寫關系。   最後,我發現要使用這個方法,還得自己繼承WebChromeClient這個類把openFileChooser(ValueCallback<Uri> uploadFile)這個方法給寫出來,代碼如下:   abstract class TestWebChromeClient extends WebChromeClient {       private WebChromeClient mWrappedClient;       protected TestWebChromeClient(WebChromeClient wrappedClient)     {         mWrappedClient = wrappedClient;     }       /** {@inheritDoc} */     @Override     public void onProgressChanged(WebView view, int newProgress)     {         mWrappedClient.onProgressChanged(view, newProgress);     }       /** {@inheritDoc} */     @Override     public void onReceivedTitle(WebView view, String title)     {         mWrappedClient.onReceivedTitle(view, title);     }       /** {@inheritDoc} */     @Override     public void onReceivedIcon(WebView view, Bitmap icon)     {         mWrappedClient.onReceivedIcon(view, icon);     }       /** {@inheritDoc} */     @Override     public void onReceivedTouchIconUrl(WebView view, String url, boolean precomposed)     {         mWrappedClient.onReceivedTouchIconUrl(view, url, precomposed);     }       /** {@inheritDoc} */     @Override     public void onShowCustomView(View view, CustomViewCallback callback)     {         mWrappedClient.onShowCustomView(view, callback);     }       /** {@inheritDoc} */     @Override     public void onHideCustomView()     {         mWrappedClient.onHideCustomView();     }       /** {@inheritDoc} */     @Override     public boolean onCreateWindow(WebView view, boolean dialog, boolean userGesture,             Message resultMsg)     {         return mWrappedClient.onCreateWindow(view, dialog, userGesture, resultMsg);     }       /** {@inheritDoc} */     @Override     public void onRequestFocus(WebView view)     {         mWrappedClient.onRequestFocus(view);     }       /** {@inheritDoc} */     @Override     public void onCloseWindow(WebView window)     {         mWrappedClient.onCloseWindow(window);     }       /** {@inheritDoc} */     @Override     public boolean onJsAlert(WebView view, String url, String message, JsResult result)     {         return mWrappedClient.onJsAlert(view, url, message, result);     }       /** {@inheritDoc} */     @Override     public boolean onJsConfirm(WebView view, String url, String message, JsResult result)     {         return mWrappedClient.onJsConfirm(view, url, message, result);     }       /** {@inheritDoc} */     @Override     public boolean onJsPrompt(WebView view, String url, String message,             String defaultValue, JsPromptResult result)     {         return mWrappedClient.onJsPrompt(view, url, message, defaultValue, result);     }       /** {@inheritDoc} */     @Override     public boolean onJsBeforeUnload(WebView view, String url, String message,             JsResult result)     {         return mWrappedClient.onJsBeforeUnload(view, url, message, result);     }       /** {@inheritDoc} */     @Override     public void onExceededDatabaseQuota(String url, String databaseIdentifier,             long currentQuota, long estimatedSize, long totalUsedQuota,             WebStorage.QuotaUpdater quotaUpdater)     {         mWrappedClient.onExceededDatabaseQuota(url, databaseIdentifier, currentQuota,                 estimatedSize, totalUsedQuota, quotaUpdater);     }       /** {@inheritDoc} */     @Override     public void onReachedMaxAppCacheSize(long spaceNeeded, long totalUsedQuota,             WebStorage.QuotaUpdater quotaUpdater)     {         mWrappedClient                 .onReachedMaxAppCacheSize(spaceNeeded, totalUsedQuota, quotaUpdater);     }       /** {@inheritDoc} */     @Override     public void onGeolocationPermissionsShowPrompt(String origin,             GeolocationPermissions.Callback callback)     {         mWrappedClient.onGeolocationPermissionsShowPrompt(origin, callback);     }       /** {@inheritDoc} */     @Override     public void onGeolocationPermissionsHidePrompt()     {         mWrappedClient.onGeolocationPermissionsHidePrompt();     }       /** {@inheritDoc} */     @Override     public boolean onJsTimeout()     {         return mWrappedClient.onJsTimeout();     }       /** {@inheritDoc} */     @Override     @Deprecated     public void onConsoleMessage(String message, int lineNumber, String sourceID)     {         mWrappedClient.onConsoleMessage(message, lineNumber, sourceID);     }       /** {@inheritDoc} */     @Override     public boolean onConsoleMessage(ConsoleMessage consoleMessage)     {         return mWrappedClient.onConsoleMessage(consoleMessage);     }       /** {@inheritDoc} */     @Override     public Bitmap getDefaultVideoPoster()     {         return mWrappedClient.getDefaultVideoPoster();     }       /** {@inheritDoc} */     @Override     public View getVideoLoadingProgressView()     {         return mWrappedClient.getVideoLoadingProgressView();     }       /** {@inheritDoc} */     @Override     public void getVisitedHistory(ValueCallback<String[]> callback)     {         mWrappedClient.getVisitedHistory(callback);     }       /** {@inheritDoc} */       public void openFileChooser(ValueCallback<Uri> uploadFile)     {         ((TestWebChromeClient) mWrappedClient).openFileChooser(uploadFile);     }   }   以上代碼我是在eoe上發現的,並不是我自己參詳發現的哈。但是原作是誰我就不知道了,因為這段代碼你只要百度一下openFileChooser這個方法你就能找到。   當你這樣寫好,然後就是去設置WebChromeClient的時候了。設置方法如下:       mContentView.web_main_web.setWebChromeClient(new TestWebChromeClient(                 new WebChromeClient()) { public void openFileChooser(ValueCallback<Uri> uploadFile) {      if (mUploadMessage != null)      return;      mUploadMessage = uploadFile;       //自己寫你的調用圖片方法,我這裡是封裝了調用圖片的方法的     //關鍵點在於這個mUploadMessage參數,獲取到圖片以後傳給這個參數回去就可以了。     //具體用法百度一下就有。        Select_Activity.start(mContext,mUploadMessage,indexUrlString,FILE_SELECTED);     }   });     當你設置完後,這個時候你就該興高采烈地去測試了。   於是,你有可能會興高采烈地發現,不行!!完全沒有反應!   是不是開始懷疑這個方法是坑人的?是不是在努力罵撸主?來來來,別生氣,讓我告訴你真相。   我告訴你哦,這個方法其實一點都不吭人,真的可以啊,不過~這是在3.0以前的sdk上有效...但是現在的主流Android機基本都是4.0以上了,哪裡還有3.0以前的系統?   於是你又開始了新的一輪罵娘,為什麼我會知道?因為我那個時候也是這個反應!   那時候我努力地翻資料,把百度、eoe、CSDN、德問、博客園、安卓巴士、DEVDIV都翻爛了,終於找到了原因,原來泥煤的3.0的要多加一個參數才能生效!   於是我傻乎乎的仿照人家重寫的openFileChooser方法,給TestWebChromeClient這個類添加了一個openFileChooser(ValueCallback<Uri> uploadFile, String acceptType)方法。(具體這個acceptType參數有什麼用,我還不怎麼清楚,有知道的大神麻煩告知一下哈)在webview的setWebChromeClient方法裡也添加了一個對應調用方法。   於是新一輪測試又開始了。   終於,你又一次興高采烈地罵娘了,泥煤的還是不行啊!(po主:喂!別打頭,把我打傻了以後就不能分享技術了!)   於是,我終於相信了國內搜索引擎和論壇的不靠譜,我投靠了谷歌和stackoverflow。   說實話,po主的英文很爛,爛得掉渣了,只有小學5年級的水准(po主那個時候是四年紀開始學的英語)所以不到逼不得已都不想投靠外國網站,實在是看不到,這搜索不來啊!   我找了足足一天得谷歌,最後通過谷歌找到了stackoverflow上有這個相同的問題(我這英文的水平只能通過谷歌使用了,捂臉)   人家大神解答到,原來尼瑪的4.0以後的版本又多了一個參數於是乎,再加一個openFileChooser(ValueCallback<Uri> uploadFile, String acceptType,String capture)方法就可以了。       下面我貼上TestWebChromeClient的完整代碼。       abstract class TestWebChromeClient extends WebChromeClient {       private WebChromeClient mWrappedClient;       protected TestWebChromeClient(WebChromeClient wrappedClient)     {         mWrappedClient = wrappedClient;     }       /** {@inheritDoc} */     @Override     public void onProgressChanged(WebView view, int newProgress)     {         mWrappedClient.onProgressChanged(view, newProgress);     }       /** {@inheritDoc} */     @Override     public void onReceivedTitle(WebView view, String title)     {         mWrappedClient.onReceivedTitle(view, title);     }       /** {@inheritDoc} */     @Override     public void onReceivedIcon(WebView view, Bitmap icon)     {         mWrappedClient.onReceivedIcon(view, icon);     }       /** {@inheritDoc} */     @Override     public void onReceivedTouchIconUrl(WebView view, String url, boolean precomposed)     {         mWrappedClient.onReceivedTouchIconUrl(view, url, precomposed);     }       /** {@inheritDoc} */     @Override     public void onShowCustomView(View view, CustomViewCallback callback)     {         mWrappedClient.onShowCustomView(view, callback);     }       /** {@inheritDoc} */     @Override     public void onHideCustomView()     {         mWrappedClient.onHideCustomView();     }       /** {@inheritDoc} */     @Override     public boolean onCreateWindow(WebView view, boolean dialog, boolean userGesture,             Message resultMsg)     {         return mWrappedClient.onCreateWindow(view, dialog, userGesture, resultMsg);     }       /** {@inheritDoc} */     @Override     public void onRequestFocus(WebView view)     {         mWrappedClient.onRequestFocus(view);     }       /** {@inheritDoc} */     @Override     public void onCloseWindow(WebView window)     {         mWrappedClient.onCloseWindow(window);     }       /** {@inheritDoc} */     @Override     public boolean onJsAlert(WebView view, String url, String message, JsResult result)     {         return mWrappedClient.onJsAlert(view, url, message, result);     }       /** {@inheritDoc} */     @Override     public boolean onJsConfirm(WebView view, String url, String message, JsResult result)     {         return mWrappedClient.onJsConfirm(view, url, message, result);     }       /** {@inheritDoc} */     @Override     public boolean onJsPrompt(WebView view, String url, String message,             String defaultValue, JsPromptResult result)     {         return mWrappedClient.onJsPrompt(view, url, message, defaultValue, result);     }       /** {@inheritDoc} */     @Override     public boolean onJsBeforeUnload(WebView view, String url, String message,             JsResult result)     {         return mWrappedClient.onJsBeforeUnload(view, url, message, result);     }       /** {@inheritDoc} */     @Override     public void onExceededDatabaseQuota(String url, String databaseIdentifier,             long currentQuota, long estimatedSize, long totalUsedQuota,             WebStorage.QuotaUpdater quotaUpdater)     {         mWrappedClient.onExceededDatabaseQuota(url, databaseIdentifier, currentQuota,                 estimatedSize, totalUsedQuota, quotaUpdater);     }       /** {@inheritDoc} */     @Override     public void onReachedMaxAppCacheSize(long spaceNeeded, long totalUsedQuota,             WebStorage.QuotaUpdater quotaUpdater)     {         mWrappedClient                 .onReachedMaxAppCacheSize(spaceNeeded, totalUsedQuota, quotaUpdater);     }       /** {@inheritDoc} */     @Override     public void onGeolocationPermissionsShowPrompt(String origin,             GeolocationPermissions.Callback callback)     {         mWrappedClient.onGeolocationPermissionsShowPrompt(origin, callback);     }       /** {@inheritDoc} */     @Override     public void onGeolocationPermissionsHidePrompt()     {         mWrappedClient.onGeolocationPermissionsHidePrompt();     }       /** {@inheritDoc} */     @Override     public boolean onJsTimeout()     {         return mWrappedClient.onJsTimeout();     }       /** {@inheritDoc} */     @Override     @Deprecated     public void onConsoleMessage(String message, int lineNumber, String sourceID)     {         mWrappedClient.onConsoleMessage(message, lineNumber, sourceID);     }       /** {@inheritDoc} */     @Override     public boolean onConsoleMessage(ConsoleMessage consoleMessage)     {         return mWrappedClient.onConsoleMessage(consoleMessage);     }       /** {@inheritDoc} */     @Override     public Bitmap getDefaultVideoPoster()     {         return mWrappedClient.getDefaultVideoPoster();     }       /** {@inheritDoc} */     @Override     public View getVideoLoadingProgressView()     {         return mWrappedClient.getVideoLoadingProgressView();     }       /** {@inheritDoc} */     @Override     public void getVisitedHistory(ValueCallback<String[]> callback)     {         mWrappedClient.getVisitedHistory(callback);     }       /** {@inheritDoc} */       public void openFileChooser(ValueCallback<Uri> uploadFile)     {         ((TestWebChromeClient) mWrappedClient).openFileChooser(uploadFile);     }       /** {@inheritDoc} */       public void openFileChooser(ValueCallback<Uri> uploadFile, String acceptType)     {         ((TestWebChromeClient) mWrappedClient).openFileChooser(uploadFile, acceptType);     }       /** {@inheritDoc} */       public void openFileChooser(ValueCallback<Uri> uploadFile, String acceptType,             String capture)     {         ((TestWebChromeClient) mWrappedClient).openFileChooser(uploadFile, acceptType,                 capture);     } }  一下是setWebChromeClient需要添加的方法。       public void openFileChooser(ValueCallback<Uri> uploadFile, String acceptType)             {                 openFileChooser(uploadFile);             }               public void openFileChooser(ValueCallback<Uri> uploadFile, String acceptType,                     String capture)             {                 openFileChooser(uploadFile);             } 盡管前面很多部分都不難找到,但是後面這段3.0和4.0坑爹隱藏代碼實在讓人慘死。我當初都差點放棄了,國內論壇我還沒有發現到關於這個描述,所以我就在這裡分享一下,也當作是馬克,省得以後忘記了。   這回終於不用再被罵娘了,感謝CCAV,感謝TVC,感謝老爸,感謝老媽,感謝老外。   各位有什麼不懂的歡迎交流,可以來關注我新浪微博琴弦欲奏,歡迎共同探討Android的應用開發的問題。
  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved