Android8.1 MTK平台 SystemUI源码分析之 网络信号栏显示刷新(下)

简介: Android8.1 MTK平台 SystemUI源码分析之 网络信号栏显示刷新(下)

5、SIM卡插入后更新图标流程


PhoneState 创建成功了并存到集合中,当收到 setMobileDataIndicators()回调后

给 PhoneState 成员变量赋值,赋值结束通过apply()更新

还记得上面说过的 apply() 中更新SIM卡图标的逻辑吧,

遍历 mPhoneStates 集合,调用PhoneState的apply()将成员变量值设置给对应的控件

int firstMobileTypeId = 0;
    for (PhoneState state : mPhoneStates) {
        if (state.apply(anyMobileVisible)) {
            if (!anyMobileVisible) {
                firstMobileTypeId = state.mMobileTypeId;
                anyMobileVisible = true;
            }
        }
    }


那么 setMobileDataIndicators() 是从哪里回调过来的呢?

分析找到 MobileSignalController 中的 notifyListeners()

vendor\mediatek\proprietary\packages\apps\SystemUI\src\com\android\systemui\statusbar\policy\MobileSignalController.java

@Override
public void notifyListeners(SignalCallback callback) {
  //获取资源ID组
    MobileIconGroup icons = getIcons();
    String contentDescription = getStringIfExists(getContentDescription());
    String dataContentDescription = getStringIfExists(icons.mDataContentDescription);
  //移动数据是否开启
    final boolean dataDisabled = mCurrentState.iconGroup == TelephonyIcons.DATA_DISABLED
            && mCurrentState.userSetup;
    /// M: Customize the signal strength icon id. @ {
  //当前手机信号格数资源ID
    int iconId = getCurrentIconId();
  //用户可自定义的资源ID,该方法将目前的iconId原值赋给了iconID,如需定制可在此修改
    iconId = mStatusBarExt.getCustomizeSignalStrengthIcon(
                mSubscriptionInfo.getSubscriptionId(),
                iconId,
                mSignalStrength,
                mDataNetType,
                mServiceState);
    /// @ }
    // Show icon in QS when we are connected or data is disabled.
  //是否显示移动数据图标
    boolean showDataIcon = mCurrentState.dataConnected || dataDisabled;
  //是否显示 mobileGroup、信号格数、SIM卡信息描述
    IconState statusIcon = new IconState(mCurrentState.enabled && !mCurrentState.airplaneMode,
            iconId, contentDescription);
    int qsTypeIcon = 0;
    IconState qsIcon = null;
    String description = null;
    // Only send data sim callbacks to QS.
    if (mCurrentState.dataSim) {
        qsTypeIcon = showDataIcon ? icons.mQsDataType : 0;
        qsIcon = new IconState(mCurrentState.enabled
                && !mCurrentState.isEmergency, getQsCurrentIconId(), contentDescription);
    //状态栏显示只能拨打紧急电话或当前的网络类型
        description = mCurrentState.isEmergency ? null : mCurrentState.networkName;
    }
  //数据下行
    boolean activityIn = mCurrentState.dataConnected
            && !mCurrentState.carrierNetworkChangeMode
            && mCurrentState.activityIn;
  //数据上行
    boolean activityOut = mCurrentState.dataConnected
            && !mCurrentState.carrierNetworkChangeMode
            && mCurrentState.activityOut;
    showDataIcon &= mCurrentState.isDefault || dataDisabled;
  //移动数据类型资源ID,关闭是X,打开是小的网络类型4G/3G/2G
    int typeIcon = showDataIcon ? icons.mDataType : 0;
    /// M: Add for lwa.
    typeIcon = mCurrentState.lwaRegState == NetworkTypeUtils.LWA_STATE_CONNCTED
            && showDataIcon ? NetworkTypeUtils.LWA_ICON : typeIcon;
    /** M: Support [Network Type on StatusBar], change the implement methods.
      * Get the network icon base on service state.
      * Add one more parameter for network type.
      * @ { **/
  //当前网络类型资源ID
    int networkIcon = mCurrentState.networkIcon;
    /// M: Support volte icon.Bug fix when airplane mode is on go to hide volte icon
  //VOlTE资源ID
    int volteIcon = mCurrentState.airplaneMode && !isImsOverWfc()
            ? 0 : mCurrentState.volteIcon;
    /// M: when data disabled, common show data icon as x, but op do not need show it @ {
    mStatusBarExt.isDataDisabled(mSubscriptionInfo.getSubscriptionId(), dataDisabled);
    /// @ }
    /// M: Customize the data type icon id. @ {
  //可自定义移动数据类型资源ID(比如常见的上下箭头)
    typeIcon = mStatusBarExt.getDataTypeIcon(
                    mSubscriptionInfo.getSubscriptionId(),
                    typeIcon,
                    mDataNetType,
                    mCurrentState.dataConnected ? TelephonyManager.DATA_CONNECTED :
                        TelephonyManager.DATA_DISCONNECTED,
                    mServiceState);
    /// @ }
    /// M: Customize the network type icon id. @ {
  //可自定义网络类型资源ID
    networkIcon = mStatusBarExt.getNetworkTypeIcon(
                    mSubscriptionInfo.getSubscriptionId(),
                    networkIcon,
                    mDataNetType,
                    mServiceState);
    callback.setMobileDataIndicators(statusIcon, qsIcon, typeIcon, networkIcon, volteIcon,
            qsTypeIcon,activityIn, activityOut, dataContentDescription, description,
             icons.mIsWide, mSubscriptionInfo.getSubscriptionId(), mCurrentState.roaming);
    /// M: update plmn label @{
    mNetworkController.refreshPlmnCarrierLabel();
    /// @}
}


这个方法比较重要,上面写了简单的注释,接下来我们会详细看下每个资源ID都是如何获取的?


在这之前我们先介绍下几个重要的 Bean 类


vendor\mediatek\proprietary\packages\apps\SystemUI\src\com\android\systemui\statusbar\policy\SignalController.java


State

static class State {
    boolean connected;
    boolean enabled;
    boolean activityIn;
    boolean activityOut;
    int level;
    IconGroup iconGroup;
    int inetCondition;
    int rssi;
  ...
}


IconGroup

static class IconGroup {
    final int[][] mSbIcons;
    final int[][] mQsIcons;
    final int[] mContentDesc;
    final int mSbNullState;
    final int mQsNullState;
    final int mSbDiscState;
    final int mQsDiscState;
    final int mDiscContentDesc;
    // For logging.
    final String mName;
  ....
}


vendor\mediatek\proprietary\packages\apps\SystemUI\src\com\android\systemui\statusbar\policy\MobileSignalController.java

MobileState


static class MobileState extends SignalController.State {
    String networkName;//当前网络类型
    String networkNameData;//移动数据网络类型
    boolean dataSim;
    boolean dataConnected;//数据是否连接
    boolean isEmergency;//是否是紧急电话模式
    boolean airplaneMode;//是否是飞行模式
    boolean carrierNetworkChangeMode;//SIM卡网络类型是否改变
    boolean isDefault;
    boolean userSetup;//是否是用户操作
    boolean roaming;//是否漫游
    /// M: Add for 4G+W
    int lwaRegState = NetworkTypeUtils.LWA_STATE_UNKNOWN;
    /// M: For network type big icon.
    int networkIcon;//网络类型大图标资源ID
    /// M: Add for data network type.
    int dataNetType;//移动数据网络类型
    /// M: Add for op network tower type.
    int customizedState;//自定义状态
    /// M: Add for op signal strength tower icon.
    int customizedSignalStrengthIcon;//自定义信号格资源ID
    /// M: Add for volte @{
    int imsRegState = ServiceState.STATE_POWER_OFF;
    int imsCap;
    int volteIcon;//volte资源ID
  ......  
}

MobileIconGroup

static class MobileIconGroup extends SignalController.IconGroup {
    final int mDataContentDescription; // mContentDescriptionDataType
    final int mDataType;//移动数据网络类型资源ID
    final boolean mIsWide;
    final int mQsDataType;//下拉快捷访问资源
  ...   
}


好了重要的Bean类介绍完了,接下来又要说一个重要的方法了 updateTelephony()

还是在 MobileSignalController.java 中

private final void updateTelephony() {
    if (DEBUG && FeatureOptions.LOG_ENABLE) {
        Log.d(mTag, "updateTelephonySignalStrength: hasService=" + hasService()
                + " ss=" + mSignalStrength);
    }
  //连接状态,是否在服务中
    mCurrentState.connected = hasService() && mSignalStrength != null;
    handleIWLANNetwork();
    if (mCurrentState.connected) {
    //SIM 卡信号格数级别 0~4格
        if (!mSignalStrength.isGsm() && mConfig.alwaysShowCdmaRssi) {
            mCurrentState.level = mSignalStrength.getCdmaLevel();
        } else {
            mCurrentState.level = mSignalStrength.getLevel();
        }
        /// M: Customize the signal strength level. @ {
    //客户可自定义
        mCurrentState.level = mStatusBarExt.getCustomizeSignalStrengthLevel(
                mCurrentState.level, mSignalStrength, mServiceState);
        /// @ }
    }
  //当前网络类型获取对应的图标组
    if (mNetworkToIconLookup.indexOfKey(mDataNetType) >= 0) {
        mCurrentState.iconGroup = mNetworkToIconLookup.get(mDataNetType);
    } else {
        mCurrentState.iconGroup = mDefaultIcons;
    }
    /// M: Add for data network type.
  //数据网络类型
    mCurrentState.dataNetType = mDataNetType;
  //数据状态
    mCurrentState.dataConnected = mCurrentState.connected
            && mDataState == TelephonyManager.DATA_CONNECTED;
    /// M: Add for op network tower type.
    mCurrentState.customizedState = mStatusBarExt.getCustomizeCsState(mServiceState,
            mCurrentState.customizedState);
    /// M: Add for op signal strength tower icon.
    mCurrentState.customizedSignalStrengthIcon = mStatusBarExt.getCustomizeSignalStrengthIcon(
            mSubscriptionInfo.getSubscriptionId(),
            mCurrentState.customizedSignalStrengthIcon,
            mSignalStrength,
            mDataNetType,
            mServiceState);
    mCurrentState.roaming = isRoaming();
    if (isCarrierNetworkChangeActive()) {
        mCurrentState.iconGroup = TelephonyIcons.CARRIER_NETWORK_CHANGE;
    } else if (isDataDisabled()) {//数据未打开,对应x
        mCurrentState.iconGroup = TelephonyIcons.DATA_DISABLED;
    }
    if (isEmergencyOnly() != mCurrentState.isEmergency) {
        mCurrentState.isEmergency = isEmergencyOnly();
        mNetworkController.recalculateEmergency();
    }
    // Fill in the network name if we think we have it.
  //当前网络运营商
    if (mCurrentState.networkName == mNetworkNameDefault && mServiceState != null
            && !TextUtils.isEmpty(mServiceState.getOperatorAlphaShort())) {
        mCurrentState.networkName = mServiceState.getOperatorAlphaShort();
    }
    /// M: For network type big icon. 网络类型大图标
    mCurrentState.networkIcon =
        NetworkTypeUtils.getNetworkTypeIcon(mServiceState, mConfig, hasService());
    /// M: For volte type icon. volte图标
    mCurrentState.volteIcon = getVolteIcon();
  //通知更新,最终回调到notifyListeners()中
    notifyListenersIfNecessary();
}


基本上获取资源ID的方法都在 updateTelephony()中了,那么都在那里调用了 updateTelephony()?


MobileSignalController中构造方法初始化了 MobilePhoneStateListener 分别监听了

mPhone.listen(mPhoneStateListener,
PhoneStateListener.LISTEN_SERVICE_STATE//服务状态改变,可用、不可用
        | PhoneStateListener.LISTEN_SIGNAL_STRENGTHS//信号强度改变,用于获取dbm、asu
        | PhoneStateListener.LISTEN_CALL_STATE//电话状态改变,空闲、来电、通话
        | PhoneStateListener.LISTEN_DATA_CONNECTION_STATE//数据网络连接状态,网络断开、正在连接中、已连接上
        | PhoneStateListener.LISTEN_DATA_ACTIVITY//数据上下行状态
        | PhoneStateListener.LISTEN_CARRIER_NETWORK_CHANGE);//网络状态发送改变
class MobilePhoneStateListener extends PhoneStateListener {
    public MobilePhoneStateListener(int subId, Looper looper) {
        super(subId, looper);
    }
    @Override
    public void onSignalStrengthsChanged(SignalStrength signalStrength) {
        ...
        updateTelephony();
    }
    @Override
    public void onServiceStateChanged(ServiceState state) {
        ...
        updateTelephony();
    }
    @Override
    public void onDataConnectionStateChanged(int state, int networkType) {
        ...
        updateTelephony();
    }
    @Override
    public void onDataActivity(int direction) {
        ...
        setActivity(direction);
    }
    @Override
    public void onCarrierNetworkChange(boolean active) {
       ...
        updateTelephony();
    }
    /// M: Add for Plugin feature. @{
    @Override
    public void onCallStateChanged(int state, String incomingNumber) {
        ...
        updateTelephony();
    }
    /// @}
};

LISTEN_SIGNAL_STRENGTHS、LISTEN_CALL_STATE、LISTEN_CARRIER_NETWORK_CHANGE

这三个监听应该是我们平常用较多的,好了说了这么久,接下来重要看获取资源ID的具体方法了


5.1、Vlote资源ID

mCurrentState.volteIcon = getVolteIcon();
private int getVolteIcon() {
    int icon = 0;
    if (isImsOverWfc()) {
        boolean needShowWfcSysIcon = mStatusBarExt.needShowWfcIcon();
        if (needShowWfcSysIcon) {
            icon = NetworkTypeUtils.WFC_ICON;
        }
    } else if (isImsOverVoice() && isLteNetWork()) {
        if (mCurrentState.imsRegState == ServiceState.STATE_IN_SERVICE) {
      //volte可用
            icon = NetworkTypeUtils.VOLTE_ICON;
        } else if(FeatureOptions.MTK_CT_MIXED_VOLTE_SUPPORT &&
            SIMHelper.isSecondaryCSIMForMixedVolte(mSubscriptionInfo.getSubscriptionId()) &&
            mCurrentState.imsRegState == ServiceState.STATE_OUT_OF_SERVICE) {
            if (DEBUG) {
                Log.d(mTag, "set dis volte icon");
            }//volte不可用
            icon = NetworkTypeUtils.VOLTE_DIS_ICON;
        }
    }
    /// M: add for disconnected volte feature. @{
    mStatusBarExt.setImsRegInfo(mSubscriptionInfo.getSubscriptionId(),
            mCurrentState.imsRegState, isImsOverWfc(), isImsOverVoice());
    /// @}
    return icon;
}

vendor\mediatek\proprietary\packages\apps\SystemUI\src\com\mediatek\systemui\statusbar\networktype\NetworkTypeUtils.java

public static final int VOLTE_ICON = R.drawable.stat_sys_volte;


20190527213054136.png

5.2、网络类型大图标资源ID

vendor\mediatek\proprietary\packages\apps\SystemUI\src\com\mediatek\systemui\statusbar\networktype\NetworkTypeUtils.java

mCurrentState.networkIcon =
        NetworkTypeUtils.getNetworkTypeIcon(mServiceState, mConfig, hasService());
public static int getNetworkTypeIcon(ServiceState serviceState, Config config,
        boolean hasService) {
    if (!hasService) {
        // Not in service, no network type. 未注册成功,比如废卡、停机卡
        return 0;
    }
  //通过 serviceState 获取当前注册的网络类型
    int tempNetworkType = getNetworkType(serviceState);
    Integer iconId = sNetworkTypeIcons.get(tempNetworkType);
    if (iconId == null) {
        iconId = tempNetworkType == TelephonyManager.NETWORK_TYPE_UNKNOWN ? 0 :
                 config.showAtLeast3G ? R.drawable.stat_sys_network_type_3g :
                                        R.drawable.stat_sys_network_type_g;
    }
    return iconId.intValue();
}
private static int getNetworkType(ServiceState serviceState) {
    int type = TelephonyManager.NETWORK_TYPE_UNKNOWN;
    if (serviceState != null) {
        type = serviceState.getDataNetworkType() != TelephonyManager.NETWORK_TYPE_UNKNOWN ?
                serviceState.getDataNetworkType() : serviceState.getVoiceNetworkType();
    }
    return type;
}
//网络类型-资源ID    4g/3g/2g/e/1x
static final Map<Integer, Integer> sNetworkTypeIcons = new HashMap<Integer, Integer>() {
    {
        // For CDMA 3G
        put(TelephonyManager.NETWORK_TYPE_EVDO_0, R.drawable.stat_sys_network_type_3g);
        put(TelephonyManager.NETWORK_TYPE_EVDO_A, R.drawable.stat_sys_network_type_3g);
        put(TelephonyManager.NETWORK_TYPE_EVDO_B, R.drawable.stat_sys_network_type_3g);
        put(TelephonyManager.NETWORK_TYPE_EHRPD, R.drawable.stat_sys_network_type_3g);
        // For CDMA 1x
        put(TelephonyManager.NETWORK_TYPE_CDMA, R.drawable.stat_sys_network_type_1x);
        put(TelephonyManager.NETWORK_TYPE_1xRTT, R.drawable.stat_sys_network_type_1x);
        // Edge
        put(TelephonyManager.NETWORK_TYPE_EDGE, R.drawable.stat_sys_network_type_e);
        // 3G
        put(TelephonyManager.NETWORK_TYPE_UMTS, R.drawable.stat_sys_network_type_3g);
        // For 4G
        put(TelephonyManager.NETWORK_TYPE_LTE, R.drawable.stat_sys_network_type_4g);
        // 3G
        put(TelephonyManager.NETWORK_TYPE_HSDPA, R.drawable.stat_sys_network_type_3g);
        put(TelephonyManager.NETWORK_TYPE_HSUPA, R.drawable.stat_sys_network_type_3g);
        put(TelephonyManager.NETWORK_TYPE_HSPA, R.drawable.stat_sys_network_type_3g);
        put(TelephonyManager.NETWORK_TYPE_HSPAP, R.drawable.stat_sys_network_type_3g);
        put(TelephonyManager.NETWORK_TYPE_IWLAN, 0);
    }
};

20190527213108771.png


5.3、移动数据类型资源ID

//mNetworkToIconLookup 和上面的网络类型 Map有点类似,键都是网络类型,
//不同的是,这次的key是上面介绍过的 MobileIconGroup
if (mNetworkToIconLookup.indexOfKey(mDataNetType) >= 0) {
    mCurrentState.iconGroup = mNetworkToIconLookup.get(mDataNetType);
} else {
    mCurrentState.iconGroup = mDefaultIcons;
}
if (isCarrierNetworkChangeActive()) {
    mCurrentState.iconGroup = TelephonyIcons.CARRIER_NETWORK_CHANGE;
} else if (isDataDisabled()) {
    mCurrentState.iconGroup = TelephonyIcons.DATA_DISABLED;
}

vendor\mediatek\proprietary\packages\apps\SystemUI\src\com\android\systemui\statusbar\policy\TelephonyIcons.java

class TelephonyIcons {
  //***** Data connection icons
  //状态栏快捷访问,其实和下面的差多不
    static final int QS_DATA_G = R.drawable.ic_qs_signal_g;
    static final int QS_DATA_3G = R.drawable.ic_qs_signal_3g;
    static final int QS_DATA_E = R.drawable.ic_qs_signal_e;
    static final int QS_DATA_H = R.drawable.ic_qs_signal_h;
    static final int QS_DATA_1X = R.drawable.ic_qs_signal_1x;
    static final int QS_DATA_4G = R.drawable.ic_qs_signal_4g;
    static final int QS_DATA_4G_PLUS = R.drawable.ic_qs_signal_4g_plus;
    static final int QS_DATA_LTE = R.drawable.ic_qs_signal_lte;
    static final int QS_DATA_LTE_PLUS = R.drawable.ic_qs_signal_lte_plus;
    static final int FLIGHT_MODE_ICON = R.drawable.stat_sys_airplane_mode;
  //此处的图标为小图标,网络类型
    static final int ICON_LTE = R.drawable.stat_sys_data_fully_connected_lte;
    static final int ICON_LTE_PLUS = R.drawable.stat_sys_data_fully_connected_lte_plus;
    static final int ICON_G = R.drawable.stat_sys_data_fully_connected_g;
    static final int ICON_E = R.drawable.stat_sys_data_fully_connected_e;
    static final int ICON_H = R.drawable.stat_sys_data_fully_connected_h;
    static final int ICON_3G = R.drawable.stat_sys_data_fully_connected_3g;
    static final int ICON_4G = R.drawable.stat_sys_data_fully_connected_4g;
    static final int ICON_4G_PLUS = R.drawable.stat_sys_data_fully_connected_4g_plus;
    static final int ICON_1X = R.drawable.stat_sys_data_fully_connected_1x;
  //流量未打开
    static final int ICON_DATA_DISABLED = R.drawable.stat_sys_data_disabled;
    static final int QS_ICON_DATA_DISABLED = R.drawable.ic_qs_data_disabled;
  ...
  static final MobileIconGroup DATA_DISABLED = new MobileIconGroup(
        "DataDisabled",
        null,
        null,
        AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH,
        0, 0,
        0,
        0,
        AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0],
        R.string.accessibility_cell_data_off,
        TelephonyIcons.ICON_DATA_DISABLED,//这个值对应的就是 移动数据类型资源ID
        false,
        TelephonyIcons.QS_ICON_DATA_DISABLED
        );
}


MobileIconGroup 的倒数第三个参数就是 移动数据类型资源ID


20190527213343292.png


5.4、信号格数资源ID


if (mCurrentState.connected) {
        if (!mSignalStrength.isGsm() && mConfig.alwaysShowCdmaRssi) {
            mCurrentState.level = mSignalStrength.getCdmaLevel();
        } else {
            mCurrentState.level = mSignalStrength.getLevel();
        }
        /// M: Customize the signal strength level. @ {
        mCurrentState.level = mStatusBarExt.getCustomizeSignalStrengthLevel(
                mCurrentState.level, mSignalStrength, mServiceState);
        /// @ }
 }


信号格数对应的是 SignalDrawable,通过 setLevel()来控制显示几格,其实以上的大部分资源ID都是


通过 Vector 标签绘制而来的,里面都是一堆 path,开始看可能会觉得很迷糊,可以把xml文件拷贝到


AS中进行预览,再学上一些基础语法就可对简单的图形进行自定义修改。比方说6.0的信号格数是通过


vector 绘制的,格与格之间是有间隔,而8.1是通过 SignalDrawable绘制,是一个填满的三角形

20190527213208491.png

修改前样式


20190527213146452.png


修改后样式

来看下 mSignalStrength.getLevel() 方法

frameworks/base/telephony/java/android/telephony/SignalStrength.java


    public int getLevel() {
    int level = 0;
    if (isGsm) { //移动或联通卡
        level = getLteLevel(); //首先获取4G信号格
        if (level == SIGNAL_STRENGTH_NONE_OR_UNKNOWN) { //未获取到
            level = getTdScdmaLevel(); //获取移动或联通的3G信号格
            if (level == SIGNAL_STRENGTH_NONE_OR_UNKNOWN) {//仍然未获取
                level = getGsmLevel(); //获取移动或联通的2G信号格
            }
        }
    } else {//电信
        int cdmaLevel = getCdmaLevel(); //获取电信2G信号格
        int evdoLevel = getEvdoLevel(); //获取电信3G信号格
        if (evdoLevel == SIGNAL_STRENGTH_NONE_OR_UNKNOWN) {
            /* We don't know evdo, use cdma */
            level = cdmaLevel;
        } else if (cdmaLevel == SIGNAL_STRENGTH_NONE_OR_UNKNOWN) {
            /* We don't know cdma, use evdo */
            level = evdoLevel;
        } else {
            /* We know both, use the lowest level */
            level = cdmaLevel < evdoLevel ? cdmaLevel : evdoLevel;
        }
    }
    if (DBG) log("getLevel=" + level);
    return level;
}

在此介绍下手机是几模的配置:GSM是移动和联通公用的band;LTE从编码方式上分为TDD和FDD,从频段上分有各种不同的band


移动:GSM、TDSCDMA、LTE(TDD)


联通:GSM、WCDMA、LTE(FDD)


电信:CDMA、EVDO、LTE(FDD)


因此如果手机支持GSM、WCDMA、TDSCDMA、TDD-LTE、FDD-LTE 这是五模;加上 CDMA、EVDO 就是七模


5.5、漫游资源ID R.drawable.stat_sys_roaming


大写的R


三、总结


信号栏的定制还是很容易的,只要理清楚了控件和对应的回调逻辑,加上日志打印,就能搞定你想要的效果。


四、相关资源


这里附上我定制使用的drawable文件,CSDN有点坑啊,我想传免费的来着,非要给我设置5分,好吧,只好换平台改链接免费下载

20190527213532314.png

drawable.zip

目录
相关文章
|
2月前
|
机器学习/深度学习 算法 数据安全/隐私保护
基于GRU网络的MQAM调制信号检测算法matlab仿真,对比LSTM
本研究基于MATLAB 2022a,使用GRU网络对QAM调制信号进行检测。QAM是一种高效调制技术,广泛应用于现代通信系统。传统方法在复杂环境下性能下降,而GRU通过门控机制有效提取时间序列特征,实现16QAM、32QAM、64QAM、128QAM的准确检测。仿真结果显示,GRU在低SNR下表现优异,且训练速度快,参数少。核心程序包括模型预测、误检率和漏检率计算,并绘制准确率图。
110 65
基于GRU网络的MQAM调制信号检测算法matlab仿真,对比LSTM
|
28天前
|
存储 编解码 监控
Android平台GB28181执法记录仪技术方案与实现
本文介绍了大牛直播SDK的SmartGBD在执法记录仪场景中的应用。GB28181协议作为视频监控联网的国家标准,为设备互联互通提供规范。SmartGBD专为Android平台设计,支持音视频采集、编码与传输,具备自适应算法和多功能扩展优势。文章分析了执法记录仪的需求,如实时音视频传输、设备管理及数据安全,并详细阐述了基于SmartGBD的技术实现方案,包括环境准备、SDK集成、设备注册、音视频处理及功能扩展等步骤。最后展望了SmartGBD在未来智慧物联领域的广阔应用前景。
69 13
|
28天前
|
存储 编解码 开发工具
Android平台毫秒级低延迟HTTP-FLV直播播放器技术探究与实现
本文详细探讨了在Android平台上实现HTTP-FLV播放器的过程。首先介绍了FLV格式的基础,包括文件头和标签结构。接着分析了HTTP-FLV传输原理,通过分块传输实现流畅播放。然后重点讲解了播放器的实现步骤,涵盖网络请求、数据解析、音视频解码与渲染,以及播放控制功能的设计。文章还讨论了性能优化和网络异常处理的方法,并总结了HTTP-FLV播放器的技术价值,尤其是在特定场景下的应用意义。
116 11
|
26天前
|
监控 Shell Linux
Android调试终极指南:ADB安装+多设备连接+ANR日志抓取全流程解析,覆盖环境变量配置/多设备调试/ANR日志分析全流程,附Win/Mac/Linux三平台解决方案
ADB(Android Debug Bridge)是安卓开发中的重要工具,用于连接电脑与安卓设备,实现文件传输、应用管理、日志抓取等功能。本文介绍了 ADB 的基本概念、安装配置及常用命令。包括:1) 基本命令如 `adb version` 和 `adb devices`;2) 权限操作如 `adb root` 和 `adb shell`;3) APK 操作如安装、卸载应用;4) 文件传输如 `adb push` 和 `adb pull`;5) 日志记录如 `adb logcat`;6) 系统信息获取如屏幕截图和录屏。通过这些功能,用户可高效调试和管理安卓设备。
|
2月前
|
算法 安全 大数据
【算法合规新时代】企业如何把握“清朗·网络平台算法典型问题治理”专项行动?
在数字化时代,算法推动社会发展,但也带来了信息茧房、大数据杀熟等问题。中央网信办发布《关于开展“清朗·网络平台算法典型问题治理”专项行动的通知》,针对六大算法问题进行整治,明确企业需落实算法安全主体责任,建立健全审核与管理制度,并对算法进行全面审查和备案。企业应积极自查自纠,确保算法合规透明,防范风险,迎接新机遇。
|
4月前
|
NoSQL 关系型数据库 MySQL
《docker高级篇(大厂进阶):4.Docker网络》包括:是什么、常用基本命令、能干嘛、网络模式、docker平台架构图解
《docker高级篇(大厂进阶):4.Docker网络》包括:是什么、常用基本命令、能干嘛、网络模式、docker平台架构图解
253 56
《docker高级篇(大厂进阶):4.Docker网络》包括:是什么、常用基本命令、能干嘛、网络模式、docker平台架构图解
|
2月前
|
运维 安全 网络安全
VMware NSX 4.2.1.3 下载 - 网络安全虚拟化平台
VMware NSX 4.2.1.3 下载 - 网络安全虚拟化平台
87 0
VMware NSX 4.2.1.3 下载 - 网络安全虚拟化平台
|
3月前
|
运维 监控 Cloud Native
构建深度可观测、可集成的网络智能运维平台
本文介绍了构建深度可观测、可集成的网络智能运维平台(简称NIS),旨在解决云上网络运维面临的复杂挑战。内容涵盖云网络运维的三大难题、打造云原生AIOps工具集的解决思路、可观测性对业务稳定的重要性,以及产品发布的亮点,包括流量分析NPM、网络架构巡检和自动化运维OpenAPI,助力客户实现自助运维与优化。
|
4月前
|
IDE 开发工具 Android开发
移动应用开发之旅:探索Android和iOS平台
在这篇文章中,我们将深入探讨移动应用开发的两个主要平台——Android和iOS。我们将了解它们的操作系统、开发环境和工具,并通过代码示例展示如何在这两个平台上创建一个简单的“Hello World”应用。无论你是初学者还是有经验的开发者,这篇文章都将为你提供有价值的信息和技巧,帮助你更好地理解和掌握移动应用开发。
131 17
|
4月前
|
SQL 安全 网络安全
网络安全与信息安全:知识分享####
【10月更文挑战第21天】 随着数字化时代的快速发展,网络安全和信息安全已成为个人和企业不可忽视的关键问题。本文将探讨网络安全漏洞、加密技术以及安全意识的重要性,并提供一些实用的建议,帮助读者提高自身的网络安全防护能力。 ####
116 17

热门文章

最新文章