Android-应用被作为第三方浏览器打开

2020-02-14 20:08:17

参考地址 Android-应用被作为第三方浏览器打开

前言

微信里的文章页面,可以选择“在浏览器打开”。现在很多应用都内嵌了WebView,那是否可以使自己的应用作为第三方浏览器打开此文章呢?
如图:

  • 微信打开三方浏览器.png

就像图中这样,让自己的应用出现在列表里。
这篇文章就是为了实现这个功能。

项目代码地址:WebViewStudy

正文

实现其实很简单:
在Manifest文件中,给想要接收跳转的Activity添加<intent-filter>配置:

 <activity
      android:name=".WebViewActivity"
      android:configChanges="orientation|screenSize"
      android:hardwareAccelerated="true"
      android:launchMode="singleTask"
      android:screenOrientation="portrait"
      android:theme="@style/WebViewTheme">

      <!--需要添加下面的intent-filter配置-->
      <intent-filter tools:ignore="AppLinkUrlError">
          <action android:name="android.intent.action.VIEW" />

          <category android:name="android.intent.category.DEFAULT" />
          <category android:name="android.intent.category.BROWSABLE" />
          <!--使用http,则只能打开http开头的网页-->
          <data android:scheme="https" />
      </intent-filter>

  </activity>

然后在 WebViewActivity 中获取相关传递数据:

public class WebViewActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_web_view);
        getIntentData();
        initTitle();
        initWebView();
        webView.loadUrl(mUrl);
       // 处理 作为三方浏览器打开传过来的值
        getDataFromBrowser(getIntent());
    }

   /**
     * 使用singleTask启动模式的Activity在系统中只会存在一个实例。
     * 如果这个实例已经存在,intent就会通过onNewIntent传递到这个Activity。
     * 否则新的Activity实例被创建。
     */
    @Override
    protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);
        getDataFromBrowser(intent);
    }

    /**
     * 作为三方浏览器打开传过来的值
     * Scheme: https
     * host: www.jianshu.com
     * path: /p/1cbaf784c29c
     * url = scheme + "://" + host + path;
     */
    private void getDataFromBrowser(Intent intent) {
        Uri data = intent.getData();
        if (data != null) {
            try {
                String scheme = data.getScheme();
                String host = data.getHost();
                String path = data.getPath();
                String text = "Scheme: " + scheme + "\n" + "host: " + host + "\n" + "path: " + path;
                Log.e("data", text);
                String url = scheme + "://" + host + path;
                webView.loadUrl(url);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

以上是核心代码,有几点需要说明的:

  • 1、设置启动模式:launchMode="singleTask"

  • 2、getDataFromBrowser()方法会在onCreateonNewIntent方法中调用。

解释:

在实际使用中,有这样的场景:
我们在微信中“通过浏览器”打开自己的应用,然后将自己的应用切到后台。重复上面的操作,会一直创建应用的实例,这样肯定是不好的,为了避免这种情况我们设置启动模式为:launchMode="singleTask"

使用singleTask启动模式的Activity在系统中只会存在一个实例。
如果这个实例不存在,新的Activity实例被创建。
如果这个实例已经存在,那么在Activity回退栈中,所有位于该Activity上面的Activity实例都将被销毁掉(销毁过程会调用Activity生命周期回调),这样使得singleTask Activity实例位于栈顶。与此同时,Intent会通过onNewIntent传递到这个SingleTask Activity实例。 - <深入讲解Android中Activity launchMode>

这就是为什么要在onNewIntent中调用的原因,当此Activity已存在时,值会通过onNewIntent传递过来。

继续拓展

也许大家用知乎进行过类似的操作,会发现有这样一个效果:
当知乎没有开启时,在其他应用打开知乎后,关闭页面会回到知乎的主页面。正常是不会有出现这样的情况的,我们需要简单设置一下。

1、在主页面设置静态变量,初始化时改变静态变量的值

public class MainActivity extends AppCompatActivity  {

    // 是否开启了主页,没有开启则会返回主页
    public static boolean isLaunch = false;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        initView();
        isLaunch = true;
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        isLaunch = false;
    }

2、当WebViewActivity关闭时判断是否打开主页面

    /**
     * 直接通过三方浏览器打开时,回退到首页
     */
    public void handleFinish() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            finishAfterTransition();
        } else {
            finish();
        }
        if (!MainActivity.isLaunch) {
            MainActivity.start(this);
        }
    }

结语

其实这相当于Activity隐式跳转,其中点击网页中的电话跳转到手机的拨号盘也是这样的原理,DeepLink也基本是这个逻辑。

设想这样一种情况:
我们通过浏览器拉起自己的应用,不一定要打开WebView,也可以打开原生的页面,只需要传过来的数据里有此页面想要的数据即可。其实很多应用都这样做了。



  • 2019-09-03 23:19:12

    ./configure 的配置和用法

    Linux环境下的软件安装,并不是一件容易的事情;如果通过源代码编译后在安装,当然事情就更为复杂一些;现在安装各种软件的教程都非常普遍;但万变不离其中,对基础知识的扎实掌握,安装各种软件的问题就迎刃而解了。Configure脚本配置工具就是基础之一,它是autoconf的工具的基本应用。

  • 2019-09-04 16:24:17

    Ubuntu apt-get更换为阿里源

    ​进入阿里巴巴开源镜像页面,找到ubuntu,点击后面的帮助,可以看到类似下面的介绍,加入就好。切记下面的第三步。

  • 2019-09-04 16:32:56

    Ubuntu tar 解压缩命令详解

    tar 解压缩命令详解,这五个是独立的命令,压缩解压都要用到其中一个,可以和别的命令连用但只能用其中一个。下面的参数是根据需要在压缩或解压档案时可选的。

  • 2019-09-04 16:50:35

    CMake入门笔记

    Make是一个跨平台的安装(编译)工具,可以用简单的语句来描述所有平台的安装(编译过程)。他能够输出各种各样的makefile或者project文件,能测试编译器所支持的C++特性,类似UNIX下的automake。只是 CMake 的组态档取名为 CMakeLists.txt。Cmake 并不直接建构出最终的软件,而是产生标准的建构档(如 Unix 的 Makefile 或 Windows Visual C++ 的 projects/workspaces),然后再依一般的建构方式使用。这使得熟悉某个集成开发环境(IDE)的开发者可以用标准的方式建构他的软件,这种可以使用各平台的原生建构系统的能力是 CMake 和 SCons 等其他类似系统的区别之处。

  • 2019-09-05 20:51:15

    在Android上使用FFmpeg压缩视频

    libavcodec-提供了更加全面的编解码实现的合集 libavformat-提供了更加全面的音视频容器格式的封装和解析以及所支持的协议 libavutil-提供了一些公共函数 libavfilter-提供音视频的过滤器,如视频加水印、音频变声等 libavdevice-提供支持众多设备数据的输入与输出,如读取摄像头数据、屏幕录制 libswresample,libavresample-提供音频的重采样工具 libswscale-提供对视频图像进行色彩转换、缩放以及像素格式转换,如图像的YUV转换 libpostproc-多媒体后处理器

  • 2019-09-05 20:54:21

    在Android 中使用FFmpeg命令

    到这里就可以运行FFmpeg命令了。一直我也是这样使用,但是我在做这个项目Cut的时候发现连续调用多次FFmpeg命令会报错(在项目需要,先改变分镜头的速度,再合成视频)。 为什么会这样的呢?

  • 2019-09-06 10:30:20

    ffmpeg错误码

    AVERROR_BSF_NOT_FOUND = -1179861752 AVERROR_BUG = -558323010 AVERROR_DECODER_NOT_FOUND = -1128613112 AVERROR_DEMUXER_NOT_FOUND = -1296385272 AVERROR_ENCODER_NOT_FOUND = -1129203192 AVERROR_EOF = -541478725 AVERROR_EXIT = -1414092869 AVERROR_FILTER_NOT_FOUND = -1279870712 AVERROR_INVALIDDATA = -1094995529 AVERROR_MUXER_NOT_FOUND = -1481985528 AVERROR_OPTION_NOT_FOUND = -1414549496 AVERROR_PATCHWELCOME = -1163346256 AVERROR_PROTOCOL_NOT_FOUND = -1330794744 AVERROR_STREAM_NOT_FOUND = -1381258232 AVERROR_BUG2 = -541545794 AVERROR_UNKNOWN = -1313558101