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

目录
相关文章
|
1月前
|
数据库 Android开发 开发者
构建高效Android应用:采用Kotlin协程优化网络请求处理
【2月更文挑战第30天】 在移动应用开发领域,网络请求的处理是影响用户体验的关键环节。针对Android平台,利用Kotlin协程能够极大提升异步任务处理的效率和简洁性。本文将探讨如何通过Kotlin协程优化Android应用中的网络请求处理流程,包括协程的基本概念、网络请求的异步执行以及错误处理等方面,旨在帮助开发者构建更加流畅和响应迅速的Android应用。
|
2月前
|
Android开发
安卓SO层开发 -- 编译指定平台的SO文件
安卓SO层开发 -- 编译指定平台的SO文件
32 0
|
3天前
|
移动开发 Java Android开发
构建高效Android应用:采用Kotlin协程优化网络请求
【4月更文挑战第24天】 在移动开发领域,尤其是对于Android平台而言,网络请求是一个不可或缺的功能。然而,随着用户对应用响应速度和稳定性要求的不断提高,传统的异步处理方式如回调地狱和RxJava已逐渐显示出局限性。本文将探讨如何利用Kotlin协程来简化异步代码,提升网络请求的效率和可读性。我们将深入分析协程的原理,并通过一个实际案例展示如何在Android应用中集成和优化网络请求。
|
11天前
|
Android开发 开发者
Android网络和数据交互: 请解释Android中的AsyncTask的作用。
Android&#39;s AsyncTask simplifies asynchronous tasks for brief background work, bridging UI and worker threads. It involves execute() for starting tasks, doInBackground() for background execution, publishProgress() for progress updates, and onPostExecute() for returning results to the main thread.
10 0
|
11天前
|
网络协议 安全 API
Android网络和数据交互: 什么是HTTP和HTTPS?在Android中如何进行网络请求?
HTTP和HTTPS是网络数据传输协议,HTTP基于TCP/IP,简单快速,HTTPS则是加密的HTTP,确保数据安全。在Android中,过去常用HttpURLConnection和HttpClient,但HttpClient自Android 6.0起被移除。现在推荐使用支持TLS、流式上传下载、超时配置等特性的HttpsURLConnection进行网络请求。
10 0
|
1月前
|
运维 监控 Java
应用研发平台EMAS产品常见问题之安卓构建版本失败如何解决
应用研发平台EMAS(Enterprise Mobile Application Service)是阿里云提供的一个全栈移动应用开发平台,集成了应用开发、测试、部署、监控和运营服务;本合集旨在总结EMAS产品在应用开发和运维过程中的常见问题及解决方案,助力开发者和企业高效解决技术难题,加速移动应用的上线和稳定运行。
|
1月前
|
运维 监控 Android开发
应用研发平台EMAS常见问题之安卓push的离线转通知目前无法收到如何解决
应用研发平台EMAS(Enterprise Mobile Application Service)是阿里云提供的一个全栈移动应用开发平台,集成了应用开发、测试、部署、监控和运营服务;本合集旨在总结EMAS产品在应用开发和运维过程中的常见问题及解决方案,助力开发者和企业高效解决技术难题,加速移动应用的上线和稳定运行。
25 1
|
2月前
|
网络协议 物联网 Linux
WireGuard 系列文章(五):Netmaker 简介 - 创建和管理 WireGuard 网络的平台
WireGuard 系列文章(五):Netmaker 简介 - 创建和管理 WireGuard 网络的平台
【计算机网络】物理链路通信信号
【1月更文挑战第27天】【计算机网络】物理链路通信信号
|
3月前
|
编解码 测试技术 开发工具
如何实现Android视音频数据对接到GB28181平台(SmartGBD)
如何实现Android视音频数据对接到GB28181平台(SmartGBD)