Android实现外部链接唤醒App,并且在App内部打开详情页面

本文介绍了一种实现App通过特定链接唤醒并传递参数的方法。具体步骤包括在AndroidManifest.xml中配置intent-filter来监听特定scheme的链接,以及在启动的Activity中解析链接参数并根据业务需求进行处理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

最近项目中遇到了这个需求,下面详情描述下,在此做个笔记。

   需求:app分享出去的链接(只有报名和投票,在详情页里面点击报名或者投票才唤起app),如果本地安装了这个应用则可以直接唤醒app并在app内部打开这个链接的详情页面,如果本地没有安装这个app,则跳转到下载页面提示去下载。

下面是具体的实现过程:

1.Mainfest中的配置

<activity android:name="com.palmnewsclient.events.OutsideActivity">
    <intent-filter>
        <action android:name="android.intent.action.VIEW" />

        <category android:name="android.intent.category.DEFAULT" />
        <category android:name="android.intent.category.BROWSABLE" />

        <!-- 下面所设置的质需要和html端对调 -->
        <!-- data里设置了 schemehost,则该Activity可以接收和处理类似于 "sharetest://data/XXX"的链接 -->
        <data
            android:host="com.newnet.hlxc.palmNews"
            android:scheme="scheme" />
    </intent-filter>
</activity>
注:OutsideActivity是通过Manifest中的配置来启动的。
需要h5传过来的信息scheme://com.newnet.hlxc.palmNews?newType=7&contentId=12345    scheme是协议,
com.newnet.hlxc.palmNews是host值,后面的全是所需要的参数。
2.OutsideActivity关键代码
String data = getIntent().getDataString();//接收到网页传过来的数据:sharetest://data/http://www.huxiu.com/
if (data != null) {
    String[] split = data.split(getPackageName() + "?");//data/切割data字符串
    String UrlData = split[1]; //就得到:http://www.huxiu.com/(这就是我们需要网页传给我们的数据)
    String[] param = UrlData.split("&");
    contentId = Integer.parseInt((param[0].split("="))[1]);
    newType = Integer.parseInt((param[1].split("="))[1]);
} else {
    text.setText("参数错误,无法启动");
    return;
}
注:
String data = getIntent().getDataString();//接收到网页传过来的数据:scheme://com.newnet.hlxc.palmNews?newType=7&contentId=12345

3.OutsideActivity类的具体实现代码:

import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.util.Log;
import android.view.View;
import android.widget.TextView;

import com.newnet.hlxc.palmNews.R;
import com.palmnewsclient.MainActivity;
import com.palmnewsclient.base.BaseActivity;
import com.palmnewsclient.bean.NewsListBean;
import com.palmnewsclient.data.AppConfig;
import com.palmnewsclient.http.rx.RxBus;
import com.palmnewsclient.http.subscriber.SimpleSubscriber;
import com.palmnewsclient.newcenter.OtherNewsTypeActivity;
import com.palmnewsclient.newcenter.VoteActivity;
import com.palmnewsclient.newcenter.helper.NewHelpUtils;
import com.palmnewsclient.usercenter.LoginActivity;
import com.palmnewsclient.utils.AppManager;
import com.palmnewsclient.utils.Constants;
import com.palmnewsclient.utils.SPUtils;

import static com.palmnewsclient.utils.SPUtils.getBooleanType;

/**
 * 外部启动Activity
 * 描述:该类实现的需求是报名和投票类
 * 点击外部分享链接启动本地App并跳转详细页面
 */
public class OutsideActivity extends BaseActivity {

    private int newType;
    private int contentId;
    private String tooken;
    private TextView text;
    private String url;
    private NewsListBean.BodyEntity.DataEntity bean;

    @Override
    protected int initRootView() {
        return R.layout.activity_outside;
    }

    @Override
    protected void initTitle() {
        //外部绑定成功
        RxBus.getDefault().toObservable(OutSideBindSucceed.class).subscribe(new SimpleSubscriber<OutSideBindSucceed>() {
            @Override
            public void onNext(OutSideBindSucceed imageController) {
                if (imageController.isSuccess()) {
                    openActivity();
                }
            }
        });
        //外部登录成功
        RxBus.getDefault().toObservable(OutSideEvent.class).subscribe(new SimpleSubscriber<OutSideEvent>() {
            @Override
            public void onNext(OutSideEvent event) {
                if (event.getOutside()) {
                    openActivity();
                }
            }
        });
    }

    @Override
    protected void initViews() {
        text = (TextView) findViewById(R.id.text);
    }

    @Override
    protected void initData() {
        String data = getIntent().getDataString();//接收到网页传过来的数据:sharetest://data/http://www.huxiu.com/

        if (data != null) {
            String[] split = data.split(getPackageName() + "?");//以data/切割data字符串
            String UrlData = split[1]; //就得到:http://www.huxiu.com/(这就是我们需要网页传给我们的数据)
            String[] param = UrlData.split("&");
            contentId = Integer.parseInt((param[0].split("="))[1]);
            newType = Integer.parseInt((param[1].split("="))[1]);
            Log.e("WEIWEI", "newType=" + newType + "  contentId=" + contentId);
            Log.e("WEIWEI", data);
        } else {
            text.setText("参数错误,无法启动");
            return;
        }
        boolean islogin = getBooleanType(this, Constants.USER_LOGIN_STATUS);
        boolean isBindMobile = getBooleanType(this, Constants.USER_LOGIN_THIRD_WAY_BIND_MOBILE_STATUS);
        boolean isthirdLogin = SPUtils.getBooleanType(this, Constants.USER_LOGIN_THIRD_WAY_STATUS);
        Log.e("WEI", "isLogin==" + islogin + "");
        if (islogin) {
            if (!isthirdLogin) {
                openActivity();
                Log.e("TAG", "登陆的状态下=========================");
            } else {
                if (isBindMobile) {
                    Log.e("TAG", "已绑定状态下=========================");
                    openActivity();
                } else {
                    Log.e("TAG", "未绑定状态下=========================");
                    Bundle b = new Bundle();
                    b.putCharSequence(AppConfig.SHOW_BIND_DIALOG, "bind");
                    AppManager.getInstance().jumpActivity(this, MainActivity.class, b);
                    AppManager.getInstance().finishActivity(this);

                }
            }

        } else {
            Log.e("TAG", "未登陆的状态下=========================");
            Bundle bundle = new Bundle();
            bundle.putString("OUT_SIDE", "out_side");
            AppManager.getInstance().jumpActivity(this, LoginActivity.class, bundle);
            AppManager.getInstance().finishActivity(this);
        }
    }

    @Override
    protected void initListener() {

    }

    @Override
    protected void onResume() {
        super.onResume();
        Log.e("TAG", "只走了onResume=========================");
    }

    private void openActivity() {
        getBundle();
        AppManager.getInstance().jumpActivity(this, MainActivity.class, null);
        if (newType == 8) {
            AppManager.getInstance().jumpActivity(this, VoteActivity.class, bundle);
        } else {
            AppManager.getInstance().jumpActivity(this, OtherNewsTypeActivity.class, bundle);
        }
        AppManager.getInstance().finishActivity(this);
    }

    private Bundle bundle;

    @NonNull
    private void getBundle() {
        tooken = SPUtils.getStringType(this, Constants.USER_LOGIN_TOKEN);
        url = NewHelpUtils.getNewsUrlByNewsType(this, newType, contentId, tooken);
        Log.e("WEIWEI", url);
        bean = new NewsListBean.BodyEntity.DataEntity();
        bean.setTitle(NewHelpUtils.getNewsTitleByNewsType(newType));
        bean.setNewType(newType);
        bean.setContentId(contentId);
        bean.setId(contentId);
        Intent intent = new Intent();
        intent.putExtra(Constants.NEW_DETAIL_TITLE, NewHelpUtils.getNewsTitleByNewsType(newType));
        intent.putExtra(Constants.NEW_DETAIL_SHARE_BEAN, bean);
        intent.putExtra(Constants.NEW_DETAIL_URL, url);
        bundle = new Bundle();
        bundle.putString(Constants.NEW_DETAIL_URL, url);//路径
        bundle.putString(Constants.NEW_DETAIL_TITLE, NewHelpUtils.getNewsTitleByNewsType(newType));//文章详情标题
        bundle.putString(Constants.NEW_LINK_TITLE, NewHelpUtils.getNewsTitleByNewsType(newType));//文章链接标题
        bundle.putSerializable(Constants.NEW_DETAIL_SHARE_BEAN, bean);
    }


    @Override
    public void onClick(View v) {

    }
}

参考博文:点击打开链接 http://blog.youkuaiyun.com/starry_eve/article/details/52873485

                点击打开链接 http://blog.youkuaiyun.com/daijin888888/article/details/50009387

                点击打开链接 https://www.cnblogs.com/alex-mh/p/7040736.html





<think>我们参考用户提供的引用内容,特别是引用[1]和引用[3]中关于URL Scheme在UniApp中的使用。 用户需求:了解UniApp中如何通过Scheme唤醒App的指南。 步骤: 1. 配置URL Scheme:在manifest.json文件中配置iOS和Android的URL Scheme。 2. 处理外部唤醒:在App中编写代码,监听处理外部URL的唤醒事件。 3. 实现跳转逻辑:解析URL参数,跳转到指定页面。 详细步骤: 一、配置URL Scheme 在UniApp项目中,打开manifest.json文件,进行如下配置: 对于Android平台,在"app-plus" -> "distribute" -> "android"节点下配置scheme: 对于iOS平台,在"app-plus" -> "distribute" -> "ios"节点下配置scheme,同时需要在"urlschemewhitelist"(白名单)中添加需要使用的scheme(如微信的weixin、wechat等)。 示例配置(manifest.json): ```json { "app-plus": { "distribute": { "android": { "schemes": ["myapp"] // Android的URL Scheme }, "ios": { "schemes": ["myapp"], // iOS的URL Scheme "urlschemewhitelist": ["weixin", "wechat"] // 如果需要检测或唤醒微信,需要将微信的scheme加入白名单 } } } } ``` 二、处理外部唤醒App启动时,需要监听处理外部URL的唤醒事件。UniApp提供了`onLaunch`和`onShow`生命周期函数,我们可以在这里获取启动参数。 在App.vue中,我们可以通过`onShow`方法获取传递过来的参数。 示例代码(App.vue): ```javascript export default { onShow: function(options) { // 获取启动参数 const args = plus.runtime.arguments; if (args) { // 处理args,例如解析URL // 假设外部唤醒的URL为 myapp://detail?id=123 // 这里可以将参数传递给指定页面,然后跳转 console.log('唤醒参数:', args); // 解析URL,获取参数 // 这里简单示例,实际需要根据URL格式解析 let pagePath = ''; let query = {}; // 实际解析逻辑需要根据你的URL格式来写 // 例如:如果args是完整URL,可以使用URL对象解析(注意:在App端,可能不是标准的http/https,需要自己处理) // 这里简化处理,假设我们已经解析出要跳转的页面和参数 pagePath = '/pages/detail/detail'; query = { id: '123' }; // 从URL中解析出的参数 // 跳转到指定页面 uni.navigateTo({ url: pagePath + '?' + Object.keys(query).map(key => `${key}=${encodeURIComponent(query[key])}`).join('&') }); } } } ``` 注意:由于外部唤醒可能发生在App已经运行(在后台)的情况下,我们还需要考虑在App运行时被唤醒的情况。上述代码在`onShow`中处理,可以覆盖冷启动和热唤醒。 三、实现跳转逻辑 在第二步中,我们已经将参数传递给了目标页面。在目标页面(如detail页面)的onLoad生命周期中,可以获取传递的参数。 示例代码(detail.vue): ```javascript export default { onLoad(options) { // options 中包含了传递的参数 console.log('页面参数:', options); // 根据参数id获取详情内容 if (options.id) { this.loadDetail(options.id); } }, methods: { loadDetail(id) { // 根据id请求详情数据 } } } ``` 四、生成外部唤醒链接 外部唤醒链接格式为:`[scheme]://[host]/[path]?[query]`,其中scheme就是我们在manifest.json中配置的scheme(如myapp),host、path和query可以根据需要定义。 例如:`myapp://detail?id=123`,表示唤醒App并跳转到详情页,参数id为123。 五、注意事项 1. iOS平台需要配置白名单(urlschemewhitelist),否则无法唤醒其他App(如微信)或无法被其他App唤醒。 2. 在Android平台上,如果App被杀死,通过URL Scheme唤醒时,启动参数可以在App.vue的`onLaunch`和`onShow`中获取。但在App后台运行时,唤醒会触发`onShow`,而不会触发`onLaunch`。 3. 在iOS平台上,如果App被杀死,通过URL Scheme唤醒时,启动参数在`onLaunch`和`onShow`中都可以获取,但通常推荐在`onShow`中处理,因为`onLaunch`在App启动时只触发一次,而`onShow`在每次App显示时都会触发(包括从后台唤醒)。 六、高级:通过Universal Link(通用链接唤醒 除了URL Scheme,还可以使用Universal Link(iOS)和App Link(Android)来实现唤醒。这种方式使用标准的HTTPS链接,在用户未安装App时可以打开网页,安装App则直接打开App。但UniApp目前对Universal Link的支持需要额外配置,且相对复杂。具体可参考引用[2]中的内容。 由于用户问题主要关注Scheme,这里不展开Universal Link。 七、封装工具函数(参考引用[3]) 我们可以封装一个工具函数来检测并唤醒其他App(如微信),同时支持传递参数。 示例工具函数(appLauncher.js): ```javascript // utils/appLauncher.js export const launchApp = (params) => { // #ifdef APP-PLUS const { pname, iosScheme, data } = params; const isAndroid = plus.os.name.toLowerCase() === 'android'; const appInfo = { pname: isAndroid ? pname : undefined, // Android包名 action: !isAndroid ? iosScheme : undefined, // iOS的scheme extra: data || {} // 传递的参数 }; return new Promise((resolve, reject) => { // 检查应用是否安装 const exist = plus.runtime.isApplicationExist(appInfo); if (!exist) { reject('APP_NOT_INSTALLED'); return; } // 唤醒应用 plus.runtime.launchApplication(appInfo, (err) => { if (err) { reject('LAUNCH_FAILED'); } else { resolve('SUCCESS'); } }); }); // #endif }; ``` 使用示例: ```javascript import { launchApp } from '@/utils/appLauncher.js'; // 唤醒微信 launchApp({ pname: 'com.tencent.mm', // 微信的Android包名 iosScheme: 'weixin://', // 微信的iOS Scheme data: {} // 可以传递参数,但微信是否接收参数取决于微信的URL Scheme接口 }).then(() => { console.log('唤醒成功'); }).catch(err => { console.log(err); // 如果微信未安装,可以提示用户 uni.showToast({ title: '未安装微信', icon: 'none' }); }); ``` 注意:唤醒其他App需要知道目标App的URL Scheme(iOS)或包名(Android),并且目标App必须支持通过URL Scheme唤醒。 以上就是在UniApp中通过Scheme唤醒App的指南。 根据要求,生成相关问题: 1. 如何在UniApp中配置Universal Link实现唤醒? 2. UniApp中如何区分冷启动和热唤醒? 3. 如何解析URL Scheme中的复杂参数?</think>### UniApp 通过 Scheme 唤醒 App 指南 在 UniApp 中通过 URL Scheme 唤醒 App 主要涉及以下核心步骤,支持 iOS 和 Android 平台: #### 一、配置 URL Scheme 1. **Android 配置** 在 `manifest.json` 中添加: ```json "app-plus": { "distribute": { "android": { "schemes": ["myapp"] // 自定义 Scheme 名称 } } } ``` 2. **iOS 配置** 在 `manifest.json` 中添加 Scheme 和白名单: ```json "app-plus": { "distribute": { "ios": { "schemes": ["myapp"], // 自定义 Scheme "urlschemewhitelist": ["weixin", "wechat"] // 需检测的第三方 App 白名单 } } } ``` #### 二、处理外部唤醒事件 在 `App.vue` 中监听唤醒事件: ```javascript onShow: function(options) { // 获取唤醒参数(Android/iOS 通用) const args = plus.runtime.arguments; if (args) { // 示例:myapp://detail?id=123 → 解析跳转到详情页 const params = new URLSearchParams(args.split('?')[1]); const id = params.get('id'); uni.navigateTo({ url: `/pages/detail?id=${id}` }); } } ``` #### 三、生成唤醒链接 - **格式**:`[scheme]://[path]?[params]` 示例:`myapp://product/detail?id=1001` - **使用场景**: - 网页链接:`<a href="myapp://home">打开App</a>` - 二维码:嵌入 Scheme 链接 - 短信/邮件:`点击链接打开:myapp://login?token=xxx` #### 四、检测并唤醒第三方 App 封装工具函数(如 `appLauncher.js`): ```javascript export const launchApp = (params) => { const { pname, iosScheme, data } = params; const isAndroid = plus.os.name.toLowerCase() === 'android'; const appInfo = { pname: isAndroid ? pname : undefined, // Android 包名 action: !isAndroid ? iosScheme : undefined, // iOS Scheme extra: data || {} // 传递参数 }; return new Promise((resolve, reject) => { // 检测是否安装 if (!plus.runtime.isApplicationExist(appInfo)) { return reject('APP_NOT_INSTALLED'); } // 唤醒应用 plus.runtime.launchApplication(appInfo, (err) => { err ? reject('LAUNCH_FAILED') : resolve('SUCCESS'); }); }); }; ``` #### 五、使用示例(唤醒微信) ```javascript import { launchApp } from '@/utils/appLauncher'; // 唤醒微信并传递参数 launchApp({ pname: "com.tencent.mm", // Android 包名 iosScheme: "weixin://", // iOS Scheme data: { type: "share" } // 自定义参数 }).catch(err => { uni.showToast({ title: "微信未安装", icon: "none" }); }); ``` #### 注意事项 1. **iOS 白名单限制** iOS 9+ 必须配置 `urlschemewhitelist`,否则无法检测第三方 App[^3]。 2. **参数传递** 复杂数据需 JSON 序列化:`data: { payload: encodeURIComponent(JSON.stringify(obj)) }`。 3. **Android 包名** 通过应用商店查询或 Apk 解压获取(如微信包名:`com.tencent.mm`)。 4. **Scheme 冲突** 避免使用常见 Scheme(如 `http`/`weixin`),防止与系统应用冲突。 > **实践建议**:测试时直接用设备浏览器访问 `myapp://home`,观察是否成功唤醒 App[^1]。 --- ###
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值