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

       在 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 文件

iOS、Android外部启动应用,实现应用跳转_第1张图片

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

iOS、Android外部启动应用,实现应用跳转_第2张图片

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


iOS、Android外部启动应用,实现应用跳转_第3张图片


       这是浏览器中输入上面链接后的提示信息。下面开始讲解代码部分了,我们这个功能如果仅仅是为了打开 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 中添加下面内容:
  
      
     
     
     
  

       添加之后,在你的主 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 两个平台上从外部打开应用。


你可能感兴趣的:(游戏开发,iOS,cocos,Crearor,Android)