hello青峰
hello青峰
  • 发布:2017-10-27 17:07
  • 更新:2020-11-19 23:48
  • 阅读:11990

【原创】离线打包webapp模式,实现从任意原生app界面跳转到h5的指定页面

分类:5+ SDK

背景:离线webapp模式打包,利用插件可以实现h5与原生之间双向调用,但是仅仅是基于启动sdk的那个Activity或者是Controller,有时候需要在任何一个原生的界面都能够调用h5的指定的页面,经过反复研究、多次请教官方的技术人员,终于得以实现,数据共享、插件调用都没有问题。
[有不清楚的地方联系qq:852085282,不喜勿喷!]

实现思路:

  • 安卓: 新启动一个Activity,获取EntryProxy单例,动态修改为webview模式,根据指定的html页面路径,创建一个webview,添加到新的Activity上面。【注意在h5页面点击返回的时候,需要定制mui.back事件,调用plus.runtime.quit();来关闭这个Activity】

  • 苹果: 新启动一个UIViewController,根据指定的html页面路径,创建一个PDRCoreAppFrame视图,作为新UIViewController的subview.【注意:在h5页面返回的时候,需要通过插件的方式通知原生app去获取当前显示在最上层的UIViewController做出关闭动作】

具体代码:

  • 安卓:在需要的地方调用:
    Intent intent = new Intent( this, WebviewActivity.class);  
    String _url = "h5page.html";// 此处还可以在url里传递数据  
    intent.putExtra("url", _url);  
    this.startActivity(intent);

关键的部分就是那个WebviewActivity.java, 具体见下方代码。

  • 苹果:在需要的地方调用:
    H5WebviewController *vc = [[H5WebviewController alloc] init];  
    vc.page = @"userpage.html?userid=1000011";  
    [self presentViewController:vc animated: YES completion:nil];// 此处也可以push的方式

关键的部分就是那个H5WebviewController类, 具体见下方代码。

封装的2个原生界面代码:

WebviewActivity.java 如下:

public class WebviewActivity extends Activity {  
    IWebview webview = null;  
    EntryProxy mEntryProxy = null;  
    @Override  
    public void onCreate(Bundle savedInstanceState) {  
        super.onCreate(savedInstanceState);  
        requestWindowFeature(Window.FEATURE_NO_TITLE);  

        mEntryProxy = EntryProxy.getInstnace();  
        mEntryProxy.onCreate(this, savedInstanceState, SDK.IntegratedMode.WEBVIEW, null);  

        final FrameLayout rootView = new FrameLayout(this);  
        setContentView(rootView);  

        rootView.setBackgroundColor(0xffffffff);  
        rootView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {  
            @Override  
            public void onGlobalLayout() {  
                webview.onRootViewGlobalLayout(rootView);  
            }  
        });  

        // 设置单页面集成的appid  
        String appid = ""+System.currentTimeMillis();  
        // 单页面集成时要加载页面的路径,可以是本地文件路径也可以是网络路径  
        String _url = this.getIntent().getStringExtra("url");  
        String url = "file:///android_asset/apps/xxxx/www/dist/html/" + _url;  

        webview = SDK.createWebview(this, url, appid, new IWebviewStateListener() {  
            @Override  
            public Object onCallBack(int pType, Object pArgs) {  
                switch (pType) {  
                    case IWebviewStateListener.ON_WEBVIEW_READY:  
                        // 准备完毕之后添加webview到显示父View中,设置排版不显示状态,避免显示webview时,html内容排版错乱问题  
                        //((IWebview) pArgs).obtainFrameView().obtainMainView().setVisibility(View.INVISIBLE);  
                        SDK.attach(rootView, ((IWebview) pArgs));  
                        break;  
                    case IWebviewStateListener.ON_PAGE_STARTED:  
                        // 首页面开始加载事件  
                        break;  
                    case IWebviewStateListener.ON_PROGRESS_CHANGED:  
                        // 首页面加载进度变化  
                        break;  
                    case IWebviewStateListener.ON_PAGE_FINISHED:  
                        // 页面加载完毕,设置显示webview  
                       // webview.obtainFrameView().obtainMainView().setVisibility(View.VISIBLE);  
                        break;  
                }  
                return null;  
            }  
        });  
    }  

    @Override  
    public boolean onCreateOptionsMenu(Menu menu) {  
        return mEntryProxy.onActivityExecute(this,  
                ISysEventListener.SysEventType.onCreateOptionMenu, menu);  
    }  

    @Override  
    public void onPause() {  
        super.onPause();  
        mEntryProxy.onPause(this);  
    }  

    @Override  
    public void onResume() {  
        super.onResume();  
        mEntryProxy.onResume(this);  
    }  

    public void onNewIntent(Intent intent) {  
        super.onNewIntent(intent);  
        if (intent.getFlags() != 0x10600000) {// 非点击icon调用activity时才调用newintent事件  
            mEntryProxy.onNewIntent(this, intent);  
        }  
    }  

    @Override  
    protected void onDestroy() {  
        super.onDestroy();  
        mEntryProxy.destroy(this);  
    }  

    @Override  
    public boolean onKeyDown(int keyCode, KeyEvent event) {  
        boolean _ret = mEntryProxy.onActivityExecute(this,  
                ISysEventListener.SysEventType.onKeyDown, new Object[] { keyCode, event });  
        return _ret ? _ret : super.onKeyDown(keyCode, event);  
    }  

    @Override  
    public boolean onKeyUp(int keyCode, KeyEvent event) {  
        boolean _ret = mEntryProxy.onActivityExecute(this,  
                ISysEventListener.SysEventType.onKeyUp, new Object[] { keyCode, event });  
        return _ret ? _ret : super.onKeyUp(keyCode, event);  
    }  

    @Override  
    public boolean onKeyLongPress(int keyCode, KeyEvent event) {  
        boolean _ret = mEntryProxy.onActivityExecute(this,  
                ISysEventListener.SysEventType.onKeyLongPress, new Object[] { keyCode, event });  
        return _ret ? _ret : super.onKeyLongPress(keyCode, event);  
    }  

    public void onConfigurationChanged(Configuration newConfig) {  
        try {  
            int temp = this.getResources().getConfiguration().orientation;  
            if (mEntryProxy != null) {  
                mEntryProxy.onConfigurationChanged(this, temp);  
            }  
            super.onConfigurationChanged(newConfig);  

        } catch (Exception e) {  
            e.printStackTrace();  
        }  
    }  

    protected void onActivityResult(int requestCode, int resultCode, Intent data) {  
        mEntryProxy.onActivityExecute(this, ISysEventListener.SysEventType.onActivityResult,  
                new Object[] { requestCode, resultCode, data });  
    }  
}  
  • H5WebviewController类如下:
    
    > #define kStatusBarHeight 20.f  
    @interface H5WebviewController()  
    {  
    }  
    @end  
    @implementation H5WebviewController  
  • (void)loadView
    {
    [super loadView];
    // 获取PDRCore句柄
    PDRCore* pCoreHandle = [PDRCore Instance];
    if (pCoreHandle != nil)
    {
    // 设置Core启动方式
    // [pCoreHandle startAsWebClient];
    //[pCoreHandle start];

    // 设置拼写Webview将要打开文件的url  
    NSString* pFilePath = [NSString stringWithFormat:@"file://%@/%@%@", [NSBundle mainBundle].bundlePath, @"Pandora/apps/xxxxx/www/dist/html/", self.page];  
    
    CGRect StRect = CGRectMake(0, kStatusBarHeight, self.view.frame.size.width, self.view.frame.size.height - kStatusBarHeight);  
    
    // 使用时间戳来区分  
    NSString *webViewID = [NSString stringWithFormat:@"%ld", (long)[[NSDate date] timeIntervalSince1970]];  
    PDRCoreAppFrame *appFrame = [[PDRCoreAppFrame alloc] initWithName:webViewID loadURL:pFilePath frame:StRect];  
    
    // 设置webview的Appframe  
    [pCoreHandle.appManager.activeApp.appWindow registerFrame:appFrame];  
    
    // 将AppFrame设置为当前View的Subview  
    [self.view addSubview:appFrame];  

    }
    }
    @end

0 关注 分享

要回复文章请先登录注册

4***@qq.com

4***@qq.com

终于解决了,厉害
2020-11-19 23:48
j***@163.com

j***@163.com

webview.onRootViewGlobalLayout(rootView); 报错。。。。。
java.lang.NullPointerException: Attempt to invoke interface method 'void io.dcloud.common.DHInterface.IWebview.onRootViewGlobalLayout(android.view.View)' on a null object reference 请问什么原因啊
2020-09-09 16:01
1***@qq.com

1***@qq.com

传参的话要怎么携带在url后面加吗
2020-01-10 00:23
逞英雄

逞英雄

回复 4***@qq.com :
android的使用webview的js方法再次调用iwebview的方式可以实现,ios的暂时还没有找到方法
2020-01-06 11:12
6***@qq.com

6***@qq.com

跳转路径 file:///android_asset/apps/xxxx/www/dist/html/...... 这是固定格式吗 ? www目录下面没有dist 目录啊
2019-12-09 17:04
无言_25

无言_25

回复 3***@qq.com :
我也遇到这样的问题,请问问题解决了吗?
2019-09-24 10:07
3***@qq.com

3***@qq.com

Android从混合到原生,再到原生打开混合页面后,再返回到混合页面,物理返回键没用
2019-06-24 19:45
逞英雄

逞英雄

打开h5页面以后 android的mui.back有效 但是ios的有错误


ios 从原生利用H5WebviewController.h打开h5页面直接 直接出现js错误 undidied this.callbacks__e() 之类的
2019-06-06 14:51
hello青峰

hello青峰 (作者)

回复 4***@qq.com :
这是5+官方限制的
2018-12-14 10:19
7***@qq.com

7***@qq.com

回复 7***@qq.com :
[self.view addSubview:appFrame];
将上面这行换成下面的代码:
[pCoreHandle.appManager.activeApp.appWindow showFrame:appFrame];
亲测有效
2018-12-05 17:45