iOS、Android外部启动应用,实现应用跳转

来源:互联网 发布:农村淘宝官网首页 编辑:程序博客网 时间:2024/05/17 08:58

       在 iOS 和 Android 开发中,常常会用到应用跳转,例如,我们分享了一个链接给其他人,这个时候,别人进入链接,点击某个按钮,就直接打开我们应用, 在 iOS 和 Android 中都可以通过 scheme 的方式打开。其实类似的文章有很多, iOS 的话,可以直接搜索“URL scheme”就能够找到相关的内容, Android 的话,也可以直接搜索 Android外部调起activity”就能找到很多相关的博客,,博主在这里只是将两者综合起来,进行总结,同时,对于 Android 还有部分内容进行详细讲解。 Android 相关的方法比较多,为了方便开发,这里都使用scheme的方式来实现。这里将之前用到了部分博客放在这里,方便其他人直接使用。
       iOS 的 URL scheme
       Android通过浏览器打开应用
       Activity的四种启动模式和onNewIntent()
       为了防止博文链接失效(之前有一篇的链接失效了,好伤心快哭了),博主在这里还是要将内容重新写一遍。
       首先是 iOS 的:
       创建自己的 iOS 项目,这里项目名字设置为 TestApp ,然后,打开 info.plist 文件



       然后,如图所示,添加一个属性URL Types,此时,在对应的item0下面的URL identifier字段设置一个 value 值,这里设置为 com.example.TestApp ,推荐使用域名翻转的方式来填写这个值。然后,在下面添加一个新的字段,也就是本文的重点 URL scheme ,这个 URL scheme 也是一个 dictionary 类型的值,所以,在它的 item0 字段对应的 value 上面填写自己的 App 信息,由于当前项目名为 TestApp ,所以博主为了方便,也填写为 TestApp ,其实填成什么都是可以的,下面截图显示:


       这样,就完成了基本的配置,此时,在手机上运行,然后,在切入后台,打开自己的 Safari ,输入连接连接,格式如下 TestApp:// 然后点击前往,这时,给出弹窗,然后点击打开,就打开了自己的 App 。其实,只要是以这种方式开头的链接,就都能打开应用,后面可以拼接任意字符。



       这是浏览器中输入上面链接后的提示信息。下面开始讲解代码部分了,我们这个功能如果仅仅是为了打开 App 这么简单,那么,到这里其实就结束了,但是如果为了传参数,就不是这么轻松了。我们在 AppDelegate.m 中添加如下代理方法:
- (BOOL)application:(UIApplication *)application   handleOpenURL:(NSURL *)url {      return true;  }    - (BOOL)application:(UIApplication *)application openURL:(NSURL *)url   sourceApplication:(NSString *)sourceApplication annotation:(id)annotation{      return true;  }  

       其实我并没有用到第一个方法,只是在第二个方法中才进行了相关的数据处理操作。当从浏览器中打开该应用的时候,之前输入的网址,也就是 TestApp:// 就会被传过来,没错,就是上面这个 url ,由于我们是从 Safari 中打开的,所以, Safari 也会被传过来,就是这个 sourceApplication 字段,传过来的参数是 sourceApplication ,内容是 com.apple.mobilesafari ,也就是类似我们上面设置好的 URL identifier 字段。好了,到这里,我们已经知道可以获取到 url 了,那么,我们应该也是可以传参数过来的。就像我们进行 get 请求一样,后面直接拼参数。例如,我们在一个论坛中看到一篇好的帖子,向分享给朋友,作为唯一标记,每个帖子都会有自己的唯一 id ,那么,我们在分享的时候,只要将帖子 id 也发出去,那么,当好友访问的时候,只需要传递 TestApp://id=12345 这样的参数,那么我们读取出这个参数,然后根据 id ,发送网络请求,获取到帖子信息,展示给用户。既然我们获取到了 url ,那么,我们接下来的操作,就是 url 解析了。我们通过 [url query] 方法获取到参数为 id=12345 ,当然,如果有多个参数的话,就会变成 id=12345&type=article 这种格式,剩下的就是解析了,这个就自行百度怎么解析了。其次,为了保证 iOS 和 Android 平台保持一致,所以这个 scheme 的格式并不是这么简单的,这个后面会讲到,当然,就算格式变得复杂了,上面的方法解析出来的参数也是一样的。
       下面,进行 Android 部分的讲解:
       Android 应用跳转其实有好多种方式,其中也有一种方式是通过 URL Scheme 来跳转的,为了保持 iOS 和 Android 的统一,这里都是用 scheme 方式来实现。因为在实际开发中,会碰到这样一个问题,用户的设备可能是 iOS 和 Android 两种类型, Android 如果不用这种方式分享,而用别的方式,会导致 iOS 无法打开应用,同时,如果 iOS 分享给了 Android ,由于解析方式不同,会造成无法解析 iOS 的分享信息。为了方便处理,这里都使用 scheme 来进行跳转。首先,打开 manifest 文件,在自己的主 activity 中添加下面内容:
<intent-filter>      <action android:name="android.intent.action.VIEW" />     <category android:name="android.intent.category.BROWSABLE" />     <category android:name="android.intent.category.DEFAULT" />     <data android:scheme="TestApp" android:host="www.example.com" android:pathPrefix="/TestScheme"/>  </intent-filter>  

       添加之后,在你的主 activity 中就产生了2个 intent-filter ,注意,上面的内容一定不要添加在已经存在的那个 intent-filter 上面,否则会造成没有应用启动 icon 的问题。下面对参数进行讲解。 android:scheme 当然就是表示当前应用的 scheme ,和 iOS 的 URL Scheme 是一样的,然后是这个 host ,当外部启动当前应用的时候, scheme 后面的字段要和这个字段一样才行,例如 TestApp://www.example.com 才行。后面的 pathPrefix 是拼接在 host 后面的,也就是说访问这个应用的时候,链接的格式会是 TestApp://www.example.com/TestScheme/ 这种,如果要带参数,可以在后面添加,例如上面例子中的 iOS 的那个 id ,就可以添加在后面,此外,还可以添加多个参数,多个参数用&来连接,和网址是一样的, TestApp://www.example.com/TestScheme/id=12345&type=article 这种格式就可以,为了保持一致,在上面的 iOS 的例子中,最好也是这种格式,然后进行相关的解析。然后,假设你的主 activity 的名字为 MainActivity ,那么,就在 onCreate 方法中进行相关的参数解析:

Intent i_getvalue = getIntent();  String action = i_getvalue.getAction();  if (Intent.ACTION_VIEW.equals(action)) {      Uri uri = i_getvalue.getData();      if (uri != null) {          String id = uri.getQueryParameter("id");          String type= uri.getQueryParameter("type");      }  }  

       这样,我们就将参数取出来了。然而,如果这样就结束了,我也没必要写这篇博客了,因为,只写到这里会有问题,下面对问题进行详细讲解。
       首先,当我们要从外部打开应用的时候,会出现以下2种情况:
       1.自己还没打开当前应用;
       2.当前应用已经打开。

       那么问题来了,默认情况下,每次从外部打开该应用的时候,都会重新启动一个新的 activity ,然后压入栈中,那如过多次从外部打开,就会产生多个相同的当前页面。如果是普通的应用还好,创建就创建了,但是,如果是游戏的话,每次创建,会崩溃的,当然,如果应用还没打开,并不会有什么大问题,如果是已经打开,就一定会崩溃了。因为游戏底层使用 C++ 实现的,而且,底层调用了 OpenGL ,每次创建,一定会出问题,崩溃是必然的。那么为了防止每次创建,我们就用到了一个 activity 启动模式,也就是 singleTask 模式,配置该模式,只需要在 activity 中添加如下属性:

android:launchMode="singleTask"  

       如果在栈中,已经存在了该 activity ,如果该 activity 在栈顶,就直接调用,如果不在,就将该 activity 上面的 activity 全部弹出。这样就防止了崩溃的产生,其实使用 singleInstance 模式应该也是可以的,只要保证只用到一个 activity 就行。然后,问题又来了,既然这里一直在使用同一个 activity ,那么,也就是说,我们只创建了一个 activity ,也就是说我们只调用了一次 onCreate 方法,那么,以后再次调用的时候,我们就无法从 onCreate 中获取到参数了。那么该怎么解决这个问题呢?其实,这里还有另外一个方法,就是 onNewIntent() , activity 第一次启动的时候,调用的流程是 onCreate->onStart->onResume ,设置了 singleTask 后,除第一次启动,其他的流程都是 onNewIntent->onRestart->onStart->onResume ,所以,我们可以从在 onNewIntent 中获取到 intent ,但是,有一个问题,就是我们在 onCreate 可以直接操作 intent ,并获取参数,但是,我们在 onNewIntent 中是无法直接从 intent 读取参数的,因此,我们要在 onNewIntent 中调用一个 activity 自带的 setIntent() 方法:


@Override  protected void onNewIntent(Intent intent) {      super.onNewIntent(intent);      SDKWrapper.getInstance().onNewIntent(intent);      setIntent(intent);  }  


       然后,在 onResume 中通过 getIntent() 方法来获取刚刚的 intent ,然后进行相应的操作。这里也有一个问题出现了,当我们应用进入后台后,如果再次切换回来后,每次都会调用 onResume 方法。这时,如果我们不在每次用完这个 intent 之后,将其清空,那么下次从后台切换回来,还会调用这个方法,这并不是我们期待的结果,因此,我们在对 intent 进行操作之后,要每次将其清空,这样,就不会出现这样的问题了。到这里,就完成了 iOS 和 Android 两个平台上从外部打开应用。


1 0
原创粉丝点击