I am using the latest Unity3D version. When using LocationService.isEnabledByUser, I should be told whether the GPS is enabled or disabled. However it is always returns true. I am using an Android 4.2 smartphone.
What could be the cause of this issue, and can I somehow resolve it?
There is a problem with LocationService.isEnabledByUser on some devices and I wouldn't trust using that in my app. It is not reliable. Just build a java plugin for this. I will share the one I made long time ago.
Java:
Create a class called LocationService. Let's assume that package name is com.progammer.plugin and the full package name is com.progammer.plugin.LocationService.
import android.content.Context;
import android.content.Intent;
import android.location.LocationManager;
import android.provider.Settings;
import android.util.Log;
import android.widget.Toast;
public class LocationService {
private static Context mContext;
// Called From C# to get the Context Instance
public static void receiveContextInstance(Context tempContext) {
mContext = tempContext;
}
// http://stackoverflow.com/a/10311891/3785314
public static boolean isLocationServiceEnabled() {
LocationManager lm = (LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE);
boolean gps_enabled = false;
boolean network_enabled = false;
try {
gps_enabled = lm.isProviderEnabled(LocationManager.GPS_PROVIDER);
} catch (Exception ex) {
Log.e("CONTEXT", "Error: " + ex.getMessage());
}
try {
network_enabled = lm.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
} catch (Exception ex) {
Log.e("CONTEXT", "Error: " + ex.getMessage());
}
return (gps_enabled && network_enabled);
}
public static boolean isGPSLocationServiceEnabled() {
LocationManager lm = (LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE);
boolean gps_enabled = false;
try {
gps_enabled = lm.isProviderEnabled(LocationManager.GPS_PROVIDER);
} catch (Exception ex) {
Log.e("CONTEXT", "Error: " + ex.getMessage());
}
return gps_enabled;
}
public static boolean isNetworkLocationServiceEnabled() {
LocationManager lm = (LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE);
boolean network_enabled = false;
try {
network_enabled = lm.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
} catch (Exception ex) {
Log.e("CONTEXT", "Error: " + ex.getMessage());
}
return network_enabled;
}
// http://stackoverflow.com/a/32797750/3785314
#SuppressWarnings({ "deprecation" })
public static boolean isAirplaneModeOn() {
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN_MR1) {
/* API 17 and above */
return Settings.Global.getInt(mContext.getContentResolver(), Settings.Global.AIRPLANE_MODE_ON, 0) != 0;
} else {
/* below */
return Settings.System.getInt(mContext.getContentResolver(), Settings.System.AIRPLANE_MODE_ON, 0) != 0;
}
}
// http://stackoverflow.com/a/7713511/3785314
public static void notifyUserToEnableLocationService() {
CharSequence searchStr = "Please enable Location Service";
Toast.makeText(mContext, searchStr, Toast.LENGTH_LONG).show();
Intent gpsOptionsIntent = new Intent(android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS);
gpsOptionsIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
mContext.startActivity(gpsOptionsIntent);
}
}
C#:
Create a script called LocationServiceManager:
using UnityEngine;
using System.Collections;
public class LocationServiceManager
{
AndroidJavaClass unityClass;
AndroidJavaObject unityActivity;
AndroidJavaObject unityContext;
AndroidJavaClass customClass;
public LocationServiceManager()
{
//Replace with your full package name
sendContextReference("com.progammer.plugin.LocationService");
}
public void sendContextReference(string packageName)
{
unityClass = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
unityActivity = unityClass.GetStatic<AndroidJavaObject>("currentActivity");
unityContext = unityActivity.Call<AndroidJavaObject>("getApplicationContext");
customClass = new AndroidJavaClass(packageName);
customClass.CallStatic("receiveContextInstance", unityContext);
}
///////////////////////////////////MAIN FUNCTIONS/////////////////////////////////////
public bool isLocationServiceEnabled()
{
return customClass.CallStatic<bool>("isLocationServiceEnabled");
}
public bool isGPSLocationServiceEnabled()
{
return customClass.CallStatic<bool>("isGPSLocationServiceEnabled");
}
public bool isNetworkLocationServiceEnabled()
{
return customClass.CallStatic<bool>("isNetworkLocationServiceEnabled");
}
public bool isAirplaneModeOn()
{
return customClass.CallStatic<bool>("isAirplaneModeOn");
}
public void notifyUserToEnableLocationService()
{
customClass.CallStatic("notifyUserToEnableLocationService");
}
}
To use the plugin in C#:
Let's make a simple Test Script to test the new plugin. This will only run on Android devices, so don't expect it to work in the Editor.
public class TestScript : MonoBehaviour
{
public Text text;
LocationServiceManager lsm;
void Start()
{
lsm = new LocationServiceManager();
text.text = "Air Plane Mode: " + lsm.isAirplaneModeOn();
text.text += "\r\nLocation Service Enabled: " + lsm.isLocationServiceEnabled();
text.text += "\r\nGPS Location Service Enabled: " + lsm.isGPSLocationServiceEnabled();
text.text += "\r\nNetwork Location Service Enabled: " + lsm.isNetworkLocationServiceEnabled();
}
}
You can even notify the player to enable Location Service by opening the Location Settings with lsm.notifyUserToEnableLocationService();.
Related
I'm trying to develop a warning if I try to connect to a specific SSID and some waiting time has passed. I've tried with a Timer class but there is some issues with Task and Threads I can't resolve.
This is my Wifi class in Xamarin.Droid
public class Wifi : Iwifi
{
private Context context;
private static WifiManager _manager;
private MyReceiver _receiver;
public void Initialize()
{
context = Android.App.Application.Context;
_manager = (WifiManager)context.GetSystemService(Context.WifiService);
_receiver = new MyReceiver();
}
public void Register()
{
IntentFilter intents = new IntentFilter();
intents.AddAction(WifiManager.ScanResultAction);
intents.AddAction(WifiManager.NetworkStateChangedAction);
context.RegisterReceiver(_receiver, intents);
}
public void Unregister()
{
context.UnregisterReceiver(_receiver);
}
public void ScanWirelessDevices()
{
_manager.StartScan();
}
public string GetConnectionSSID()
{
return _manager.ConnectionInfo.SSID;
}
public void ConnectToSSID(string SSID, string pwd)
{
if (!_manager.IsWifiEnabled)
{
_manager.SetWifiEnabled(true);
}
WifiConfiguration wifiConfiguration = new WifiConfiguration();
wifiConfiguration.Ssid = '"' + SSID + '"';
if (pwd.Empty)
{
wifiConfiguration.AllowedKeyManagement.Set((int)KeyManagementType.None);
}
else
{
//Configuration for protected Network
}
var addNet = _manager.AddNetwork(wifiConfiguration);
if (addNet == -1)
{
_manager.Disconnect();
_manager.EnableNetwork(addNet, true);
_manager.Reconnect();
return;
}
var list = _manager.ConfiguredNetworks;
foreach (WifiConfiguration conf in list)
{
if (conf.Ssid.Equals('"' + SSID + '"'))
{
_manager.Disconnect();
_manager.EnableNetwork(conf.NetworkId, true);
_manager.Reconnect();
return;
}
}
}
public class MyReceiver : BroadcastReceiver
{
public override void OnReceive(Context context, Intent intent)
{
if (intent.Action.Equals(WifiManager.ScanResultAvailableAction))
{
IList<ScanResult> scanResult = _manager.ScanResult;
App.Networks.NetworksList.Clear();
foreach (ScanResult result in scanResult)
{
App.Networks.NetworksList.Add(result.Ssid);
}
}
}
}
}
Then this is a part of App class in Xamarin.Forms
public partial class App: Application
{
private static ...
.
.
.
private static string _selectedSSID;
private static MainDetail _pageDetail;
public static IWifi WifiManager { get; } = DependencyService.Get<Iwifi>();
public static string SelectedSSID { get { return _selectedSSID; } set { _selectedSSID = value; } }
public static MainDetail PageDetail { get { return _pageDetail; } }
public App()
{
InitializeComponent();
WifiManager.Initialize();
WifiManager.Register();
InitViews();
MainPage = _mainPage;
Connectivity.ConnectivityChanged += NetworkEvents;
NetSearch();
}
.
.
.
public void NetSearch()
{
Task.Run(async () =>
{
while (true)
{
WifiManager.ScanWirelessDevices();
await Task.Delay(Utility.SCAN_WIFI_TIMER); //waiting 31000 milliseconds because of Scanning throttling
}
});
}
public void NetworkEvents(object sender, ConnectivityChangedEventArgs e)
{
MainMaster master = (MainMaster)_mainPage.Master;
if (e.NetworkAccess == NetworkAccess.Unknown)
{
Debug.WriteLine("Network Access Unknown " + e.ToString());
}
if (e.NetworkAccess == NetworkAccess.None)
{
Debug.WriteLine("Network Access None " + e.ToString());
}
if (e.NetworkAccess == NetworkAccess.Local)
{
Debug.WriteLine("Network Access Local " + e.ToString());
}
if (e.NetworkAccess == NetworkAccess.Internet)
{
if(selectedSSID == Wifimanager.GetConnectionInfo())
{
//WE CONNECTED!!
//Now I want to stop the Timeout Timer to attempt
}
}
if (e.NetworkAccess == NetworkAccess.ConstrainedInternet)
{
Debug.WriteLine("Network Access Constrainde Internet " + e.ToString());
}
}
}
And part of Detail page class in which I start the event of connection and where I want to start also the timeout timer
public partial class MainDetail : ContentPage
{
.
.
.
public void OnItemListClicked(object sender, SelectedItemChangedEventArgs e)
{
if (e.SelectedItem == null)
{
return;
}
ImageCell item = (ImageCell)e.SelectedItem;
App.SelectedSSID = item.Text;
App.WifiManager.ConnectToSSID(item.Text, "");
ActivityIndicator(true);
//Now the timer should start.
//And call PageDetail.ActivityIndicator(false) and warning the user if the timeout go to 0.
listView.SelectedItem = null;
}
}
I tried with the Timers Timer class but doesn't work.. any suggestion?
Ok I figured a solution! Instead of using Thread and Task, I used Device.StartTimer.
In the event on the DetailPage I wrote:
public void OnItemListClicked(object sender, SelectedItemChangedEventArgs e)
{
if (e.SelectedItem == null)
{
return;
}
ImageCell item = (ImageCell)e.SelectedItem;
App.SelectedSSID = item.Text;
App.WifiManager.ConnectToSSID(item.Text, "");
ActivityIndicator(true);
Device.StartTimer(TimeSpan.FromSeconds(10), () => //Waiting 10 second then if we are not connected fire the event.
{
Device.BeginInvokeOnMainThread(() =>
{
if (App.IsLogout) //variable I use to check if I can do the logout or not
{
ActivityIndicator(false);
App.SelectedSSID = "";
//My message to users "Fail to connect"
}
});
return false;
});
listView.SelectedItem = null;
}
I am trying to create a Regular Expression system as part of my program. When I pass emailSub (which is a String version of an InputField for the user's email) into other functions within the program, the emailSub goes from the email address (e.g: emailaddress#emailprovider.com) to null (I know this because the output of a Debug.Log before being passed is the email address and Debug.Log-ing it after passing it comes back with " ". This means that when it reaches the length check (IsEmailValid) it is less than 6 characters so all email addresses are rejected as invalid.
How can I fix this problem?
Thanks.
using System.Text.RegularExpressions;
using System.Globalization;
using UnityEngine;
using UnityEngine.UI;
using System;
public class RegEx : MonoBehaviour
{
public InputField emailField;
public Button acceptSubmissionButton;
public string emailSub;
public void Start()
{
var input = gameObject.GetComponent<InputField>();
var se = new InputField.SubmitEvent();
se.AddListener(SubmitName);
input.onEndEdit = se;
}
private void SubmitName(string arg0)
{
Debug.Log(arg0);
emailSub = arg0;
Debug.Log(emailSub);
}
public void Sequencer(string emailSub)
{
Debug.Log(emailSub);
IsEmailValid(emailSub);
Main(emailSub);
}
public static bool IsEmailValid(string emailSub)
{
if (emailSub.Length <= 6)
{
Debug.Log(emailSub + "1");
return false;
}
if (string.IsNullOrWhiteSpace(emailSub))
{
Debug.Log(emailSub + "2");
return false;
}
try
{
emailSub = Regex.Replace(emailSub, #"(#)(.+)$", DomainMapper, RegexOptions.None,
TimeSpan.FromMilliseconds(200));
string DomainMapper(Match match)
{
var idnConversion = new IdnMapping();
var processDomainName = idnConversion.GetAscii(match.Groups[2].Value);
Debug.Log(emailSub + "3");
return match.Groups[1].Value + processDomainName;
}
}
catch (RegexMatchTimeoutException e)
{
return false;
}
catch (ArgumentException e)
{
return false;
}
try
{
Debug.Log(emailSub + "4");
return Regex.IsMatch(emailSub, #"^(([0-9a-z]((\.(?!\.))(?<=[0-9a-z])#))" + #"(([0-9a-z][-0-
9a-z]*[0-9a-z]*\.)+[a-z0-9][\-a-z0-9]{0,22}[a-z0-9]))$", RegexOptions.IgnoreCase,
TimeSpan.FromMilliseconds(250));
}
catch (RegexMatchTimeoutException)
{
return false;
}
}
public static void Main(string emailSub)
{
if (RegEx.IsEmailValid(emailSub))
{
Debug.Log($"Valid: {emailSub}");
Debug.Log(emailSub + "5");
}
else
{
Debug.Log($"Invalid: {emailSub}");
Debug.Log(emailSub + "6");
}
}
}
The answer below was written by the person who asked the original question, but they wrote it as a replacement of the question, not in answer.
I fixed the problem, the program takes the contents of a text field and decides whether the text is in a valid email format or not. The problem was that the functions were running before the SubmitName() had updated the contents of arg0. Here is the working code:
using System.Text.RegularExpressions;
using System.Globalization;
using UnityEngine;
using UnityEngine.UI;
using System;
public class RegEx : MonoBehaviour
{
public InputField emailField;
public Button acceptSubmissionButton;
public string emailSub;
public void Start()
{
var input = gameObject.GetComponent<InputField>();
var se = new InputField.SubmitEvent();
se.AddListener(SubmitName);
input.onEndEdit = se;
}
private void SubmitName(string arg0)
{
Debug.Log(arg0);
IsEmailValid(arg0);
ValidCheck(arg0);
}
public void Sequencer(string emailSub)
{
Debug.Log(emailSub);
IsEmailValid(emailSub);
ValidCheck(emailSub);
}
public static bool IsEmailValid(string arg0)
{
if (arg0.Length <= 6)
{
return false;
}
try
{
return Regex.IsMatch(arg0, #"^(?("")("".+?(?<!\\)""#)|(([0-9a-z]((\.(?!\.))|[-!#\$%&'\*\+/=\?\^`\{\}\|~\w])*)(?<=[0-9a-z])#))" + #"(?(\[)(\[(\d{1,3}\.){3}\d{1,3}\])|(([0-9a-z][-0-9a-z]*[0-9a-z]*\.)+[a-z0-9][\-a-z0-9]{0,22}[a-z0-9]))$", RegexOptions.IgnoreCase, TimeSpan.FromMilliseconds(250)); // The pattern is taken from an article written by Microsoft. https://learn.microsoft.com/en-us/dotnet/standard/base-types/how-to-verify-that-strings-are-in-valid-email-format
}
catch (RegexMatchTimeoutException)
{
return false;
}
}
public static void ValidCheck(string arg0)
{
if (IsEmailValid(arg0))
{
Debug.Log($"Valid: {arg0}");
}
else
{
Debug.Log($"Invalid: {arg0}");
}
}
}
I built off of this code: https://www.codeproject.com/Articles/1052356/Creating-a-Simple-Plugin-System-with-NET and I turned it into a windows form. However I can't figure out how I can make it edit the UI from the DLL. I created a controller class with the following code:
public RichTextBox console;
public void WriteToRichTextBox(dynamic text, RichTextBox control)
{
control.AppendText(text + "\n");
}
` However, I can't figure out how to make them share the same controller class.
Form Code:
PluginLoader loader;
Controller controller;
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
try
{
//Let the user fill in an plugin name
string line = textBox1.Text;
string name = line.Split(new char[] { ' ' }).FirstOrDefault();
IPlugin plugin = PluginLoader.Plugins.Where(p => p._pluginName
== name).FirstOrDefault();
if (plugin != null)
{
//If the plugin is found, execute it
plugin.PluginLaunched();
}
else
{
Log(string.Format("No plugin found with name '{0}'", name));
}
}
catch (Exception ex)
{
Log(string.Format("Caught exception: {0}", ex.Message));
}
textBox1.Clear();
}
private void Log(string text)
{
richTextBox1.AppendText(text + "\n");
}
private void Form1_Load(object sender, EventArgs e)
{
Log("Started plugin app..");
try
{
loader = new PluginLoader();
controller = new Controller();
loader.LoadPlugins();
controller.console = richTextBox1;
}
catch (Exception ex)
{
Log(string.Format("Plugins couldn't be loaded: {0}",
ex.Message));
}
}
Interface:
public interface IPlugin
{
string _pluginName { get; }
string _pluginDetails { get; }
void PluginLaunched();
}
Plugin:
public class ListPlugins : IPlugin
{
public void PluginLaunched()
{
Controller _Controller = new Controller();
foreach (IPlugin plugin in PluginLoader.Plugins)
{
_Controller.WriteToRichTextBox(string.Format("{0}: {1}", plugin._pluginName, plugin._pluginDetails), _Controller.console);
}
}
public string _pluginName
{
get
{
return "listplugins";
}
}
public string _pluginDetails
{
get
{
return "This plugin shows all loaded plugins and what they do.";
}
}
}
You have already done the hard part of instantiating the plugin, now you just need to pass the controller when you execute the plugin like so:
plugin.PluginLaunched(controller);
So, I am working on a Unity project in which I need to implement client/server functionality.
The client has its own "scene" and the server has its own scene as well. The server code and a networkView are attached to the Main Camera in their scene. The code is as follows:
using UnityEngine;
using System.Collections;
using System.Net;
using System.Collections.Generic;
public class NetworkManagerCS : MonoBehaviour {
public int loadlevel;
public int connectPort = 25000;
public string hostname;
public string GameName = "Historical Grounds";
private bool refreshing;
private HostData[] hostData;
private Dictionary<string, string> playerList = new Dictionary<string, string>();
string textToEdit = "Type text here";
// This is for debuggin purposes only!! Will be deprecated
public void OnGUI() {
if (Network.peerType == NetworkPeerType.Disconnected) {
GUILayout.Label("Connection status: Disconnected");
GUILayout.BeginVertical();
if (GUILayout.Button("Connect as client"))
{
ConnectToServer();
}
if (GUILayout.Button("Start Server"))
{
Network.InitializeServer(4, connectPort, true);
MasterServer.RegisterHost(GameName, "Tutorial Game", "This is a turn based shooter");
//Network.Instantiate(camera, transform.position, transform.rotation, 0);
}
GUILayout.EndVertical();
}
else
{
// Connecting...
if (Network.peerType == NetworkPeerType.Connecting)
{
GUILayout.Label("Connection status: Connecting");
}
// Clientside buttons
else if (Network.peerType == NetworkPeerType.Client)
{
GUILayout.Label("Connection status: Client!");
GUILayout.Label("Ping to server: " + Network.GetAveragePing(Network.connections[0]));
textToEdit = GUILayout.TextField(textToEdit, 25);
if( GUILayout.Button("Attack Server")) {
float[] args = new float[3];
args[0] = float.Parse(textToEdit);
args[1] = 4.123f;
args[2] = 23.2f;
networkView.RPC("AttackServer", RPCMode.AllBuffered, args);
}
}
// Serverside
else if (Network.peerType == NetworkPeerType.Server)
{
GUILayout.Label("Connection status: Server!");
GUILayout.Label("Hostname is:" + System.Net.Dns.GetHostName() );
GUILayout.Label("Connections: " + Network.connections.Length);
}
// Disconnect happens in both server and client
if (GUILayout.Button("Disconnect"))
{
Network.Disconnect(200);
}
}
}
// AKA While(true)
public void Update() {
/*
* If we have a "refreshing" flag, then we poll the master server
* until we get a length larger than 0. Then, we connect to server.
*/
if(refreshing) {
if (MasterServer.PollHostList().Length > 0) {
refreshing = false;
Debug.Log(MasterServer.PollHostList().Length);
hostData = MasterServer.PollHostList();
ConnectToServer();
}
}
}
/*
* If hostData does not exist, refresh
* Otherwise, connect to the first game you see.
*
* This is the "dumb" approach, but I assume that there are not going to be more
* than one game running at a time...
*/
public void ConnectToServer() {
if (hostData == null) {
MasterServer.RequestHostList(GameName);
refreshing = true;
} else {
Network.Connect(hostData[0]);
}
}
/*
* Keeping this here so that I will remember to add system info sends
*/
public void OnConnectedToServer()
{
//Application.LoadLevel(loadlevel);
}
/*
* DEBUG FUNCTION!!! This will be called when someone disconnected from
* the msater server
*/
public void OnDisconnectedFromServer(NetworkDisconnection info) {
if (info == NetworkDisconnection.LostConnection) {
if (Network.peerType == NetworkPeerType.Client) {
Debug.Log ("Client has lost connection");
} else {
Debug.Log ("Server has lost connection");
}
} else {
Debug.Log ("Disconnected Successfully");
}
}
/*
* Lawl, fail....
*/
public void OnFailedToConnect(NetworkConnectionError error)
{
Debug.LogError(error.ToString());
Network.Disconnect(400);
}
/*
* The purpose of this function is to assign a monster to a player
* Once all monsters have been assigned, I guess the Update() function will
* RPC to the phones that they are ready to play.
*/
public void OnPlayerConnected(NetworkPlayer player) {
networkView.RPC("assignPlayer", RPCMode.All, player);
}
/*
* Not interesting... Server initialized..
*/
public void OnServerInitialized()
{
//Application.LoadLevel(loadlevel);
Debug.Log("Server Started");
}
void OnMasterServerEvent(MasterServerEvent msg) {
if (msg == MasterServerEvent.RegistrationSucceeded){
Debug.Log("Registered Server!");
Network.isMessageQueueRunning = true;
}
}
/*void OnPlayerDisconnected(NetworkPlayer player) {
Transform playerTransform = GameObject.Find("Player_" + player.guid);
if (playerTransform != null) {
Destroy (playerTransform.gameObject);
}
Network.RemoveRPCs(player);
Network.DestroyPlayerObjects(player);
}*/
// Testers - Should deprecate
/*[RPC]
public void AttackServer(float[] args) {
foreach (float value in args) {
Debug.Log ("Server is under attack with force " + value);
}
}*/
// RPC's Server Side
[RPC]
public void sendLifeCount(NetworkPlayer player) {
Debug.Log("Sending Life Count to " + player.ipAddress);
}
[RPC]
public void isDead(NetworkPlayer player) {
Debug.Log("You're dead! " + player.ipAddress);
}
[RPC]
public void unlockScreen(NetworkPlayer player) {
Debug.Log("Unlocking screen for.." + player.ipAddress);
}
[RPC]
public void assignPlayer(NetworkPlayer player) {
playerList.Add(player.guid, "1");
Debug.Log(playerList[player.guid]);
Debug.Log("Player connected from: " + player.ipAddress + ":" + player.port);
Debug.Log("The player on IP " + player.ipAddress + " has been assigned the x monster");
}
public Object networkprefab { get; set; }
}
The client on the other hand, is in another scene and its code is here: (no networkView attached, due to problems...
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
using System.Text.RegularExpressions;
public center code herelass InputField : MonoBehaviour {
// Client-server bullshit
private int loadlevel;
private HostData[] hostData;
private bool refreshing;
public string GameName = "Historical Grounds";
private bool connected;
public Canvas mainCanvas;
public Canvas gameCanvas;
public Button Connect;
public Text nameFieldInput;
public Text nameField;
public Text Error;
private string userName;
void Awake()
{
if (connected)
{
mainCanvas.enabled = false;
gameCanvas.enabled = true;
}
else {
mainCanvas.enabled = true;
gameCanvas.enabled = false;
}
Debug.Log(connected);
}
public void Update()
{
/*
* If we have a "refreshing" flag, then we poll the master server
* until we get a length larger than 0. Then, we connect to server.
*/
if (refreshing)
{
if (MasterServer.PollHostList().Length > 0)
{
refreshing = false;
Debug.Log(MasterServer.PollHostList().Length);
hostData = MasterServer.PollHostList();
ConnectToServer();
}
}
}
public void onConnect()
{
ConnectToServer();
}
public void OnConnectedToServer()
{
var viewID = Network.AllocateViewID();
}
public void ConnectToServer()
{
if (hostData == null)
{
MasterServer.RequestHostList(GameName);
refreshing = true;
}
else
{
if (Switch())
{
connected = true;
Network.Connect(hostData[0]);
}
}
}
private bool Switch(){
userName = nameFieldInput.text;
Debug.Log(userName);
if(Validate(userName)){
nameField.text = userName;
mainCanvas.enabled = false;
gameCanvas.enabled = true;
connected = true;
return true;
} else {
Error.text = "Invalid name!" + "\n" + "Name should be 2-8 characters and start with a capital letter";
return false;
}
}
private bool Validate(string input){
string pattern = #"^[A-Z][A-Za-z0-9][A-Za-z0-9]+";
Match match = Regex.Match(input, pattern);
if (match.Success)
{
return true;
}
return false;
}
public void OnDisconnectedFromServer(NetworkDisconnection info)
{
if (info == NetworkDisconnection.LostConnection)
{
if (Network.peerType == NetworkPeerType.Client)
{
Debug.Log("Client has lost connection");
}
else
{
Debug.Log("Server has lost connection");
}
}
else
{
Debug.Log("Disconnected Successfully");
}
}
public void OnFailedToConnect(NetworkConnectionError error)
{
Debug.LogError(error.ToString());
Debug.Log("FAIL!");
}
public void OnDisconnectedFromServer()
{
connected = false;
Debug.Log("Lawl Disconnected");
}
}
TL;DR: I keep getting that error message when trying to invoke an RPC ( fire() ) from the client to the server. Anyone know why?
Thanks!!
I have problem share to facebook from android use unity C#.
When I try, when debug, it's always need user access token to share, and when share it's just share to tester and admin.
When I try on device it's just show "this application will be access to your email ..." and after that nothing happened.
This is my code:
using UnityEngine;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using Facebook;
public class PTShare : MonoBehaviour {
private string lastResponse = "";
public OTSprite shareBtn;
// Use this for initialization
void Awake () {
CallFBInit ();
}
void Start () {
shareBtn = GameObject.Find ("share").GetComponent<OTSprite>();
}
// Update is called once per frame
void Update () {
if (Input.GetMouseButtonDown (0)) {
if(OT.Over(shareBtn)) {
FB.Login("email,publish_actions", LoginCallback);
CallFBFeed();
}
}
}
public static IEnumerator GetAppAccessToken() {
//Debug.Log("asking FB for App AccessToken");
string url = string.Format("https://graph.facebook.com/oauth/access_token?grant_type=client_credentials&client_ id={0}&client_secret={1}",
"1443575049241638",
"efde01d85ba62e4d81708b4189419d5c");
WWW fbRequest = new WWW(url);
// Wait for download to complete
yield return fbRequest;
string accessToken = fbRequest.text;
Debug.Log("got token: " + accessToken);
accessToken = accessToken.Substring(accessToken.IndexOf("=") + 1);
Debug.Log("trimmed token: " + accessToken);
//FB.UserId = accessToken;
return true;
}
public string FeedToId = "";
public string FeedLink = "http://gambrenggames.com/game-detail/junes-potion/2";
public string FeedLinkName = "June's Potion";
public string FeedLinkCaption = "I play June's Potion friends! Can you play it?";
public string FeedLinkDescription = "";
public string FeedPicture = "http://gambrenggames.com/website/images/game-icon/05540225032014.png";
public string FeedMediaSource = "";
public string FeedActionName = "";
public string FeedActionLink = "";
public string FeedReference = "";
public bool IncludeFeedProperties = false;
private Dictionary<string, string[]> FeedProperties = new Dictionary<string, string[]>();
private void CallFBFeed()
{
Dictionary<string, string[]> feedProperties = null;
if (IncludeFeedProperties)
{
feedProperties = FeedProperties;
}
FB.Feed(
toId: FeedToId,
link: FeedLink,
linkName: FeedLinkName,
linkCaption: FeedLinkCaption,
linkDescription: FeedLinkDescription,
picture: FeedPicture,
mediaSource: FeedMediaSource,
actionName: FeedActionName,
actionLink: FeedActionLink,
reference: FeedReference,
properties: feedProperties,
callback: Callback
);
}
private Texture2D lastResponseTexture;
public string ApiQuery = "";
void Callback(FBResult result)
{
lastResponseTexture = null;
// Some platforms return the empty string instead of null.
if (!String.IsNullOrEmpty(result.Error))
lastResponse = "Error Response:\n" + result.Error;
else if (!ApiQuery.Contains("/picture"))
lastResponse = "Success Response:\n" + result.Text;
else
{
lastResponseTexture = result.Texture;
lastResponse = "Success Response:\n";
}
}
private bool isInit = false;
private void CallFBInit()
{
FB.Init(OnInitComplete, OnHideUnity);
}
private void OnInitComplete()
{
Debug.Log("FB.Init completed: Is user logged in? " + FB.IsLoggedIn);
isInit = true;
}
private void OnHideUnity(bool isGameShown)
{
Debug.Log("Is game showing? " + isGameShown);
}
private void CallFBLogin()
{
FB.Login("email,publish_actions", LoginCallback);
}
void LoginCallback(FBResult result)
{
if (result.Error != null)
lastResponse = "Error Response:\n" + result.Error;
else if (!FB.IsLoggedIn)
{
lastResponse = "Login cancelled by Player";
}
else
{
lastResponse = "Login was successful!";
}
}
private void CallFBLogout()
{
FB.Logout();
}
}
FB.Login is async method and FB.Feed (maybe?) requires Login.
So try call CallFBFeed(); inside LoginCallback method. Like that:
void Update () {
if (Input.GetMouseButtonDown (0)) {
if(OT.Over(shareBtn)) {
if (FB.IsLoggedIn)
{
CallFBFeed();
}
else
{
FB.Login("email,publish_actions", LoginCallback);
}
}
}
}
void LoginCallback(FBResult result)
{
if (result.Error != null)
lastResponse = "Error Response:\n" + result.Error;
else if (!FB.IsLoggedIn)
{
lastResponse = "Login cancelled by Player";
}
else
{
lastResponse = "Login was successful!";
CallFBFeed();
}
}
But it can be problem with android device (i had "magic" with fb login on some old devices) or settings and your code is ok