2016-08-17 22 views
7

hi Tôi đang gặp phải tình huống sau:Trình xử lý AndroidView có phản hồi gốc được nhấp vào Url trước khi tải

Tôi đang hiển thị một Trang web trải qua một WebView theo nguồn gốc phản ứng. Trên trang web này có một liên kết đến tệp PassWallet (.pkpass) (không phải là trường hợp sử dụng duy nhất). Khi tôi nhấp vào bất kỳ liên kết nào trên trang web này, tôi muốn kiểm tra xem đó là một trang web khác hoặc tệp .pkpass hay bất kỳ thứ gì. Trong khi kiểm tra này đang chạy Tôi không muốn tải bất cứ điều gì, chỉ cần chờ cho đến khi chức năng của tôi kết thúc và tôi biết nếu tôi nên mở một trang web hoặc mở một ứng dụng hoặc bất cứ điều gì. Tôi muốn làm điều này ở phía JavaScript bởi vì toàn bộ chức năng định tuyến của tôi đều ở đó và theo ý kiến ​​phản ứng của tôi được tạo cho trường hợp này :-)

Trên iOS có chức năng đẹp này onShouldStartLoadWithRequest.

_onShouldStartLoadWithRequest(e) { 

    if(checkUrl(e.url)) { 

     let Router = this.props.navigator.props.router; 
     let route = Router.getRouteFromUrl(e.url); 
     this.props.navigator.push(route); 

     return false; 

    } 

    return true; 
} 

Tôi nhận được sự kiện (e) và có thể kiểm tra url đang cố gắng tải. Tôi thậm chí có thể kiểm tra với e.navigationType nếu nó là một nhấp chuột hoặc bất cứ điều gì.

Hiện tại trên Android chức năng này không tồn tại. Về phía bản địa có chức năng shouldOverrideUrlLoading nhưng chức năng này không được thực hiện trong phản ứng bản địa. Tôi tìm thấy vấn đề GitHub sau/PR https://github.com/facebook/react-native/pull/6478 Tôi đoán bây giờ, vì sự cố này đã bị đóng và do đó, có giải thích cho nên chức năng này không được triển khai.

Vì vậy, tôi bắt đầu tự tìm một cách. Tôi đã tạo ra một thành phần giao diện người dùng Native hiển thị một WebView và sau đó thực hiện phương thức này.

CustomWebViewManager.java:

package ch.mypackage; 

import android.support.annotation.Nullable; 
import android.webkit.WebView; 

import com.facebook.react.uimanager.SimpleViewManager; 
import com.facebook.react.uimanager.ThemedReactContext; 
import com.facebook.react.uimanager.annotations.ReactProp; 

public class CustomWebViewManager extends SimpleViewManager<CplusWebView> { 

    @Override 
    public String getName() { 
     return "CplusWebView"; 
    } 

    @Override 
    protected CustomWebView createViewInstance(ThemedReactContext reactContext) { 
     return new CustomWebView(reactContext); 
    } 

    @ReactProp(name = "url") 
    public void setUrl(CustomWebView view, @Nullable String url) { 
     view.loadUrl(url); 
    } 

    @ReactProp(name = "javascriptEnabled") 
    public void setJavascriptEnabled(CustomWebView view, boolean enabled) { 
     view.getSettings().setJavaScriptEnabled(enabled); 
    } 

} 

CustomWebView.java

package ch.couponplus; 

import android.util.Log; 
import android.webkit.WebView; 
import android.webkit.WebViewClient; 

import com.facebook.react.bridge.Arguments; 
import com.facebook.react.bridge.ReactContext; 
import com.facebook.react.bridge.WritableMap; 
import com.facebook.react.uimanager.ThemedReactContext; 
import com.facebook.react.uimanager.events.EventDispatcher; 
import com.facebook.react.uimanager.events.RCTEventEmitter; 

public class CustomWebView extends WebView { 

    EventDispatcher eventDispatcher; 
    EventWebClient eventWebClient; 

    public CustomWebView(ThemedReactContext reactContext) { 
     super(reactContext); 
     eventWebClient = new EventWebClient(); 
     setWebViewClient(eventWebClient); 
    } 

    protected class EventWebClient extends WebViewClient { 

     @Override 
     public boolean shouldOverrideUrlLoading(WebView view, String url) { 

      WritableMap event = Arguments.createMap(); 
      event.putString("message", "MyMessage"); 
      ReactContext reactContext = (ReactContext)getContext(); 
      reactContext.getJSModule(RCTEventEmitter.class).receiveEvent(
        getId(), 
        "topChange", 
        event); 

      return true; 
     } 

    } 

} 

Nó hoạt động như mong đợi. Bây giờ tôi có thể kích hoạt chức năng shouldOverrideUrlLoading trong JS và tạo nhật ký hoặc bất kỳ thứ gì.

Nhưng câu hỏi của tôi là làm cách nào để tôi có thể đặt true hoặc false trong Javascript để kiểm soát chức năng shouldOverrideUrlLoading của tôi? Và có khả năng làm cho các chức năng của riêng tôi có sẵn không? Cho đến bây giờ tôi chỉ quản lý để kích hoạt sự kiện onChange?

Tôi chỉ muốn làm giống như tôi đã tạo trong iOS :-(Có thể ai đó đến và nói với tôi rằng điều này là không thể vì bất kỳ lý do gì nhưng tôi nên làm cách nào hoặc bạn xử lý các trường hợp như thế này như thế nào? biết có những schemas Url nhưng rất nhiều tôi biết họ không làm việc trong trường hợp này.

tôi biết ơn sự giúp đỡ nào về cái này ....

Trả lời

7

tôi thấy một máng website trên trang web Trang web này có liên kết tới tệp PassWallet (.pkpass) (không phải là trường hợp sử dụng duy nhất ). Khi tôi nhấp vào bất kỳ liên kết nào trên Trang web này, tôi muốn kiểm tra cho dù đó là một trang web khác hoặc tệp .pkpass hay bất kỳ thứ gì.

Tôi cũng gặp vấn đề tương tự, nơi tôi muốn kiểm tra loại liên kết được nhấp trong webView của ứng dụng gốc phản ứng của tôi. Như bạn đã nói, ở bên iOS chức năng onShouldStartLoadWithRequest, không có mặt ở phía Android.

Đây là giải pháp của tôi ở phía Android.

<WebView 
     source={{uri: this.props.url}} 
     onLoad={this.onLoad.bind(this)} 
     onShouldStartLoadWithRequest={this._onShouldStartLoadWithRequest} 
     onNavigationStateChange = {this._onShouldStartLoadWithRequest} 
    /> 

Sau đó, bạn có thể làm một cái gì đó như thế này:

_onShouldStartLoadWithRequest(e) { 

if(checkUrl(e.url)) { 

    let Router = this.props.navigator.props.router; 
    let route = Router.getRouteFromUrl(e.url); 
    this.props.navigator.push(route); 

    this.refs[WEBVIEW_REF].stopLoading(); // <---- Add a similar line 
    //This will tell your webView to stop processing the clicked link 

    return false; 

} 

return true; 

Nếu tôi hiểu vấn đề của bạn một cách chính xác, bạn muốn có một cách để kiểm tra URL nhấp trong WebView của bạn và sau đó quyết định dựa trên URL để tiếp tục hoặc dừng lại và làm điều gì đó khác. Các giải pháp trên cách tôi xử lý nó trong ứng dụng của chúng tôi.

Kiểm tra các liên kết bên dưới:

https://facebook.github.io/react-native/docs/webview.html#stoploading https://github.com/facebook/react-native/pull/6886

+0

nhờ cho câu trả lời của bạn. đây là một giải pháp thực sự tốt Tôi đang sử dụng điều này trong các trường hợp khác ví dụ như khi có một liên kết và tôi muốn nó mở theo quan điểm của riêng tôi chứ không phải trong webbrowser. Nhưng nếu bạn muốn mở một liên kết không được nhắm mục tiêu đến trang web như tệp .pkpass thì ứng dụng gặp sự cố vì nó bắt đầu tải liên kết trước khi bạn có thể dừng liên kết đó. Với chức năng iOS, bạn có thể dừng yêu cầu trước khi thực hiện bất kỳ hành động nào. Theo như tôi có thể kiểm tra trường hợp này 'onNavigationStateChange' được gọi sau khi một yêu cầu tải đầu tiên. Hay bạn đã tìm cách dừng tải khi bạn nhấp vào liên kết không hợp lệ? – vanBrunneren

+0

Cách duy nhất tôi có thể nghĩ là giải quyết vấn đề này là dừng tải webview bằng cách sử dụng chức năng 'stopLoading'. Nhưng sau đó bạn nói 'onNavigationStateChage' đang được gọi sau khi yêu cầu tải .. do đó, do thời gian' stopLoading() 'được gọi - có thể đã quá muộn và ứng dụng sẽ bị lỗi. Nhưng tôi sẽ thử một lần để xem liệu giải pháp trên có hiệu quả hay không. –

+0

Tôi không thể nói chính xác chức năng nào được gọi vào thời gian nào nhưng tôi có thể thấy rằng ứng dụng gặp sự cố trước khi tôi có thể dừng ứng dụng ngay khi tôi muốn mở một liên kết như '.pkpass' – vanBrunneren

Các vấn đề liên quan