发送手机物理标识请求

标签: 手机 物理 标识 | 发表时间:2015-12-13 14:59 | 作者:u012515223
出处:http://blog.csdn.net

作为应用的重要关注指标-激活, 需要在每次启动时, 都上传手机的物理标识到服务器. 我来简述一下需要上传的信息.

Android

1. 获取

激活信息主要包含:
1. AppId: 公司拥有多款应用, 标示本应用的类型.
2. Platform: 平台Android或者iOS.
3. SystemVersion: 在Android中, 代表Android版本号.
4. Version: 本应用的版本.
5. AppVersion: 本应用的服务器接口版本.
6. IMEI(International Mobile Equipment Identity): 国际移动设备标识, 手机身份.
7. DeviceId: 设备标示, 一般是IMEI, 也可以是Mac地址.
8. Mac: WIFI的Mac地址.
9. SecureId: 设备随机生成的第一个引导, 间接获取设备寿命.
10. InstallId: 应用安装时间.
11. MODEL: 设备型号
12. MANUFACTURER: 设备生产工厂.

其中获取DeviceId需要权限: READ_PHONE_STATE; 获取Mac地址需要权限 ACCESS_WIFI_STATE.

  /**
 * 获取手机标示, 用于激活信息, 需要权限
 * READ_PHONE_STATE和ACCESS_WIFI_STATE
 * <p/>
 * Created by wangchenlong on 15/12/11.
 */
public class ActiveInfo {

    @SuppressWarnings("unused")
    private static final String TAG = "DEBUG-WCL: " + ActiveInfo.class.getSimpleName();

    @SuppressWarnings("all")
    private static final String STAT_INFO_STR =
            "app=%s&platform=android&systemVer=%s&version=%s&app_ver=%s&imei=%s"
                    + "&device_id=%s&mac=%s&secureId=%s&installId=%s&phoneType=%s_by_%s&vendor=";

    private static final String APP_ID = "512";
    private static final String VENDOR = "PedometerLibrary";

    private static final int HTTP_OK = 200; // 请求成功
    private static final int TIME_OUT = 5 * 1000; // 连接超时时间

    private static ActiveInfo sInstance;

    private final Context mContext;
    private final SharedPreferences mPrefs;
    private final TelephonyManager mTelephonyManager;
    private final WifiManager mWifiManager;

    private ActiveInfo() {
        mContext = PedometerManager.getInstance().getContext();
        mPrefs = PreferenceManager.getDefaultSharedPreferences(mContext);
        mTelephonyManager = (TelephonyManager) mContext
                .getSystemService(Context.TELEPHONY_SERVICE);
        mWifiManager = (WifiManager) (mContext.getSystemService(Context.WIFI_SERVICE));
    }

    public static ActiveInfo getInstance() {
        if (sInstance == null) {
            sInstance = new ActiveInfo();
        }
        return sInstance;
    }

    // 获取签名信息
    private String getPhoneSignature() {
        String signature; // 手机标示
        signature = String.format(STAT_INFO_STR,
                getUrlString(APP_ID), // 应用ID
                getUrlString(android.os.Build.VERSION.RELEASE), // 系统版本
                getUrlString(BuildConfig.VERSION_NAME), // SDK版本
                getUrlString(BuildConfig.VERSION_NAME), // 服务器版本
                getUrlString(getDeviceId()), // IMEI
                getUrlString(getDeviceId()), // 设备ID
                getUrlString(getMac()), // Mac地址
                getUrlString(getSecureId()), // 安全ID
                getUrlString(getInstallId()), // 安装时间
                getUrlString(android.os.Build.MODEL), // 设备型号
                getUrlString(android.os.Build.MANUFACTURER)); // 设备工厂
        signature += VENDOR;

        return signature;
    }

    private String getUrlString(String s) {
        //noinspection deprecation
        return URLEncoder.encode(s);
    }

    // 获取设备ID, 需要权限READ_PHONE_STATE
    private String getDeviceId() {
        if (mPrefs.contains(PrefsConsts.PHONE_INFO_DEVICE_ID_PREFS)) {
            return mPrefs.getString(PrefsConsts.PHONE_INFO_DEVICE_ID_PREFS, "");
        } else {
            mPrefs.edit().putString(
                    PrefsConsts.PHONE_INFO_DEVICE_ID_PREFS,
                    mTelephonyManager.getDeviceId())
                    .apply();
            return mPrefs.getString(PrefsConsts.PHONE_INFO_DEVICE_ID_PREFS, "");
        }
    }

    // 获取Mac地址, 需要权限ACCESS_WIFI_STATE
    private String getMac() {
        if (mPrefs.contains(PrefsConsts.PHONE_INFO_MAC_ADDRESS_PREFS)) {
            return mPrefs.getString(PrefsConsts.PHONE_INFO_MAC_ADDRESS_PREFS, "");
        } else {
            mPrefs.edit().putString(
                    PrefsConsts.PHONE_INFO_MAC_ADDRESS_PREFS,
                    mWifiManager.getConnectionInfo().getMacAddress())
                    .apply();
            return mPrefs.getString(PrefsConsts.PHONE_INFO_MAC_ADDRESS_PREFS, "");
        }
    }

    // 获取安全ID
    private String getSecureId() {
        if (mPrefs.contains(PrefsConsts.PHONE_INFO_SECURE_ID_PREFS)) {
            return mPrefs.getString(PrefsConsts.PHONE_INFO_SECURE_ID_PREFS, "");
        } else {
            mPrefs.edit().putString(
                    PrefsConsts.PHONE_INFO_SECURE_ID_PREFS,
                    Settings.Secure.getString(
                            mContext.getContentResolver(), Settings.Secure.ANDROID_ID))
                    .apply();
            return mPrefs.getString(PrefsConsts.PHONE_INFO_SECURE_ID_PREFS, "");
        }
    }

    // 获取安装时的系统时间
    private String getInstallId() {
        if (mPrefs.contains(PrefsConsts.PHONE_INFO_INSTALL_ID_PREFS)) {
            return mPrefs.getString(PrefsConsts.PHONE_INFO_INSTALL_ID_PREFS, "");
        } else {
            mPrefs.edit().putString(
                    PrefsConsts.PHONE_INFO_INSTALL_ID_PREFS,
                    String.format("%d", System.currentTimeMillis()))
                    .apply();
            return mPrefs.getString(PrefsConsts.PHONE_INFO_INSTALL_ID_PREFS, "");
        }
    }

    // 发送激活信息
    public void postActiveInfo() {
        String path = "http://api.chunyu.me/api/launch_request/?";
        path += getPhoneSignature();
        Log.d(TAG, "url: " + path);
        try {
            URL url = new URL(path);
            HttpURLConnection connection = (HttpURLConnection) url.openConnection();
            connection.setConnectTimeout(TIME_OUT); // 连接超时
            connection.connect();
            if (connection.getResponseCode() == HTTP_OK) {
                Log.d(TAG, " 发送激活信息成功");
            } else {
                Log.e(TAG, " 发送激活信息失败: " + connection.getResponseCode());
            }
            connection.disconnect();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

为了减少获取代价, 可以存储一些关键值到首选项.

2. 上传

网络请求必须使用异步线程, 我们只是上传激活, 并不关心返回值, 比较简单.

  new PostActiveTask().execute(); // 发送激活信息
      // 发送激活任务的线程
    private class PostActiveTask extends AsyncTask<Void, Void, Void> {
        @Override
        protected Void doInBackground(Void... params) {
            ActiveInfo.getInstance().postActiveInfo();
            return null;
        }

        @Override
        protected void onPostExecute(Void result) {
        }
    }

返回均为空值, 在 doInBackground中, 需要注明 return null.

OK, Enjoy It.

作者:u012515223 发表于2015/12/13 6:59:35 原文链接
阅读:140 评论:0 查看评论

相关 [手机 物理 标识] 推荐:

发送手机物理标识请求

- - CSDN博客推荐文章
作为应用的重要关注指标-激活, 需要在每次启动时, 都上传手机的物理标识到服务器. 激活信息主要包含:. AppId: 公司拥有多款应用, 标示本应用的类型. Platform: 平台Android或者iOS. SystemVersion: 在Android中, 代表Android版本号. Version: 本应用的版本.

手机设备的唯一标识符

- - 移动开发 - ITeye博客
有很多场景和需求你需要用到手机设备的唯一标识符. 在 Android中,有以下几种方法获取这样的ID. The IMEI: 仅仅只对Android手机有效:. 采用此种方法,需要在AndroidManifest.xml中加入一个许可: android.permission.READ_PHONE_STATE,并且用户应当允许安装此应用.

物理系【图】

- Typhoon - Initiative
貌似出自这里,IMDb, Douban. This particular scene he is supposed to be proving the Heisenberg Uncertainty Principle to which he adds in the end, "It proves we can't ever really know.

创意的品牌标识设计

- emilo - 创意悠悠花园
今天分享一些关于创意的品牌标识设计,希望其中有你喜欢的,或者可以给你带来灵感 的. Read the rest of 创意的品牌标识设计 (69 words). © emilo for 创意悠悠花园, 2011. Post tags: 创意, 品牌, 标识, 设计. 如果你喜欢创意悠悠花园的文章,可以收听我们@emilo,或者订阅我们的rss.

视频请使用schema.org标识

- - Google China Blog
发表者:Henry Zhang,产品经理. 原文: Using schema.org markup for videos. 转载自: 谷歌中文网站管理员博客. 发布时间:2012年2月29日 下午 04:22:00. 视频是使用Google搜索时最常见的一种搜索内容,因此我们要确保您的视频能正确编入索引.

Angry Birds 物理学

- 逆风迎上 - Apple4.us
【本文原载:《连线》,作者:Rhett Allain ,原文链接】. 你知道这个游戏的,我晓得你知道. 没错,Angry Birds. 你可以一次只玩一点点(比如一两关)并且每次当你「发射」,得到的结果都会稍微有那么点不同. 等等,你还没玩过 Angry Birds. 这个游戏简单创意是,用一支弹弓发射一些小鸟(它们看上去有些生气),就像投垒球一样扔出一个弧线,目标是把对面的绿猪们打翻撞倒.

物理学的未来

- Aaron Xu - 译言-每日精品译文推荐
They suggested that neutrinos—ethereal particles which pervade the universe but rarely interact with anything while they are doing so—can travel faster than light.

【Oracle】物理体系结构

- - CSDN博客推荐文章
一、ORACLE 物理体系结构. PGA: 私有内存区,仅供当前发起用户使用. 用户登录后的session信息会保存在PGA. 执行排序,如果内存不够,oracle会在临时表空间中完成. SGA: 包含共享池,数据缓冲区,日志缓冲区以及一些相关的进程. DATABASE: 数据最终存放的地方,其中一块区域是日志存放区.

物理IO与逻辑IO

- - 操作系统 - ITeye博客
IO性能对于一个系统的影响是至关重要的. 一个系统经过多项优化以后,瓶颈往往落在数据库;而数据库经过多种优化以后,瓶颈最终会落到IO. 而IO性能的发展,明显落后于CPU的发展. Memchached也好,NoSql也好,这些流行技术的背后都在直接或者间接地回避IO瓶颈,从而提高系统性能. 上图层次比较多,但总的就是三部分.

塑料标识——非常重要,不可不看!

- princewzy - 有意思吧
  塑料,我们几乎每天无时无刻都在接触着. 当我们清晨起床,穿上拖鞋,端起脸盆,拿着洗面乳、牙膏牙刷去洗漱;接下来早餐吃点啥好呢. 喝点奶,吃几片面包,还是喝豆浆吃油条. 然后出门,打卡上车,坐在公交车的座位上或者拉着把手去上班……然后,还有很多很多. 然而,虽然我们对塑料都很熟悉,但是塑料的标识大家可都知道.