2011-02-09 2 views
5

webview를 사용하여 백그라운드에서 인증하려고하는 웹 서비스가 있습니다. 처음에 요청을 보내면 적절하게 작동하고 (자격 증명을 기준으로 실패/성공) 캐시 된 응답이 표시되는 것처럼 보입니다.WebView에서 캐싱, 쿠키 및 기타 모든 기능을 비활성화합니다.

  1. 자바 스크립트 (AddAccountJSInterface)에 대한 인터페이스를 제공하는 객체
  2. : 당신이 내 웹보기를 제어하는 ​​두 개의 추가 수업을 볼 수 있습니다 그래서

    WebView browser = new WebView(this); 
    WebSettings settings = browser.getSettings(); 
    settings.setJavaScriptEnabled(true); 
    settings.setSavePassword(false); 
    settings.setCacheMode(WebSettings.LOAD_NO_CACHE); 
    settings.setAppCacheEnabled(false); 
    browser.setWebChromeClient(new WebChromeClient() { 
        public void onProgressChanged(WebView view, int progress) { 
        Log.d("BROWSERPROGRESS", Integer.toString(progress)); 
    } 
    }); 
    jsInterface = new AddAccountJSInterface(); 
    browser.addJavascriptInterface(jsInterface, "ADDACCOUNTJSINTERFACE"); 
    browser.setWebViewClient(new AddAccountClient(this)); 
    

    : 여기

    내 웹보기 설정 코드
  3. WebViewClient

WebChromeClient이지만, 디버깅을 위해서만 존재하며, 어떤 것도 방해하지 않을 것이라고 확신합니다.

JS 인터페이스는 분석을 수행하기 위해 본문 HTML을 가져 오는 간단한 방법을 제공하기 때문에 문제가 아닌 것으로 확신합니다.

WebViewClient에는 웹 서비스의 다양한 응답을 기반으로 라우팅을위한 "사용자 지정"작업을 수행하는 다음 코드가 있습니다.

@Override 
    public boolean shouldOverrideUrlLoading(WebView view, String url) { 
     if(url.contains(INSTALL_PREFIX)) { 
      HashMap<String, String> params = extractParameters(url); 
      verificationComplete(params); 
      return true; 
     } 
     return false; 
    } 

    @Override 
    public void onPageFinished(WebView view, String url){ 
     if(invalidShop(view)) { 
      Toast.makeText(context, context.getString(R.string.no_find_shop), Toast.LENGTH_SHORT).show(); 
      shopAddressField.requestFocus(); 
      replaceUiElements(loadingBar, addAccountButton); 
     } else if(url.contains(ADMIN_AUTH_LOGIN)) { 
      if(invalidLogin(view)) { 
       Toast.makeText(context, context.getString(R.string.invalid_login),Toast.LENGTH_SHORT).show(); 
       emailField.requestFocus(); 
       replaceUiElements(loadingBar, addAccountButton); 
      } else { 
       String email = emailField.getText().toString(); 
       String password = passwordField.getText().toString(); 
       String submitJS = String.format(FORM_SUBMISSION_JS, email, password); 

       jsInterface.setInnerHTML(""); 

       browser.loadUrl(submitJS); 
      } 
     } 
    } 

내 활동에 필자가 작성해야하는 텍스트 필드가 3 개 있으며 제출하려면 버튼을 클릭해야합니다. 액티비티는 3 개의 텍스트 필드 (shopAddressField, usernameField, passwordField)에서 데이터를 가져온 다음 보이지 않는 webView에로드 된 일부 양식 데이터를 채운 다음 실행 버튼을 클릭하는 일부 자바 스크립트를 실행합니다.

마지막 부분은 엉망입니다. 쿠키는 쿠키를 사용하여 서버의 응답을 캐싱하고 서버에 데이터가 올바른지 묻는 대신이를 반환합니다.

JSInterface 단순히 나 해당 개체 내에서 함수에 연결되어 내 웹뷰에서 자바 스크립트를 실행할 수있는 자바 객체입니다

설명의 비트

. 필자의 경우, JSInterface에는 setInnerHtml (String html)이라는 하나의 함수가있다.

은 웹뷰에서 실행되는 자바 스크립트입니다 :

javascript:window.ADDACOUNTJSINTERFACE.setInnerHTML(document.body.innerHTML) 

그리고 이것은 setInnerHtml 기능입니다 :

public void setInnerHtml(String innerHtml) { 
    this.innerHtml = innerHtml; 
} 

그래서 실제로 jsInterface.setInnerHtml를 ("") 나 '실행할 때 가져온 HTML을 그냥 덮어 씁니다. (어떤 이유로 든 오래된 데이터를 가져 오지 못하게 할 것입니다). 아마도 쿠키하지

// submitJS will be something like this once all the credentials have been set 
// Note: I know that the server will make jQuery available 
// Note: Much of the Java string formatting has been removed to help clarify 
// the code. 
String submitJS = 
    "javascript:(function() { 
     $('login-input').value='username'; 
     $('password').value='password'; 
     $('sign-in-form').up().submit(); 
    })()" 
// I then simply get the webview to execute the javascript above 
webView.loadData(submitJS); 
+3

를 귀하의 질문에 주목을 받고 있지 않은지 트위터에 불평 45 분이 지나면 모욕을 당한다. 시간외 응답을 보장 받으려면 컨설턴트를 고용하십시오. 그 동안 jsInterface.setInnerHTML ("");과'submitJS'가 무엇인지에 대해 설명해주십시오. 문제가있는 곳이라고 말하기 때문입니다. – CommonsWare

+0

사과. 나는 자바 스크립트가하고있는 일과 내 jsInterface 자바 객체를 사용하는 방법에 대해 더 자세히 설명했다. 이 질문이 더 명확하게 도움이되기를 바랍니다. – csaunders

+0

매니페스트 파일에서 "android.permission.DELETE_CACHE_FILES"이 하나를 보완합니다. –

답변

2

그래서이 문제는 캐싱 기반으로하지 않은 밝혀과 :

내 submitJS에 관해서는 다시 한 번 다음과 같이 내 웹보기에서 실행되는 일부 자바 스크립트입니다.

webView에서 javascript를 실행할 때 별도의 스레드에서이 작업을 수행하면 속도가 매우 느려질 수 있습니다.이로 인해 코드가 잘못된 순서로 실행되는 경쟁 조건이 발생합니다.

나는 세마포어를 뮤텍스로 사용하여이 문제를 해결했습니다. 이렇게하면 WebView의 Javascript가 실행되기 전에 getter가 돌아 오지 않도록 할 수 있습니다.

내가 만든 인터페이스는 이제 다음과 같습니다

다음과 같이
private class AddAccountJSInterface { 
    private final String TAG = getClass().getName().toUpperCase(); 
    private Semaphore mutex = new Semaphore(1, false); 
    private String innerHTML; 

    public void aquireSemaphore() { 
     Log.d(TAG, "Attempting to lock semaphore"); 
     try { 
      mutex.acquire(); 
     } catch(InterruptedException e) { 
      Log.d(TAG, "Oh snap, we got interrupted. Just going to abort."); 
      return; 
     } 
     Log.d(TAG, "Semaphore has been aquired"); 
    } 

    @SuppressWarnings("unused") 
    public void setInnerHTML(String html) { 
      this.innerHTML = html; 
      Log.d(TAG, "setInnerHTML is now releasing semaphore."); 
      mutex.release(); 
      Log.d(TAG, "setInnerHTML has successfully released the semaphore."); 
    } 

    public synchronized String getInnerHTML() { 
     Log.d(TAG, "getInnerHTML attempting to aquire semaphore, may block..."); 
     String innerHTML = ""; 
     try { 
      mutex.acquire(); 

      Log.d(TAG, "getInnerHTML has aquired the semaphore, grabbing data."); 
      innerHTML = this.innerHTML; 

      Log.d(TAG, "getInnerHTML no longer needs semaphore, releasing"); 
      mutex.release(); 
     } catch (InterruptedException e) { 
      Log.d(TAG, "Something has gone wrong while attempting to aquire semaphore, aborting"); 
     } 

     return innerHTML; 
    } 
} 

지금 나는 내 코드에서 이것을 사용하는 방법은 다음과 같습니다

// I have access to the jsInterface object which is an instance of the class above as well as a webView which I will be executing the javascript on. 
String getInnerHtmlJS = "javascript:window.MYJSINTERFACE.setInnerHTML(document.body.innerHTML);" 
jsInterface.aquireSemaphore() 
// Execute my JS on the webview 
jsInterface.loadUrl(getInnerHtmlJS) 
// Now we get our inner HTML 
// Note: getInnerHTML will block since it must wait for the setInnerHTML (executed via the JS) function to release the semaphore 
String theInnerHTML = jsInterface.getInnerHTML(); 
+0

약간의 피드백을 얻을 때까지 나는 이것을 아직 정확한 것으로 평가하지 않을 것입니다. – csaunders

관련 문제