热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Cocos项目为安卓添加获取手机信号强度和网络类型的功能(JAVA/C++/Lua)

首先是JAVA层:直接使用Android自带的TelephonyManager和ConnectivityManager都可以获取到NetworksInfo对象,可以通过ge

首先是JAVA层:

直接使用Android自带的TelephonyManager 和 ConnectivityManager 都可以获取到 NetworksInfo 对象,可以通过 getType() 获取类型,判断是 “WIFI”还是 “MOBILE”,如果是MOBILE,可以通过 NetworksInfo 对象的 getSubType() 和 getSubTypeName() 可以获取到对于的网络类型和名字。

通过简单地查看Android API即可调用。安卓SDK19暂无对4G网络的强度判断方法。

先声明一些常量:

	//网络状态强度
    public static final int NETLEVEL_STRENGTH_NONE_OR_UNKNOWN = 0;
    public static final int NETLEVEL_STRENGTH_POOR = 1;
    public static final int NETLEVEL_STRENGTH_MODERATE = 2;
    public static final int NETLEVEL_STRENGTH_GOOD = 3;
    public static final int NETLEVEL_STRENGTH_GREAT = 4;
    //定义数组用于返回
    static int[] netInfo = new int[2];
    //信号监听
    TelephonyManager        Tel;  
    MyPhoneStateListener    MyListener; 
    public static int singnalLevel;

    //Wifi监听
    private static WifiInfo wifiInfo = null;
    private static WifiManager wifiManager = null; 
    public static int wifiLevel;
在onCreate()里添加注册监听:

//添加信号强度监听
        MyListener = new MyPhoneStateListener();
        Tel = (TelephonyManager)getSystemService(Context.TELEPHONY_SERVICE);
        Tel.listen(MyListener, PhoneStateListener.LISTEN_SIGNAL_STRENGTHS);

        //添加wifi强度监听
        wifiManager = (WifiManager)getSystemService(WIFI_SERVICE);
	}
再调用方法public void onSignalStrengthsChanged(SignalStrength signalStrength) 就能得到信号强度了,注意下面代码中加了对4G信号强度的判断:

/**
	 * 获取当前网络类型
	 */
	static public String getNetworkType() {
		ConnectivityManager cOnnManager= (ConnectivityManager) _activity
				.getSystemService(Context.CONNECTIVITY_SERVICE);
		NetworkInfo networkinfo = connManager.getActiveNetworkInfo();
		if (networkinfo != null) {
			return networkinfo.getTypeName();
		}
		return "无";
	}

	 //netType   -1: 没有网络    1: WIFI     2: 移动数据
    //netLevel  1: None 2:poor  3:moderate  4:good  5:great 
    public static int[] getNetInfo() {
        Log.d("getNetInfo", "enter the function getNetInfo ----- ");
        //根据Android的安全机制,在使用ConnectivityManager时,必须在AndroidManifest.xml中添加 否则无法获得系统的许可。
        ConnectivityManager cOnnMgr= (ConnectivityManager)_activity.getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo networkInfo = connMgr.getActiveNetworkInfo();
        if( null == networkInfo)
            return netInfo;
        int nType = networkInfo.getType();
        if (nType == ConnectivityManager.TYPE_MOBILE) {
            netInfo[0] = 2;
        }
        else if (nType == ConnectivityManager.TYPE_WIFI) {
            netInfo[0] = 1;
        }
        Log.d("getNetInfo", "java ---- netType --- "+ netInfo[0]);

        //according to netType. set the value of netLevel
        switch (netInfo[0]) {
        case 1:
            netInfo[1] = getWifiLevel();
            break;
        case 2:
            netInfo[1] = getSingnalLevel();
            break;
        default:
            break;
        }
        Log.d("getNetInfo", "java ---- netLevel --- "+ netInfo[1]);

        return netInfo;
    }
    //信号强度等级
    private class MyPhoneStateListener extends PhoneStateListener  
    {  
      @Override  
      public void onSignalStrengthsChanged(SignalStrength signalStrength)  
      {  
         super.onSignalStrengthsChanged(signalStrength);  
         int asu = signalStrength.getGsmSignalStrength();
         
         //获取4G信号下的信号强度,可能存在部分手机机型导致的bug
         String signalInfo = signalStrength.toString();  
         String[] params = signalInfo.split(" "); 
         // 17/8/14 注意,可能在不同机型上解析params得到的Itedbm值不同
         if(Tel.getNetworkType() == TelephonyManager.NETWORK_TYPE_LTE){  
         //4G网络 最佳范围   >-90dBm 越大越好  
             int Itedbm = Integer.parseInt(params[9]);
             asu=asu+Itedbm;
             if (asu<=0 ||asu>=99) singnalLevel = NETLEVEL_STRENGTH_NONE_OR_UNKNOWN;
             //Log.d("Itedbm-----","Itedbm----->"+Itedbm);
         }
         //Log.d("asu----","java---asu---"+ asu);
         
         if (asu <= 2 || asu == 99) singnalLevel = NETLEVEL_STRENGTH_NONE_OR_UNKNOWN;
         else if (asu >= 12) singnalLevel = NETLEVEL_STRENGTH_GREAT;
         else if (asu >= 8)  singnalLevel = NETLEVEL_STRENGTH_GOOD;
         else if (asu >= 5)  singnalLevel = NETLEVEL_STRENGTH_MODERATE;
         else singnalLevel = NETLEVEL_STRENGTH_POOR;
      }  
    };/* End of private Class */  
    //获取信号强度
    public static int getSingnalLevel() {
         return singnalLevel;
    }

    //获取wifi强度
    public static int getWifiLevel() {
        wifiInfo = wifiManager.getConnectionInfo();
        int wifiStrength = wifiInfo.getRssi();
        if (wifiStrength <= 0 && wifiStrength >= -50) {  
            wifiLevel = NETLEVEL_STRENGTH_GREAT;
        } else if (wifiStrength <-50 && wifiStrength >= -70) {  
            wifiLevel = NETLEVEL_STRENGTH_GOOD; 
        } else if (wifiStrength <-70 && wifiStrength >= -80) {  
            wifiLevel = NETLEVEL_STRENGTH_MODERATE;
        } else if (wifiStrength <-80 && wifiStrength >= -100) {  
            wifiLevel = NETLEVEL_STRENGTH_POOR; 
        } else {  
            wifiLevel = NETLEVEL_STRENGTH_NONE_OR_UNKNOWN; 
        } 
        return wifiLevel;
    }

对于4G信号强度,目前我使用的安卓API里并没有提供获取强度功能,所以只能自己查了一下资料,发现貌似没有一个很好的简单的解决方案。所以自己在上面的代码中加了自己添加的判断,我的判断并不是正确的解决方案。另外如注释所说,还可能在某些机型上存在解析错误的bug。但是在我的测试机上勉强能用了。然后在Cocos工程里调用上述JAVA方法。

在C++层:

在自己的C++文件里添加JniHelper相关的类来调用JAVA方法。

#include "platform/android/jni/JniHelper.h"
再通过方法就能调用到JAVA里的函数信息了。
static bool getStaticMethodInfo(JniMethodInfo &methodinfo, const char *className, const char *methodName, const char *paramCode);
static bool getMethodInfo(JniMethodInfo &methodinfo, const char *className, const char *methodName, const char *paramCode);

可以参考http://blog.csdn.net/luxiaoyu_sdc/article/details/15874505。

然后在代码里实现getNetworkType()返回当前网络类型和getNetLevle()返回当前信号强度。如下:

const string& TestClass::getNetworkType(void)   //返回当前网络类型(wifi or mobile)
	{
		static string strNetworkType;
#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)			//如果是IOS系统
		strNetworkType = INVOKEOC_MGR->getNetworkType();  //这是获得IOS平台网络类型的方法,在此不提
#elif (CC_TARGET_PLATFORM == CC_PLATFORM_WIN32)			//windows
		strNetworkType = "windows";
#elif (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)	//如果是Android系统,则调用JAVA类里的getNetworkType()方法,返回当前网络类型。


		cocos2d::JniMethodInfo t;
		if (cocos2d::JniHelper::getStaticMethodInfo(t, g_szJavaPackage, "getNetworkType", "()Ljava/lang/String;"))
		{
			jstring ret = (jstring)t.env->CallStaticObjectMethod(t.classID, t.methodID);
			strNetworkType = cocos2d::JniHelper::jstring2string(ret);
			t.env->DeleteLocalRef(ret);
			t.env->DeleteLocalRef(t.classID);
		}
#endif

		return strNetworkType;
	}

	const int TestClass::getNetLevel(void)   //返回当前手机信号强度
	{
		int out_NetLevel = 1000;
#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)      //如果是IOS系统
		out_NetLevel = INVOKEOC_MGR->getNetLevel();
#elif (CC_TARGET_PLATFORM == CC_PLATFORM_WIN32)   

#elif (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)   //如果是Android系统,和上面的getNetworkType()方法一样,通常返回值是(int)0-4(弱->强)
		JniMethodInfo t;
		bool isHave = JniHelper::getStaticMethodInfo(t, g_szJavaPackage, "getNetInfo", "()[I");
		if (isHave)
		{
			jintArray msg = (jintArray)t.env->CallStaticObjectMethod(t.classID, t.methodID);
			int len = t.env->GetArrayLength(msg);
			jint* elems = t.env->GetIntArrayElements(msg, 0);
			if (2 == len)
			{
				out_NetLevel = elems[1];
			}
			t.env->DeleteLocalRef(t.classID);
		}
		else
		{
			cocos2d::log("JniFun call getNetInfo error!");
		}
#endif
		CCLOG("TestClass::getNetInfo ===== getNetInfo1:%d", out_NetLevel);
		return out_NetLevel;
	}

在Lua层:

要在Lua中使用自定义的C++方法,自然需要让C++和Lua交互,要用到tolua++等,在此不提。

/*
**重要代码**
tolua_function(tolua_S,"getNetLevel", lua_class_TestClass_getNetLevel);
tolua_function(tolua_S,"getNetworkType", lua_class_TestClass_getNetLevel);
**重要代码**
*/

让C++绑定Lua,获取网络类型:

int lua_class_TestClass_getNetworkType(lua_State* tolua_S)
	{
		int argc = 0;
		bool ok = true;

		//参数判断
		argc = lua_gettop(tolua_S) - 1;
		if (argc == 0)
		{
			string ret = TestClass::getInstance()->getNetworkType();
			tolua_pushcppstring(tolua_S, ret);
			return 1;
		}
		luaL_error(tolua_S, "%s , %d, was expecting %d \n", "TestClass::getInstance():getNetworkType", argc, 0);
		return 0;
	}
获取信号强度:
int lua_class_TestClass_getNetLevel(lua_State* tolua_S)
	{
		int argc = 0;
		bool ok = true;

		//参数判断
		argc = lua_gettop(tolua_S) - 1;
		if (argc == 0)
		{
			int ret = TestClass::getInstance()->getNetLevel();
			tolua_pushnumber(tolua_S, (lua_Number)ret);
			return 1;
		}
		luaL_error(tolua_S, "%s, %d, was expecting %d \n", "TestClass::getInstance():getNetInfo", argc, 0);
		return 0;
	}
之后在Lua中调用(注意下面的TestClass是经过Lua和C++交互转换的,不能直接使用C++里的TestClass类)。

local NetworkType = TestClass:getNetworkType()            -- MOBILE  or WIFI
local NetLevel = TestClass:getNetLevel()                  --  0-4(弱到强)


晚饭后编辑,错误多多,希望有错请指出。




推荐阅读
  • Java容器中的compareto方法排序原理解析
    本文从源码解析Java容器中的compareto方法的排序原理,讲解了在使用数组存储数据时的限制以及存储效率的问题。同时提到了Redis的五大数据结构和list、set等知识点,回忆了作者大学时代的Java学习经历。文章以作者做的思维导图作为目录,展示了整个讲解过程。 ... [详细]
  • SpringBoot uri统一权限管理的实现方法及步骤详解
    本文详细介绍了SpringBoot中实现uri统一权限管理的方法,包括表结构定义、自动统计URI并自动删除脏数据、程序启动加载等步骤。通过该方法可以提高系统的安全性,实现对系统任意接口的权限拦截验证。 ... [详细]
  • 本文介绍了Redis的基础数据结构string的应用场景,并以面试的形式进行问答讲解,帮助读者更好地理解和应用Redis。同时,描述了一位面试者的心理状态和面试官的行为。 ... [详细]
  • 计算机存储系统的层次结构及其优势
    本文介绍了计算机存储系统的层次结构,包括高速缓存、主存储器和辅助存储器三个层次。通过分层存储数据可以提高程序的执行效率。计算机存储系统的层次结构将各种不同存储容量、存取速度和价格的存储器有机组合成整体,形成可寻址存储空间比主存储器空间大得多的存储整体。由于辅助存储器容量大、价格低,使得整体存储系统的平均价格降低。同时,高速缓存的存取速度可以和CPU的工作速度相匹配,进一步提高程序执行效率。 ... [详细]
  • Java中包装类的设计原因以及操作方法
    本文主要介绍了Java中设计包装类的原因以及操作方法。在Java中,除了对象类型,还有八大基本类型,为了将基本类型转换成对象,Java引入了包装类。文章通过介绍包装类的定义和实现,解答了为什么需要包装类的问题,并提供了简单易用的操作方法。通过本文的学习,读者可以更好地理解和应用Java中的包装类。 ... [详细]
  • Imtryingtofigureoutawaytogeneratetorrentfilesfromabucket,usingtheAWSSDKforGo.我正 ... [详细]
  • 先看官方文档TheJavaTutorialshavebeenwrittenforJDK8.Examplesandpracticesdescribedinthispagedontta ... [详细]
  • JDK源码学习之HashTable(附带面试题)的学习笔记
    本文介绍了JDK源码学习之HashTable(附带面试题)的学习笔记,包括HashTable的定义、数据类型、与HashMap的关系和区别。文章提供了干货,并附带了其他相关主题的学习笔记。 ... [详细]
  • Whatsthedifferencebetweento_aandto_ary?to_a和to_ary有什么区别? ... [详细]
  • Android系统源码分析Zygote和SystemServer启动过程详解
    本文详细解析了Android系统源码中Zygote和SystemServer的启动过程。首先介绍了系统framework层启动的内容,帮助理解四大组件的启动和管理过程。接着介绍了AMS、PMS等系统服务的作用和调用方式。然后详细分析了Zygote的启动过程,解释了Zygote在Android启动过程中的决定作用。最后通过时序图展示了整个过程。 ... [详细]
  • Week04面向对象设计与继承学习总结及作业要求
    本文总结了Week04面向对象设计与继承的重要知识点,包括对象、类、封装性、静态属性、静态方法、重载、继承和多态等。同时,还介绍了私有构造函数在类外部无法被调用、static不能访问非静态属性以及该类实例可以共享类里的static属性等内容。此外,还提到了作业要求,包括讲述一个在网上商城购物或在班级博客进行学习的故事,并使用Markdown的加粗标记和语句块标记标注关键名词和动词。最后,还提到了参考资料中关于UML类图如何绘制的范例。 ... [详细]
  • 基于Socket的多个客户端之间的聊天功能实现方法
    本文介绍了基于Socket的多个客户端之间实现聊天功能的方法,包括服务器端的实现和客户端的实现。服务器端通过每个用户的输出流向特定用户发送消息,而客户端通过输入流接收消息。同时,还介绍了相关的实体类和Socket的基本概念。 ... [详细]
  • 本文介绍了MVP架构模式及其在国庆技术博客中的应用。MVP架构模式是一种演变自MVC架构的新模式,其中View和Model之间的通信通过Presenter进行。相比MVC架构,MVP架构将交互逻辑放在Presenter内部,而View直接从Model中读取数据而不是通过Controller。本文还探讨了MVP架构在国庆技术博客中的具体应用。 ... [详细]
  • 本文介绍了Swing组件的用法,重点讲解了图标接口的定义和创建方法。图标接口用来将图标与各种组件相关联,可以是简单的绘画或使用磁盘上的GIF格式图像。文章详细介绍了图标接口的属性和绘制方法,并给出了一个菱形图标的实现示例。该示例可以配置图标的尺寸、颜色和填充状态。 ... [详细]
  • 欢乐的票圈重构之旅——RecyclerView的头尾布局增加
    项目重构的Git地址:https:github.comrazerdpFriendCircletreemain-dev项目同步更新的文集:http:www.jianshu.comno ... [详细]
author-avatar
吴由兴_834
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有