本文主要完成两个功能,附上完整流程代码,以便后续查看
使用Unity5.6.3 JavaEclipse(Androidsdk同级目录)
ps:已测2017.3通过,需要增加定位权限
功能一:Unity应用实现开机自启动 获取电量WIFI等
1:创建项目 File--Android Application Project
2:导入class.jar BuildPath-->Add External Archieves-->class.jar(使用Unity5.6.3测试)
D:\Program Files\Unity5.6.3\Editor\Data\PlaybackEngines\AndroidPlayer\Variations\mono\Release\Classes
注意工程上方的Package Explorer!选错了就不会有Add External Archieves选项
增加WIFI权限(也可以在Unity里手动增加)
3:代码模块
MainActivity.java
package com.example.getinfo;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import com.unity3d.player.UnityPlayerActivity;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
public class MainActivity extends UnityPlayerActivity {
private static Context instance;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
instance = getApplication();
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
//获取手机当前电量、总电量(默认其实都是100)、当前状态(充电还是放电)
//其余数据例如电压、电池温度用的较少
public String MonitorBatteryState()
{
IntentFilter iFilter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
Intent intent = instance.registerReceiver(null, iFilter);
int rawLevel = intent.getIntExtra("level", 0); //获得当前电量
int scale = intent.getIntExtra("scale", 0); //获得总电量
int status = intent.getIntExtra("status", 0); //电池充电状态
int health = intent.getIntExtra("voltage", 0); //电池健康状况
int batteryV = intent.getIntExtra("voltage", 0); //电池电压(mv)
int temperature = intent.getIntExtra("temperature", 0); //电池温度(数值)
double t = temperature / 10.0; //电池摄氏温度,默认获取的非摄氏温度值,需做一下运算转换
String targetStr = "";
int level = -1;
if(rawLevel > 0 && scale > 0)
{
level = (rawLevel * 100) / scale;
targetStr = level + "|" + scale + "|" + status;
}
return targetStr;
}
//获取Wifi信号强度
@SuppressWarnings("deprecation")
private String ObtainWifiInfo()
{
String result = "";
WifiManager wifiManager = (WifiManager)getApplication().getSystemService(WIFI_SERVICE);
WifiInfo info = wifiManager.getConnectionInfo();
if(info.getBSSID() != null)
{
//链接信号强度
int strength = WifiManager.calculateSignalLevel(info.getRssi(), 5);
//链接速度
int speed = info.getLinkSpeed();
//链接速度单位
String units = WifiInfo.LINK_SPEED_UNITS;
//Wifi源名称
String ssid = info.getSSID();
int ip = info.getIpAddress();
String mac = info.getMacAddress();
result = strength + "|" + IntToIp(ip) + "|" + mac + "|" + ssid;
}
return result;
}
private String IntToIp(int paramInt)
{
return (paramInt & 0xFF) + "." + (0xFF & paramInt >> 8) + "." + (0xFF & paramInt >> 16) + "." + (0xFF & paramInt >> 24);
}
}
AndroidMainfest.xml文件
只是获取电量WIFI以上就行!
(拓展)开机自启动 新建一个class
BootBroadcastReceiver.java
package com.example.getinfo;
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import com.unity3d.player.UnityPlayerNativeActivity;
import com.unity3d.player.UnityPlayer;
import com.unity3d.player.UnityPlayerActivity;
public class BootBroadcastReceiver extends BroadcastReceiver {
private final String ACTION_BOOT = "android.intent.action.BOOT_COMPLETED";
@Override
public void onReceive(Context context, Intent intent) {
if(intent.getAction().equals(ACTION_BOOT)){
Intent myIntent = new Intent(context,MainActivity.class);
myIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(myIntent);
}
}
}
加入AndroidMainfest文件中(一定要添加开机自启权限和reciever)
4:导出jar
5:导入Unity里
6:新建脚本Test.cs
新建场景后创建一个button 两个text,最好多一个button为了退出应用
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class Test : MonoBehaviour
{
public Button button;
public Text phonePowerText;
public Text wifiText;
private string batteryData;
private string wifiData;
void Awake()
{
button.onClick.AddListener(OnButtonClicked);
}
private void OnButtonClicked()
{
AndroidJavaClass jc = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
AndroidJavaObject jo = jc.GetStatic("currentActivity");
batteryData = jo.Call("MonitorBatteryState");
wifiData = jo.Call("ObtainWifiInfo");
OnBatteryDataBack(batteryData);
OnWifiDataBack(wifiData);
}
//安卓那边将数据以“|”进行分割,所以这边以"|"来分割数据
private void OnBatteryDataBack(string data)
{
phonePowerText.text = "";
string[] args = data.Split('|');
if (args[2] == "2")
{
phonePowerText.text += "电池充电中\n";
}
else
{
phonePowerText.text += "电池放电中\n";
}
int curPower = int.Parse(args[0]);
float power = float.Parse(args[1]);
float percent = curPower / power;
phonePowerText.text += " cur power:" + curPower;
phonePowerText.text += " all power:" + power;
phonePowerText.text += " 电量比例:" + (Mathf.CeilToInt(percent * 100) + "%").ToString();
}
private void OnWifiDataBack(string data)
{
wifiText.text = "";
wifiText.text += wifiData;
string[] args = wifiData.Split('|');
int wifiLevel = int.Parse(args[0]);
wifiText.text += "Wifi信号格数:" + wifiLevel.ToString() + "\n";
string ip = "IP:" + args[1] + "\n";
string mac = "MAC:" + args[2] + "\n";
string ssid = "Wifi Name:" + args[3] + "\n";
wifiText.text += ip;
wifiText.text += mac;
wifiText.text += ssid;
}
}
6:打包 Pakage Name需要和Eclipse里的包名一致!!!
到这里恭喜你,打包成功!!!
可能出现的问题如下:
1:获取不到WIFI名字,显示unknown ssid
解决办法:
a: 把Unity里Android目录下的AndroidMainfest文件修改了一下target API=25就行了,因为我Unity的Minimum API Level是16-25(红圈下方),和使用SDK Manager下载的API有关
b:还不行的话就增加定位权限,如下
2:以上测试通过了,换了个Unity版本,例如Unity2017.3 又出现unkown ssid 。通过修改API还是不行
解决办法:把Unity里Android目录下的AndroidMainfest文件增加一个 定位权限,就可以了
<结束>想了一下还是不附带工程了,毕竟每个人PC上安装Unity的路径不一样,class.jar 。有问题可以留言
<总结>可以同时导入多个class.jar ,一个WIFI权限基本足够
功能二:已有第三方SDK作为MainActivity,如何调取我们的Activity
PS:在游戏开发中我们参考如上已能实现功能,因为UnityPlayerActivity作为2D平面展示应用已经足够,比如手机上或平板上。但如果在VR开发中我们可能就没这个MainActivity了,它可能已经被占用。例如一体机PicoVR。这个时候主窗口是不能切换的,也就是说Actiivity不能切换,直接写一个不继承的java类你会发现报错很多,关键是在Unity里调用不到。我们通过Unity官方提供的AndoridJavaClass这个接口,可以调取currentActivity里的静态/非静态函数。但是在一个没有运行起来的Activity则无法调取非静态函数。
因此我们需要一个静态类或静态函数以供在任何需要的时候调用。
PS:上一个功能里的有些函数在static的驱动下要作出修改,如下
流程如下:
1:删除MainActivity,增加一个供调用的ThirdActivity.java类
package com.example.getinfo;
import com.unity3d.player.UnityPlayer;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.os.Bundle;
import android.app.Service;
public class ThirdActivity {
//获取电量
public static String MonitorBatteryState()
{
IntentFilter iFilter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
Intent intent = UnityPlayer.currentActivity.getApplicationContext().registerReceiver(null, iFilter);
int rawLevel = intent.getIntExtra("level", 0); //获得当前电量
int scale = intent.getIntExtra("scale", 0); //获得总电量
int status = intent.getIntExtra("status", 0); //电池充电状态
int health = intent.getIntExtra("voltage", 0); //电池健康状况
int batteryV = intent.getIntExtra("voltage", 0); //电池电压(mv)
int temperature = intent.getIntExtra("temperature", 0); //电池温度(数值)
double t = temperature / 10.0; //
String targetStr = "";
int level = -1;
if(rawLevel > 0 && scale > 0)
{
level = (rawLevel * 100) / scale;
targetStr = level + "|" + scale + "|" + status;
}
return targetStr;
}
//获取WIFI
public static String ObtainWifiInfo()
{
String result = "null";
WifiManager wifiManager = (WifiManager)(UnityPlayer.currentActivity.getApplicationContext()).getSystemService(Context.WIFI_SERVICE);
WifiInfo info = wifiManager.getConnectionInfo();
if(info.getBSSID() != null)
{
//链接信号强度
int strength = WifiManager.calculateSignalLevel(info.getRssi(), 5);
//链接速度
int speed = info.getLinkSpeed();
//链接速度单位
String units = WifiInfo.LINK_SPEED_UNITS;
//Wifi源名称
String ssid = info.getSSID();
int ip = info.getIpAddress();
String mac = info.getMacAddress();
result = strength + "|" + IntToIp(ip) + "|" + mac + "|" + ssid;
}
return result;
}
private static String IntToIp(int paramInt)
{
return (paramInt & 0xFF) + "." + (0xFF & paramInt >> 8) + "." + (0xFF & paramInt >> 16) + "." + (0xFF & paramInt >> 24);
}
}
2:此时的AndroidMainfest文件 (记得增加开机自启权限以及添加reciever)
可以看到此时是没有MainActivity的,并且BootBroadcastReciever类已报错,此处的MainActivity填入VR的MainActivity。例如Pico的是在vractivity.jar包里。使用com.XXX.UnityPicoNative.class.需要先导入jar包到Eclipse中
3:导出jar到Unity
说明:在没有MainActivity的情况下打包APK是无法安装运行的,这里是已有PicoVR作为主Activity。所以直接导入jar并打包APK
2019.07.25日更新
今天在做重启功能,很顺利的找到一篇文章。测试过OK
https://www.jianshu.com/p/c90f25539302
AndroidSdutio或者Eclipse里函数
public void doRestart(int Ntime)
{
Log.d("Unity", "========restart "+Ntime);
Intent restartIntent = getPackageManager()
.getLaunchIntentForPackage(getPackageName() );
PendingIntent intent = PendingIntent.getActivity(this, 0,restartIntent,0);
AlarmManager manager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
manager.set(AlarmManager.RTC, System.currentTimeMillis()+Ntime, intent);
finish();
android.os.Process.killProcess(android.os.Process.myPid());
}
Unity调用
public static void Restart(int delay)
{
AndroidJavaClass jc = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
AndroidJavaObject mainActivity = jc.GetStatic("currentActivity");
mainActivity.Call("doRestart", delay);
jc.Dispose();
mainActivity.Dispose();
}
上面能成功的前提是,你有一个MainActivity。通常建立一个Android工程,里面就有MainActivity。
这一段我也说了是用第三方的SDK。因此我没有MainActivity。所有都是静态调用
因此Eclipse代码修改如下
public static void doRestart()
{
Intent restartIntent = (UnityPlayer.currentActivity.getApplicationContext()).getPackageManager().getLaunchIntentForPackage((UnityPlayer.currentActivity.getApplicationContext()).getPackageName() );
PendingIntent intent = PendingIntent.getActivity((UnityPlayer.currentActivity.getApplicationContext()), 0,restartIntent,0);
AlarmManager manager = (AlarmManager) (UnityPlayer.currentActivity.getApplicationContext()).getSystemService(Context.ALARM_SERVICE);
manager.set(AlarmManager.RTC, System.currentTimeMillis()+1, intent);
UnityPlayer.currentActivity.finish();
android.os.Process.killProcess(android.os.Process.myPid());
}
精髓就在于 UnityPlayer.currentActivity.getApplicationContext() 。等于Context
细心的你也注意到。doRestart()并没有参数。对的,使用第三方静态调用的时候加了参数并没有成功
AndroidJavaClass jc2 = new AndroidJavaClass("com.pico.hasai.ThirdActivity");
//"com.pico.hasai" 包名
//ThirdActivity一个java脚本。无任何继承。作为被调用的管理类
jc2.CallStatic("doRestart");
jc2.Dispose();
到此。重启功能完毕。开心
未解决问题:
1:开机自启的时间太长。(推测和手机性能有关,和一体机初始化引导有关)
2:没有MainAvtivity或未知情况下,无法重写里面的keydown事件等。例如一直亮屏
参考链接:
1:https://blog.csdn.net/qq_26999509/article/details/78444163 获取手机电量信息、网络状况
2:http://www.cnblogs.com/wuzhang/p/wuzhang20170318.html#commentform Unity获取安卓手机运营商,电量,wifi信号
3:https://blog.csdn.net/weixin_39706415/article/details/84571421 无法获取wifi ssid (unknow ssid)解决方案
4:http://dev.picovr.com/ PicoVR开发者平台