以下是各种错误:
安装eclipse和adt插件,adt插件必须是zip压缩包,且解压出来就可以看到jar包,否则检查不到adt。有时需要放到eclipse目录的plugins文件夹下。
https://blog.csdn.net/tomatulip/article/details/75453780 各个版本adt下载地址。
eclipse的adt插件必须和sdk manager版本相对应,一般更新了sdk,adt就需要相应的更新,否则无法创建工程。
如果是adt版本过高,请升级sdk。如下更新速度会很快。
在SDK Manager -> tools -> options中:
HTTP Proxy Server: mirrors.neusoft.edu.cn
HTTP Proxy Port: 80
勾选: Force https:// ...sources to be ...
或者换一个低版本的adt。
eclipse查看adt版本,Help > About Eclipse ,进入页面,点击细节。查看Android Development Toolkit。
下载最新版本ADT-23.0.7。然后更新sdk manager。发现sdk manager一闪而过。
Eclipse报错: Failed to get the required ADT version number from the SDK,最近通过Adroid Studio升级了SDK;结果Eclipse导致了这样的问题。解决方法之一:Adroid Studio 2.3之后不能和Eclipse共用一个SDK,给Eclispe重新配置一个SDK路径,即重新拷贝一份。拷贝之后肯定是没用的,因为android studio更新过sdk之后,会将sdk下的tools文件里的内容重新处理,所以eclipse就不能正常使用了。解决办法是下载新的tools文件夹和新的sdk manager,下载android-sdk_r24.4.1-windows就可以了。
在这个http://www.androiddevtools.cn/网站下载相应的SDK Tools压缩包就可以了。
都搞定之后,下载了一个最新的adt,但是发现并没有sdk avd的图标,到 Windows -> Perspective -> Customize Perspective去勾选就行了。
以下2篇是如何勾选的文章:
https://www.cnblogs.com/oukunqing/p/6728969.html
https://blog.csdn.net/jhjyear/article/details/43225629
以下是关于sdk manager哪些东西是需要下载的:
https://blog.csdn.net/jing__jie/article/details/74418691
错误:Android library projects cannot be launched的解决方法如下:
https://blog.csdn.net/w88193363/article/details/8528475
devices.xml文件出错的解决方法如下:
https://blog.csdn.net/xb12369/article/details/50510302?locationNum=9&fps=1
错误:Failed to load E:\SDK_For_Eclipse\SDK\build-tools\28.0.2\lib\dx.jar,这表示adt和sdk tools版本不匹配,在sdk manager里删掉相应的高版本就行了。另外,adt如果版本是23,那对应的sdk tools的版本也应该是23。
eclipse本身是有版本的,eclipse本身需要adt也达到某个最低版本,然后sdk再去对应adt版本。
另外,如果eclipse本身版本过低,那它就只能装低版本的sdk,一旦装了高版本的sdk,无论
什么版本的adt和sdk tools对应都没用。就是无法创建android工程。或者创建了工程,但是
错误This Android SDK requires Andr...ate ADT to the latest version.
这样的问题很好解决,一个升级ADT到指定版本或以上,另一个简单的办法是调低SDK版本。
如下:
https://zhidao.baidu.com/question/1818992187676541148.html
错误nno target available如下,加个/就好了:
https://zhidao.baidu.com/question/220357787.html
错误:This AVD's configuration is missing a kernel file!试了,没查证。
https://blog.csdn.net/qq503393230/article/details/39610545
以下几个重要的:src,gen,assets,bin,libs,res,androidmanifest.xml。
1,src:自定义的java类,符合java的命名规范,分包。
2,gen:自动生成,自动维护的文件,分类管理android的res文件夹下的资源。比如R.java类里面会自动将用上的资源添加唯一标示符在里面,注意:资源名字默认小写,大写会出错,如果有出错,那R.java将不会继续自动维护。
3,assets:原生资源文件,通常是一些不会经常修改的资源,比如打开apk时的logo等。
4,bin:包含编译生成的apk应用程序,xx.apk。
5,libs:第3方库,jar包。
6,res:
darwable-xxxdpi图片资源,hdpi,ldpi,mdpi分别对应不同清晰度。
layout:布局文件,各种ui控件拖放。
menu:菜单。
android:应用菜单。
values:字符串资源文件,通常用在手机国际化。
7,Androidmanifest.xml:清单文件。
8,Android 4.1和Android Dependencies:android提供的环境。
1,在Activity中添加了 android:configChanges属性,目的是当所指定属性(Configuration Changes)发生改变时,通知程序调用 onConfigurationChanged()函数
2,android.intent.category.LAUNCHER决定应用决定应用程序是否显示在程序列表里。当将该App安装到手机上,在手机桌面上会出现相应的图标。详细如下:
https://blog.csdn.net/ahence/article/details/42676933
category的用途还有很多:
比如做个桌面,按home键时启动自己做的应用。
https://blog.csdn.net/jason0539/article/details/10049899 关于过滤
过滤有2种,implicit(隐藏) intent,explicit(明确) intent。
Explicit Intent明确的指定了要启动的Acitivity ,比如以下Java代码:
Intent intent= new Intent(this, B.class);
startActivity(new Intent(MainActivity.this, NextActivity.class));转到下一个activity。
理论上来说,如果intent不指定category,那么无论intent filter的内容是什么都应该是匹配的。但是,如果是implicit intent,android默认给加上一个CATEGORY_DEFAULT,这样的话如果intent filter中没有android.intent.category.DEFAULT这个category的话,匹配测试就会失败。所以,如果你的 activity支持接收implicit intent的话就一定要在intent filter中加入android.intent.category.DEFAULT。
如下写法,xml文件要加上activity内容,注意action和category:
<activity
android:name=".MainActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
intent-filter>
activity>
<activity android:name=".NextActivity" >
<intent-filter>
<action android:name="XXXnextActivityTestTest" />
<category android:name="android.intent.category.DEFAULT" />
intent-filter>
activity>
代码如下:
Intent intent = new Intent("XXXnextActivityTestTest");
startActivity(intent);
Intent intent = new Intent();
intent.setAction("XXXnextActivityTestTest");
startActivity(intent);
过滤的组成由:intent到底发给哪个activity,需要进行三个匹配,一个是action,一个是category,一个是data。在不直接指定要跳转的Activity的时候,为Intent提供一些相关的参数,让其自动去和AndroidManifest.xml中已有的Activity去匹配。
我们通过Intent的构造函数或者Intent提供的方法可以指定这个三个参数:
intent.setAction(action);
intent.addCategory(category);
intent.setData(data);
关于data:https://www.jianshu.com/p/37f3ea4fd3d6
android:name="string" android:resource="resource specification" android:value="string" /> android:name:该item的唯一名称。 android:resource:对资源的引用。其值为资源的ID,可以通过该Bundle的 Bundle.getIn()方法获取其ID值 android:value:分配给该item的值。 Data的值都存储在单个Bundle对象中,并作为PackageItemInfo.metaData字段提供给父控件。读取data数据: ApplicationInfo ai = getPackageManager().getApplicationInfo(getPackageName(),PackageManager.GET_META_DATA); Bundle bundle = ai.metaData; String myApiKey = bundle.getString("my_test_metagadata"); Data还可以用于第3方库或APIs: 完整编写如下: 当运行我们的Android应用程序时,Android操作系统首先会去找我们的AndroidManifest.xml这个文件,这个文件是我们应用程序的主配置文件,因为我们一个应用可能有多个的Activity,那我们首先会展示哪个Activity呢?这个主配置文件就定义了当前这个应用默认所加载的那个Activity对象,找到这个Activity对象后,就会调用其onCreate()方法,这个方法主要就是用来加载我们的布局文件的,通过 setContentView()方法可以来加载我们指定的布局文件,最后根据布局文件中的各个控件显示在我们的屏幕上。这个就是我们Activity的启动流程。 xml: Intent 意图 filter 过滤 category 类别 LAUNCHER 启动器 找到相匹配的意图过滤器所在的Activity元素,再根据 public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); super.setContentView(R.layout.main); } } super.onCreate:调用父类Activity的OnCreate方法来实现对界面的画图绘制工作。 SetContentView:加载一个界面,找到"res"目录下的"layout"子目录下main.xml文件的标识符。 1,Unity调用Android: 获得一个类,不是类的对象: AndroidJavaClass jc = new AndroidJavaClass("com.example.callwifistrength.MyTestActivity"); , 使用类名,获得一个静态的属性,并且返回该属性,且该属性为当前类类型(当然也可以是int类型): AndroidJavaObject joCurrent = jc.GetStatic jc.GetStatic 使用对象,获得一个普通属性: joCurrent.Get 使用类名,调用一个静态的方法,没人任何返回,和返回某种类型的值: jc.CallStatic(""); int jjjj = jc.CallStatic AndroidJavaObject joCurrent = jc.CallStatic 使用对象,调用一个普通方法,且返回值为int: joCurrent(类的一个对象).Call 设置某个变量,某个静态变量的值。 joCurrent(类的一个对象).Set jc(类名).SetStatic 2,Android调用Unity: //参数分别是:对象名字,函数名(该对象上的某个类的函数),传给函数的参数 UnityPlayer.UnitySendMessage(_objName, _funcStr, _content); Android里的Activity是用户能够操作的活动界面。 1,如果没有android插件时,androidmanifest内容为: package="week.storm.snk" 包名 5.X以上版本 导出apk安装包的默认入口类名字为 com.unity3d.player.UnityPlayerActivity。 5.X以下的版本(亲验证4.6.3)的入口类名字则为 com.unity3d.player.UnityPlayerNativeActivity。 2,如果有插件,但是该插件没有继承UnityPlayerActivity也没有继承android的其他activity时的内容: package="com.example.callwifistrength"包名 因为没有继承activity,所以依旧是这个作为入口。androidmanifest也没有加其他activity。 3,如果存在继承自UnityPlayerActivity时,androidmanifest内容: package="com.example.callwifistrength"包名 activity应该是和onCreate()方法通过,使用setContentView()加载我们指定的布局文件有关系。activity和类里面有哪些业务逻辑并没有关系。所以只要和布局没有关系就同一默认写"com.unity3d.player.UnityPlayerNativeActivity" 肯定没错。 网上摘抄:继承UnityPlayerActivity这个类,继承后MainActivty就是游戏的入口文件了,也就不需要布局了,直接把setContentView这一行删除,最好把res-layout下的布局也一并删除了。 4,如果没有继承UnityPlayerActivity,但是继承了android的activity(这个类ActionBarActivity)会怎么样? 首先androidmanifest只写一个activity时,如下: 这说明,androidmanifest的主activity一定是和unity有关的activity。 如果只写一个activity为如下时: android:name="com.unity3d.player.UnityPlayerNativeActivity" 可以进入apk,但是无法调用android里写好的方法,属性。 如果同时写2个: 继承自android的activity无论怎么写都不能在unity里生效,没有查到相关资料,只能暂时判定继承自android的activity在unity里无效。 当然,以上的操作仅仅是实验而已,而我对android并不了解,所以可能存在一些其他因素。 一个技巧:不继承任何activity,但是,通过unity调用该类,将unity当前的activity传入, 然后该类就拿到了当前的activity。测试可行。 unity可以拿到android里的类,对象,属性。android可以拿到到unity对象的某个函数并执行该函数。如果有些信息必须通过android的原生接口去取,那有2种方式: 1,直接通过unity的UnityPlayerActivity去获取,直接在unity里操作就可以了,不需要jar包。 2,创建android工程,导出jar包,再在unity里去取数据。 比如“获取移动网络信号,它只能在android里通过注册监听事件,当信号产生变化时才调用”,这种就只能写在android工程里,推荐的方法是创建的类不要继承任何activity,仅仅是业务逻辑就行,需要的和activity有关的东西通过"com.unity3d.player.UnityPlayer"的类给予(比如将UnityPlayerActivity当成参数传递到android)。 1,只能有一个继承自UnityPlayerActivity的类。不会存在多个,可以由一个管理类同一处理。 2,res文件夹下的资源正常情况下没有任何作用。, 3,导出的jar包只需要src也就是类就行了。其他的libs,res文件夹是不需要导出的。, 4,单纯的java类,就是单纯的一些业务逻辑而已。是拿不到activity里提供的一些服务的。 但是可以通过unity调用相应的函数将activity传递进去,也可以使用unitysendmessage从unity里面拿。 5,unity只有在主线程才能调android的方法,就好像只有在主线程里才可以使用继承自mono的功能一样。 6,继承关系 MyActivity(自定义的类,继承UnityPlayerActivity) <-- UnityPlayerActivity <--UnityPlayerNativeActivity <-- NativeActivity<-- Activity 在 UnityPlayerNativeActivity 这个类中,声明了一个UnityPlayer对象并在oncreate方法里面初始化了这个对象, 把UnityPlayerNativeActivity上下文作为参数传了进去,然后在UnityPlayer类的构造方法中, 把当前的上下文赋值给了currentActivity。MyActivity是主Activity,Unity程序一启动就会调用这个Activity, 他是在AndroridManifest.xml中配置的.他需要继承UnityPlayerActivity,就是我们刚刚引入的class.jar包中的接口类. 接着我们配置本程序的AndroidManifest.xml。 android打包导入到unity: 对于调用android原生接口,有2种方式,1,unity将工程导出到android。2,android打包导入到unity。 对于导入Library的Plugins接入方式: 一般u3d的SDK会直接提供代码+资源的形式,但Library并没有直观的给出这两者,不过我们可以自己把它分离出来:也就是在unity项目的android文件夹下放: 1,代码:libs文件夹下,分2种,一种是jar包的形式,一种是so库文件的形式。jar包即为源码,so文件一般是一些依赖库,放在不同的ABI文件夹里面(armeabi),所以so是放在文件夹里,jar是直接放。 对于so文件:u3d编译的时候支持的cpu类型主要有两种,一种是armeabi-v7a,一种是x86,所接入的SDK最好需要有这两个cpu类型的so文件。 2,资源:资源通常是放在res文件夹中(也有可能放在assets中),要注意的是当接入多个SDK的时候,value里面的string等资源的id不要重复了。 3,配置:一般只有AndroidManifest文件。 我们分离出这三个部分,就可以把这个几个部分分别放到Plugins对应的文件夹中去了。 对于androidManifest: package:指定本应用内java主程序包的包名,它也是一个应用进程的默认名称 Application:一个AndroidManifest.xml中必须含有一个Application标签 intent-filter属性: action很简单,只有android:name这个属性。常见的android:name值为android.intent.action.MAIN,表明此activity是作为应用程序的入口。 category也只有android:name属性。常见的android:name值为android.intent.category.LAUNCHER(决定应用程序是否显示在程序列表里) 修改 AndroidManifest.xml: 工程里已经有了AndroidManifest.xml,在导入jar时,需要合并2个AndroidManifest.xml。 一个 AndroidManifest.xml 只有一个主 activity (直接的观察就是这个 activity 标签中包含了下面这段标签)。 unity工程,需要将继承了 UnityPlayerActivity 或者 UnityNativePlayerActivity 的 Activity设置为启动 Activity ,才可以在 Android 平台(说白了就是手机等等)启动你的 unity 工程。在 AndroidManifest.xml 中将这个 Activity 注册为主 Activity 。 主 activity 的 android:name 需要为 用于导出 jar 的 Library 的包名 + 我们导出的 jar 的主类名: Package name :com.example.myjar(这个包名,其实也就是 unity 工程 Player Settings 中填写的包名,因为他们需要一致) com.example.myjar.MyActivity 这个直接使用unity提供的的方法就行。 SystemInfo.batteryStatus 充电,放电等,可以直接在unity里查看。 SystemInfo.batteryLevel 0-1 之间, 如果目标平台上没有电池电量,则此属性返回-1。 string.Format("{0}:{1}",DateTime.Now.Hour,DateTime.Now.Minute) 按照格式获得系统时间。 这个需要获取android原生的信息。这里先说下android和unity交互的一些方法,最后才是wifi和移动网络强度获取。 获取wifi信号强度,可以直接在unity里获取,这种方法不需要打jar包。 public static int GetWifiStrength() { AndroidJavaClass contextClass = new AndroidJavaClass("android.content.Context"); //拿到一个静态的规定好的字符串 string WIFI_SERVICE = contextClass.GetStatic AndroidJavaClass jc = new AndroidJavaClass("com.unity3d.player.UnityPlayer"); AndroidJavaObject joCurrent = jc.GetStatic //通过函数getSystemService获得操作wifi相关的对象 AndroidJavaObject joWifi = joCurrent.Call AndroidJavaObject joWifiInfo = joWifi.Call int level = joWifiInfo.Call return level; } 对应的android里的方法如下: public int obtainWifiStrength(){ WifiManager wifi_servicve = (WifiManager) getSystemService(WIFI_SERVICE); WifiInfo connectionInfo = wifi_servicve.getConnectionInfo(); //得到的值是一个0到-100的区间值,是一个int型数据,其中0到-50表示信号最好,-50到-70表示信号偏差,小于-70表示最差,有可能连接不上或者掉线,一般Wifi已断则值为-200。 int level = connectionInfo.getRssi(); return level; } 在AndroidManifest里加上网络相关权限: 获取移动网络信号,只能通过在android里注册点击事件来获取,只有导jar包的方法来做。 java类并没有继承任何activity,需要activity服务的时候通过unity提供传递。这里有2种方式处理m_dbm值。 1,直接在unity里定时去取,我目前使用了这种。 2,在触发监听事件时,使用UnitySendMessage调用unity的函数将m_dbm的值传递到unity。 import android.telephony.SignalStrength; import android.telephony.TelephonyManager; public class MyTestActivity { //通过"com.unity3d.player.UnityPlayer",在unity里初始化currentActivity。 public static UnityPlayerActivity currentActivity; public static void setActivity(Activity act) { currentActivity = (UnityPlayerActivity)act; } public static int m_dbm = 0; public static MyTestActivity myCurrentActivity = new MyTestActivity(); TelephonyManager tm; PhoneStateListener mylistener; public void initListenerNetDBMParam() { tm = (TelephonyManager)currentActivity.getSystemService(Context.TELEPHONY_SERVICE); mylistener = new PhoneStateListener(){ //@Override public void onSignalStrengthsChanged(SignalStrength signalStrength) { super.onSignalStrengthsChanged(signalStrength); //通过signalStrength来拿到移动网络的信号信息 //第1种方式 https://blog.csdn.net/sinat_31057219/article/details/81134030 int asu = signalStrength.getGsmSignalStrength(); m_dbm = -113 + 2*asu; //api23 android6.0以上才可以使用 //level = signalStrength.getLevel(); //第2种方式 https://blog.csdn.net/cdzz11/article/details/52197732 } }; } public void ListenerNetDBM() { //开始监听 tm.listen(mylistener, PhoneStateListener.LISTEN_SIGNAL_STRENGTHS); } public void removeListenerNetDBM() { //取消监听 tm.listen(mylistener, PhoneStateListener.LISTEN_NONE); } } 在AndroidManifest里加上网络相关权限: 5,定位服务开启 /** @Override public static void OpenChatGps() 1,使用Unity的Activity才可以跳转到定位开启界面 3,一些android基础知识
1,android结构,执行流程。
2,实际代码
Android与Unity交互
1,unity与android交互的函数
2,unity导入jar包的几种情况
3,unity与android交互的2种方式
4,其他的一些相关的知识
5,懒得整理的一些知识
实际的一些应用
1,电池电量wifi移动网络的获取
1,电量,时间相关的信息的获取
2,wifi和移动网络强度的获取
3,获取wifi信号强度
4,获取移动网络信号
* Android6.0申请权限的回调方法
*/
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
testCB = "onRequestPermissionsResult fail 1 ";
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
switch (requestCode) {
// requestCode即所声明的权限获取码,在checkSelfPermission时传入
case BAIDU_READ_PHONE_STATE:
//如果用户取消,permissions可能为null.
if (grantResults[0] == PackageManager.PERMISSION_GRANTED && grantResults.length > 0) { //有权限
// 获取到权限,作相应处理
testCB = "onRequestPermissionsResult success";
} else {
testCB = "onRequestPermissionsResult fail";
}
break;
default:
break;
}
}
public void onActivityResult(int requestCode, int resultCode, Intent data) {
testCB = "onActivityResult fail "+requestCode;
super.onActivityResult(requestCode, resultCode, data);
switch (requestCode) {
case PRIVATE_CODE:
if(data == null) {
testCB = "onActivityResult fail "+resultCode;
}else {
testCB = "onActivityResult success" + resultCode+" "+data.getExtras().getString("result");
}
break;
}
}
public void showGPSContacts(Activity activity) {
LocationManager locationManager = (LocationManager) activity.getSystemService(Context.LOCATION_SERVICE);
boolean isOpen = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
if (isOpen) {//开了定位服务
if (Build.VERSION.SDK_INT >= 23) { //判断是否为android6.0系统版本,如果是,需要动态添加权限
if (ContextCompat.checkSelfPermission(activity, Manifest.permission.ACCESS_FINE_LOCATION)
!= PackageManager.PERMISSION_GRANTED) {
// 没有权限,申请权限。
Toast.makeText(activity, "没有权限", Toast.LENGTH_SHORT).show();
ActivityCompat.requestPermissions(activity, LOCATIONGPS,
BAIDU_READ_PHONE_STATE);
} else {
testCB = "7";
}
}
} else {
Toast.makeText(activity, "系统检测到未开启GPS定位服务,请开启", Toast.LENGTH_SHORT).show();
//跳转到手机原生设置页面
Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
activity.setResult(100, intent);
activity.startActivityForResult(intent,PRIVATE_CODE);
// activity.finish(); 退出应用
}
}
{
#if UNITY_ANDROID && !UNITY_EDITOR
AndroidJavaClass jc = new AndroidJavaClass("setGps.SetGps");
AndroidJavaObject instance = jc.GetStatic
AndroidJavaClass jc2 = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
AndroidJavaObject joCurrent = jc2.GetStatic
instance.Call("showGPSContacts", joCurrent);
Input.location.Start(10.0f, 10.0f);
#endif
}
2,继承自Unity的Activity且在AndroidManifest中写入该类作为入口,才会触发定位服务的回调函数,目前回调函数没有参数数据,暂时没有找到原因
3,检查权限会报错,因为support-v4包版本不对,下载最新版本,并且导入到Unity中,因为sdk中的support-v4包就不对
4,本来这些行为除了回调函数外都可以在Unity中处理,但类中的静态类,某些jar包中的类好像不能从Unity中直接拿到