I'm having a weird problem with android's webview. I load a page to the webview which has a link in it. I have set the webview to open that link in the same webview (not on a browser). When the next page is opened it writes some stuff to mysql. If an user has already opened that second page on a same day, the user gets redirected to the first page and no stuff is written to mysql. I noticed that in 1 out of 3-4 times on first situation pressing the link writes the stuff to mysql twice (with a same timestamp) and redirects the user right away to first page. So it seems that when the link is clicked the url is opened twice in a row. Everything works as supposed on my computer's browsers (safari, firefox and chrome). I found some article that said that empty src-fields on images can cause this but there are no empty src-fields in my php/html code.
Webview is set like this:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_description);
WebViewClient yourWebClient = new WebViewClient()
{
public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
webView.loadUrl("file:///android_asset/404.html");
}
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url)
{
if ( url.contains("google") == false ) {
webView.loadUrl(url);
return false;
}
else {
Intent i = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
startActivity(i);
return true;
}
}
};
webView = (WebView) findViewById(R.id.description);
webView.getSettings().setJavaScriptEnabled(true);
if (Build.VERSION.SDK_INT >= 11){
webView.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
}
String url = (MainActivity.URL+"app/description.php?tagid="+tagId+"&screenwidth="+viewPortWidth+"&screenheight="+viewPortHeight+"&deviceid="+MainActivity.myDeviceId+"&lang="+MainActivity.myLanguage+"&os=android);
webView.setWebViewClient(yourWebClient);
webView.loadUrl(url);
}
My link is just a typical div inside an anchor tag (written in php):
echo '<a href="description.php?type='.$type.'&screenwidth='.$screenWidth.'&screenheight='.$screenHeight.'&tagid='.$tagid.'&no=1&deviceid='.$deviceid.'&lang='.$language.'">
<div class="redbutton">'.$lang['NO'].'</div></a>';
Actually only return false, webpage will automatically be loaded in WebView. No need to use webView.loadUrl();.
if ( url.contains("google") == false ) {
return false;
}
Give it a try and let me know if doesn't work.
As Documentation states -
while return false means the current WebView handles the url
Ok I found the reason for this. This was the cause:
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url)
{
if ( url.contains("google") == false ) {
webView.loadUrl(url);
return false; // <----THIS LINE
}
else {
Intent i = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
startActivity(i);
return false;
}
}
That should have returned true. I found this out by testing with this:
#Override
public void onPageFinished(WebView view, String url)
{
super.onPageFinished(view, url);
String url_new = view.getUrl();
Log.v("","Webview url: "+url_new);
}
I noticed that it printed out the url twice every time that some link was pressed, but it didn't do that when the webview was loaded first time. When I changed the return statement to true it only printed out once per click as it's supposed to do.
Related
I'm facing a frustrating problem right now and I can't see any reason why this doesn't work since is pure Unity developer copy paste code.
I can't send data from Unity to website. Every Unity sent parameter is taken as empty.
That's how my [Web.cs] looks like:
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UnityEngine.Networking;
public class Web : MonoBehaviour
{
public IEnumerator Login(string Username, string Password)
{
Debug.Log(Username);
Debug.Log(Password);
WWWForm Form = new WWWForm();
Form.AddField("loginUser", Username);
Form.AddField("loginPass", Password);
UnityWebRequest www = UnityWebRequest.Post("http://localhost/Login.php", Form);
yield return www.SendWebRequest();
if (www.isNetworkError || www.isHttpError)
Debug.Log(www.error);
else
{
Debug.Log("Form upload complete!");
Debug.Log(www.downloadHandler.text);
}
}
}
And I'm calling it via Login.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class Login : MonoBehaviour
{
public InputField UserName;
public InputField Password;
public Button myButton;
private void Start()
{
myButton.onClick.AddListener(() =>
{
StartCoroutine(Main.Instance.Web.Login(UserName.text, Password.text));
});
}
}
The php code looks like:
<?php
$UserName = $_GET["loginUser"];
$Password = $_GET["loginPass"];
$myfile = fopen("testfile.txt", "a");
fwrite($myfile, "Username: $UserName\nPassowrd: $Password\n\n");
?>
So, when I manually acces the path link, I get the expected results:
http://localhost/Login.php?loginUser=Test&loginPass=Ok
https://i.imgur.com/s0bP5tJ.png
But when I do it with Unity, XAMPP writes the parameters as empty.
A debug photo:
https://i.imgur.com/r1IUTy2.png
It appears you're sending a POST request to a GET request.
Try this: UnityWebRequest.Get(...)
#Kale, thank you, I kinda still don't understand what's the difference between post and get methods :-?
For future searchers, that's how I managed to resolve the issue:
public class Web : MonoBehaviour
{
public IEnumerator Login(string Username, string Password)
{
WWWForm Form = new WWWForm();
string Link = "http://localhost/Login.php?loginUser=" + Username + "&loginPass=" + Password;
UnityWebRequest www = UnityWebRequest.Get(Link);
yield return www.SendWebRequest();
if (www.isNetworkError || www.isHttpError)
Debug.Log(www.error);
else
{
Debug.Log("Form upload complete!");
Debug.Log(www.downloadHandler.text);
}
}
}
I have a web server which contains a sql database. There are two "users" to this server/database. One is the actual user where they will submit changes through a UnityWebRequest using HTTP:Post. This will make changes to the database.
I have another system that is also in Unity, that needs to be notified, or somehow monitor for whenever a change is made to a specific table in a database. I don't know how to monitor the table for changes without constantly making select calls to the database.
What I've tried
I have a unity function which calls the webserver through HTTP:Post. The webserver goes into an infinite while loop making calls to the database something like
$variable = $_REQUEST['variable_to_monitor'];
$stmt = $pdo->prepare("SELECT variable_to_monitor FROM table_name;")
while(true){
$stmt->execute();
results = $stmt->fetchAll()[0];
if ($variable != results['variable_to_monitor']){
die(results['variable_to_monitor']);
}
}
This holds up the webserver and is making too many calls to the database.
I would like for Unity to be able to make a single call to a web server giving it a given state, the web server will compare said state to database until the database changes, then once the db changes respond to unity with the updated state. I want to be able to do this without making a million SELECT calls to a database per second.
Unity Code
void Update()
{
if(hasResponse)
{
hasResponse = false;
StartCoroutine(SendRequest());
}
}
IEnumerator SendRequest(WWWForm form = null, Action<string> callback = null)
{
if(null == form) form = new WWWForm();
form.AddField("request", "monitor_variable");
form.AddField("variable_to_monitor", this.variable_to_monitor);
UnityWebRequest www = UnityWebRequest.Post(url, form);
yield return www.SendWebRequest();
if (www.isNetworkError)
{
Debug.Log("Network Error");
}
else if (www.isHttpError)
{
Debug.Log("Http Error");
}
else
{
if(null == callback)
{
Debug.Log(www.downloadHandler.text);
}
else
{
if (!www.downloadHandler.text.Contains("New Request Started"))
{
hasResponse = true;
callback(www.downloadHandler.text);
}
else
{
Debug.Log(www.downloadHandler.text);
}
}
}
}
Of course you can and always should wait in Unity for the UnityWebRequest to finish! You should allways use e.g. a Coroutine
And than you can as well e.g. add a time offset so you don't make a new request right ahead but maybe wait a few seconds.
I personally would also add callbacks for the response which makes it way more flexible and reusable e.g.
public void MakeRepeatedRequests(string url, float timeOffset, Action<string> successCallback, Action<string> errorCallback)
{
StartCoroutine(RepeatedRequestRoutine(url, timeOffset, successCallback, errorCallback);
}
private IEnumerator RepeatedRequestRoutine(string url, float timeOffset, Action<string> successCallback, Action<string> errorCallback)
{
// No worries this still looks like a while loop (well it is ^^)
// but the yield makes sure it doesn't block Unity's UI thread
while(true)
{
// Configure your request
var request = UnityWebRequest.Post(url);
// Make the request and wait until the it has finished (has a response or timeout)
// a yield kind of tells this routine to leave, let Unity render this frame
// and continue from here in the next frame
yield return request.SendWebRequest();
if(request.isNetworkError || request.isHttpError)
{
errorCallback?.Invoke(request.error);
}
else
{
successCallback?.Invoke(request.downloadHandler.text);
}
// Now wait for the timeOffset
yield return new WaitForSeconds(timeOffset);
}
}
Now you can call it e.g. for waiting 2 seconds after the last request finished
// ...
MakeRepeatedRequests ("http://example.com", 2.0f, OnSuccess, OnError);
// ...
private void OnSuccess(string success)
{
Debug.LogFormat(this, "Nice it worked! Server said:/"{0}/"", success);
// Do something e.g. using success
}
private void OnError(string error)
{
Debug.LogFormat(this, "Oh no, request failed with \"{0}\"", error);
}
or also do the same thing using lambda expressions
MakeRepeatedRequests ("http://example.com", 2.0f,
success =>
{
Debug.LogFormat(this, "Nice it worked! Server said:/"{0}/"", success);
// Do something e.g. using success
},
error =>
{
Debug.LogFormat(this, "Oh no, request failed with \"{0}\"", error);
// Do something else
});
Even if you don't want the timeOffset this at least waits for every request to finish before starting the next one so your server only has to make one DB query and either return a success or an error.
In your case I would respond with a success (200) anyway (because error should be sent only if the server really had an error) but either send an empty string or some predefined one you can check for in Unity (something like e.g. "!NO_CHANGE!").
so on the server side without a loop something like e.g.
results = "SELECT * FROM table_name;"
if ($_REQUEST['variable_name'] != results['variable_name']){
echo results['variable_name'];
} else {
echo "!NO_CHANGE!";
}
than you could later in Unity check it
if(string.Equals(success, "!NO_CHANGE!")) return;
I looked swipe , but I did not understand. i have php page.
i want:
When the page opens (m.mydomain.com/content.php?id=13) if right touch id=12 if left touch 14.
I do not know where to write this is urls. and this is possible?
private class HelloWebViewClient extends WebViewClient {
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
webview = (WebView) findViewById(R.id.webview);
webview.getSettings().setJavaScriptEnabled(true);
webview.loadUrl("m.mydomain.com");
view.loadUrl(url);
//if right { view.loadUrl(m.mydomain.com/content.php?id=13-1) }
//if left { view.loadUrl(m.mydomain.com/content.php?id=13+1) }
return true;
}
After spending so many days, am trying to get some help from experts.
I am stuck with login redirection in my yii2 application only in chrome browser,
This is my controller class,
class InvitationsController extends Controller
{
public function beforeAction($action)
{ $array=array('index','imageupload','template','category','subcategory','slug','chooseanotherdesign');
if(!in_array($action->id, $array))
{
if (\Yii::$app->getUser()->isGuest &&
\Yii::$app->getRequest()->url !== Url::to(\Yii::$app->getUser()->loginUrl)
) {
\Yii::$app->getResponse()->redirect(\Yii::$app->getUser()->loginUrl,FALSE);
}
}
return parent::beforeAction($action);
}
public function actionGenerateevent(){
$redirectUrl="";
if(Yii::$app->request->post()){
unset(Yii::$app->session['copyinvitation']);
unset(Yii::$app->session['eventform']);
Yii::$app->session['eventform']=Yii::$app->request->post();
}
if (!Yii::$app->user->isGuest)
{
$eventid=$this->invitation->savecontinue(Yii::$app->session['eventform']);
$eventdata=$this->invitation->getEventById($eventid);
$refurl=Yii::$app->session['eventform']['refererurl'];
$aa['Events']=$eventdata;
$aa['refererurl']=$refurl;
Yii::$app->session['eventform']=$aa;
$redirectUrl = Yii::$app->urlManager->createAbsoluteUrl(['invitations/event/'.$eventdata['event_token']]);
return $this->redirect($redirectUrl);
}
}
}
My workflow
step1: submitting formdata to controller xx-action
step2: If user login it will proceed further action
Else
am trying to store the values in session then redirecting the page to login
step 3: after successful login am return back to same xx-action
This workflow is working fine in firefox but chrome it's making infinitive loop its not going through the login page.
Please refer am attached the screenshot
Please help me to solve this issue.
I can't infere how are you calling your actionGenerateevent() but you seems to have an error there:
$redirectUrl=""; //empty
...
return $this->redirect($redirectUrl); //still empty
Since you are not setting your $redirectUrl, your redirect is redirecting you to the current (same) url again and again, causing the loop.
This is the function used by redirectUrl() method: Url::to(). Its docs says:
an empty string: the currently requested URL will be returned;
I have a GWT app with inputs (let's say Name, Address, Email). After user input all the required fields and press submit button, a PHP page will display the inputs from the GWT app. How can I connect my GWT app to php? I'm using Request Builder now. Do I still have to use XML to pass the GWT inputs to PHP? Please help. I'm just starting to learn GWT here.
Thanks in advance.
You actually don't need RequestBuilder for something like that.
It would be sufficient if you redirect to the PHP url and append your inputs as GET parameters.
So for example in the click handler you can do something like that:
submitButton.addClickHandler(new ClickHandler() {
public void onClick(ClickEvent event) {
String linkURL = "somePage.php?name="+name+"&address="+address+"&email="+email;
Window.Location.assign(linkURL);
}
});
and then in the PHP page you can retrieve the parameters in this way:
$name = $_GET['name'];
$address = $_GET['address'];
$email = $_GET['email'];
Update
If you want to use RequetBuilder you have to do something like that:
submitButton.addClickHandler(new ClickHandler() {
public void onClick(ClickEvent event) {
RequestBuilder request = new RequestBuilder(POST,PHP_URL);
JSONObject jsonValue = new JSONObject();
jsonValue.put("name", new JSONString(name));
jsonValue.put("address", new JSONString(address));
jsonValue.put("email", new JSONString(email));
request.setHeader("Content-Type", "application/json");
request.sendRequest(jsonValue.toString(),new RequestCallback() {
#Override
public void onResponseReceived(Request request, Response response) {
if (200 == response.getStatusCode()) {
//retrieve a uniqueid or so and redirect to the PHP page which displays the infos
} else {
// displayError("Couldn't retrieve
}
}
#Override
public void onError(Request request, Throwable exception) {
//displayError("Couldn't retrieve JSON");
}
});
}
});
On the server you just access the global $_POST variable to get the values:
$name = #_POST['name']