Android app produces a lot of network traffic - php

I'm building an android app that connects to a remote MySQL database to fetch for a specified data.
I'm using a AsyncTask and JSON to read from the database, the AsyncTask is executed every 20 seconds.
The problem is that when I measure the traffic (upload and download ) for my app, it exceeds the normal values, means the app uses approximately 5 kB every 20 seconds.
Here is the code of the AsyncTask:
Any help will be appreciated.
class NewOrders extends AsyncTask<String,Integer,Integer>{
public Integer doInBackground(String...strings){
int res=0;
String today = todaysdf.format(new Date());
String ftime = fullsdf.format(new Date());
listOrders.add(new BasicNameValuePair("action", "myRequests"));
listOrders.add(new BasicNameValuePair("taxiid", idCab));
listOrders.add(new BasicNameValuePair("driverid", idDriver));
listOrders.add(new BasicNameValuePair("devid", idDevice));
listOrders.add(new BasicNameValuePair("date", today));
listOrders.add(new BasicNameValuePair("time", ftime));
try {
postOrders.setEntity(new UrlEncodedFormEntity(listOrders));
responseOrders = clientOrders.execute(postOrders);
entityOrders = responseOrders.getEntity();
resultOrders = EntityUtils.toString(entityOrders,"UTF-8");
jarrayOrders = new JSONArray(resultOrders);
if (jarrayOrders.length() > 0) {
res = 1;
}
else {
jarrayOrders = null;
}
} catch (Exception e) {e.printStackTrace();}
return res;
}
public void onPostExecute(Integer result){
if(result==1){
playNotification();
notifyNewOrder();
}
}
}

Related

AsyncTask takes forever to fetch result

I am making an android application where I need to fetch data from an online database. The online database has 3 columns, Date, Time and Varchar(255).
Here is my PHP code:
<?php
require "connection.php";
if($result = mysqli_query($conn, "select * from `xuberance_updates`")) {
while($row = mysqli_fetch_assoc($result)) {
echo $row["date"].",".$row["time"].",".$row["updates"].";";
}
}
?>
And here is my kotlin code in android:
class RefreshTask(private val alertDialog: AlertDialog) :
AsyncTask<String, Void, String>() {
override fun onPreExecute() {
...
alertDialog.show()
...
}
override fun doInBackground(vararg params: String?): String? {
val url = URL("https://.../show_update.php")
val httpURLConnection = url.openConnection() as HttpURLConnection
httpURLConnection.doInput = true
httpURLConnection.doOutput = true
httpURLConnection.requestMethod = "POST"
httpURLConnection.connect()
val reader = BufferedReader(InputStreamReader(httpURLConnection.inputStream, "UTF-8"))
var line = reader.readLine()
val result = StringBuilder()
while (line != null) {
result.append(line)
line = reader.readLine()
}
reader.close()
httpURLConnection.disconnect()
return result.toString()
}
override fun onPostExecute(result: String?) {
alertDialog.dismiss()
...
}
...
}
When I start the AsyncTask, The dialog appears. But it never gets dismissed. The onPostExecute(result: String?) method is never reached. How to fix this?
Edit: Sometimes, It successfully reaches the onPostExecute(result: String?) method. But most of the times, I need to wait for 2 or more minutes to get to that method.
Use this library to make network calls. Very simple yet efficient.
http://loopj.com/android-async-http/
this should be culprit
while (line != null) {
result.append(line)
line = reader.readLine()
}

Whats better, make a loop reading php in android or make a loop in php reading a database?

i am making an application in android that has to read constantly a database hosted in my server, my question is, is better make a loop in android, reading the php document constantly or just read once but the php document makes a loop to get information from a database?
in android studio i just make a loop with a sleep, and read the php document. I don't have the code because i haven't made it, but here is the code to connect with php, just imagine it in a loop:
StringRequest conexion = new StringRequest(Request.Method.POST,
Constantes.URL_NombreIcono,
new Response.Listener<String>() {
#Override
public void onResponse(String response) {
if(response.charAt(response.length() - 1) == '1'){
}
else {
NombreGrupo.setText(response);
}
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Toast("No se ha podido conectarse con la base de datos", "l");
}
});
RequestQueue requ = Volley.newRequestQueue(this);
requ.add(conexion);
and the php code in this case is like this:
<?php
$con = mysqli_connect('localhost','root','', 'JNDatabase');
if (!$con) {
echo "|Error";
}
else{
$query = "SELECT * FROM Log ORDER BY id DESC LIMIT 1";
$resultado = $con->query($query);
if (!$resultado){
echo "|Error";
}
else {
$row = $resultado->fetch_assoc();
if($row["Realizada"] == 1){
echo $row["Accion"]."|".$row["id"];
}
}
}
?>
The other case, is read the php document once, but the php document makes the loop, i have the code of the loop in php:
<?php
ini_set('max_execution_time', 0);
while (true) {
$con = mysqli_connect('localhost','root','', 'JNDatabase');
if (!$con) {
echo "|Error";
}
else{
$query = "SELECT * FROM Log ORDER BY id DESC LIMIT 1";
$resultado = $con->query($query);
if (!$resultado){
echo "|Error";
}
else {
$row = $resultado->fetch_assoc();
if($row["Realizada"] == 1){
echo $row["Accion"]."|".$row["id"];
}
}
}
ob_flush();flush();sleep(1);
}
?>
so which do you think is better,having in mind that is an android application and i have to take care about the battery.
PDT: I know that exists services like Firebase, but i want to do this with my own server, you know, try to avoid giving the information to other companies
In Android it depends what will you do with data received from your database. But definitely you shouldn't make loop in PHP. What it will do when Android device is off-line? PHP should get data from database (maybe from cache) and pass it to Android device by request.
If you want to show data from database in UI and nothing else, you can use any loop or Handler.postDelayed() API. But would be nice if you will pause your work when application closed or paused.
Or if you want do some work in background like storing data in SQLite you can use AlarmManager or JobScheduler API. There is a list of available tools.

Azure notifications hub push notification failing or delivering invalid or incomplete data

I am using the following php code to send a push notification to Android application using Azure Notification Hub.
$hub = new NotificationHub("Endpoint=sb://ServiceName.servicebus.windows.net/;SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=SharedAccessKey", "ServiceNameNotification");
$message = '{"data":{"message":"This is a sample notification","title":"Sample Notification","action":"Test","action_id":"60"}}';
$notification = new AzureNotification("gcm", $message);
$hub->sendNotification($notification, null);
But unfortunately most of the times the notification is not getting delivered, although I am getting a 201 as the response. Whenever it does get delivered, the results are unpredictable, sometimes the contents of old notifications end up getting shown.
The following code is used to show the notifications in Android app (Xamarin.Android) :
using System;
using Android.App;
using Android.Content;
using Gcm.Client;
using Microsoft.WindowsAzure.MobileServices;
using Newtonsoft.Json.Linq;
using ServiceName.Helpers;
[assembly: Permission(Name = "#PACKAGE_NAME#.permission.C2D_MESSAGE")]
[assembly: UsesPermission(Name = "#PACKAGE_NAME#.permission.C2D_MESSAGE")]
[assembly: UsesPermission(Name = "com.google.android.c2dm.permission.RECEIVE")]
//GET_ACCOUNTS is needed only for Android versions 4.0.3 and below
[assembly: UsesPermission(Name = "android.permission.GET_ACCOUNTS")]
[assembly: UsesPermission(Name = "android.permission.INTERNET")]
[assembly: UsesPermission(Name = "android.permission.WAKE_LOCK")]
namespace ServiceName.Droid
{
[BroadcastReceiver(Permission = Gcm.Client.Constants.PERMISSION_GCM_INTENTS)]
[IntentFilter(new string[] { Gcm.Client.Constants.INTENT_FROM_GCM_MESSAGE },
Categories = new string[] { "#PACKAGE_NAME#" })]
[IntentFilter(new string[] { Gcm.Client.Constants.INTENT_FROM_GCM_REGISTRATION_CALLBACK },
Categories = new string[] { "#PACKAGE_NAME#" })]
[IntentFilter(new string[] { Gcm.Client.Constants.INTENT_FROM_GCM_LIBRARY_RETRY },
Categories = new string[] { "#PACKAGE_NAME#" })]
public class ServiceNameBroadcastReceiver : GcmBroadcastReceiverBase<PushHandlerService>
{
public static string[] senderIDs = new string[] { Constants.SenderID };
public const string TAG = "MyBroadcastReceiver-GCM";
}
// The ServiceAttribute must be applied to the class.
[Service]
public class PushHandlerService : GcmServiceBase
{
public static string RegistrationID { get; private set; }
public PushHandlerService() : base(ServiceNameBroadcastReceiver.senderIDs) { }
protected override void OnMessage(Context context, Intent intent)
{
string message = string.Empty;
string title = string.Empty;
string action = string.Empty;
string action_id = string.Empty;
if (intent.Extras.ContainsKey("title"))
{
title = intent.Extras.Get("title").ToString();
}
if (intent.Extras.ContainsKey("message"))
{
message = intent.Extras.Get("message").ToString();
}
if (intent.Extras.ContainsKey("action"))
{
action = intent.Extras.Get("action").ToString();
}
if (intent.Extras.ContainsKey("action_id"))
{
action_id = intent.Extras.Get("action_id").ToString();
}
// Extract the push notification message from the intent.
if (!string.IsNullOrWhiteSpace(message) || !string.IsNullOrWhiteSpace(title))
{
// Create a notification manager to send the notification.
var notificationManager =
GetSystemService(Context.NotificationService) as NotificationManager;
// Create a new intent to show the notification in the UI.
PendingIntent contentIntent =
PendingIntent.GetActivity(context, 0,
new Intent(this, typeof(MainActivity)), 0);
// Create the notification using the builder.
var builder = new Notification.Builder(context);
builder.SetAutoCancel(false);
if (!string.IsNullOrWhiteSpace(title))
{
builder.SetContentTitle(title);
}
else
{
builder.SetContentTitle("Notification from ServiceName");
}
if (!string.IsNullOrWhiteSpace(message))
{
builder.SetContentText(message);
}
else
{
builder.SetContentText("Hello ServiceName User");
}
builder.SetSmallIcon(Resource.Drawable.ic_stat_icon);
builder.SetContentIntent(contentIntent);
var notification = builder.Build();
// Display the notification in the Notifications Area.
notificationManager.Notify(1, notification);
}
}
protected override void OnError(Context context, string errorId)
{
System.Diagnostics.Debug.WriteLine(
string.Format("Error occurred in the notification: {0}.", errorId));
}
protected override async void OnRegistered(Context context, string registrationId)
{
System.Diagnostics.Debug.WriteLine("The device has been registered with GCM.", "Success!");
// Get the MobileServiceClient from the current activity instance.
MobileServiceClient client = MainActivity.CurrentActivity.CurrentClient;
var push = client.GetPush();
// Define a message body for GCM.
const string templateBodyGCM = "{\"data\":{\"message\":\"$(messageParam)\", \"title\": \"$(titleParam)\", \"action\":\"$(actionParam)\",\"action_id\":\"$(action_idParam)\"}}";
// Define the template registration as JSON.
JObject templates = new JObject();
templates["genericMessage"] = new JObject
{
{"body", templateBodyGCM }
};
try
{
// Make sure we run the registration on the same thread as the activity,
// to avoid threading errors.
MainActivity.CurrentActivity.RunOnUiThread(
// Register the template with Notification Hubs.
async () => {
try
{
await push.RegisterAsync(registrationId, templates);
System.Diagnostics.Debug.WriteLine(
string.Format("Push Installation Id " + push.InstallationId.ToString()));
var res = await MiscServices.RegisterDevice(Settings.UserID, Settings.AccessToken, push.InstallationId.ToString(), "gcm");
if ((bool)res.data)
{
System.Diagnostics.Debug.WriteLine("Registered InstallationId in Server");
}
else
{
System.Diagnostics.Debug.WriteLine("Cannot register with Server" + " " + res.status.StatusCode);
}
}
catch (Exception e)
{
}
});
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine(
string.Format("Error with Azure push registration: {0}", ex.Message));
}
}
protected override void OnUnRegistered(Context context, string registrationId)
{
System.Diagnostics.Debug.WriteLine("Unregistered with Azure push registration");
}
}
}
Even test notifications fail to get delivered at times, but mostly test notifications work fine. We can't really figure out where the issue is occurring, any help is much appreciated.
As you successfully sent messages to Azure NH, and got 201 responses. When you send a notification via Notification Hubs, initially it just gets queued up for NH to do processing to figure out all its targets and then eventually NH sends it to the PNS.
This means that when you are using REST API or any of the client SDK, the successful return of your send call only means that the message has been successfully queued up with Notification Hub.
It doesn’t give an insight into what happened when NH eventually got to send the message to PNS. If your notification is not arriving at the client device, there is a possibility that when NH tried to deliver the message to PNS, there was an error e.g. the payload size exceeded the maximum allowed by the PNS or the credentials configured in NH are invalid etc.
To get an insight into the PNS errors, we have introduced a property called EnableTestSend feature. This property is automatically enabled when you send test messages from the portal or Visual Studio client and therefore allows you to see detailed debugging information.
Or you can try to call via RESTful APIs for troubleshooting:
https://mynamespace.servicebus.windows.net/mynotificationhub/messages?api-version=2013-10&test
Please refer to Azure Notification Hubs - Diagnosis guidelines for more info.

Create a simple json response which can be accessed from webview of an android application

I have a url site.com/test.php which has the following code
<?php
$num1 = $_REQUEST['num1'] ;
$num2 = $_REQUEST['num2'] ;
$tot = $num1 + $num2 ;
?>
From an android application using POST/GET num1 and num2 parameters are passed to www.site.com/test.php
How can I make the response in such a way that the android application will be able to get the response from this request.
I tried this
header('Content-Type: application/json');
echo json_encode($response);
but all it does is echo it in the web view and im not able to get the response.Is there someway I can get the response as standard json response,which is not displayed but get it as soon as I hit the url as a response ?
** UPDATE **
#Override
public boolean shouldOverrideUrlLoading (WebView view, String url) {
if(flag) {
URL aURL = new URL(url);
URLConnection conn = aURL.openConnection();
conn.connect();
InputStream is = conn.getInputStream();
// read inputstream to get the json..
...
...
return true;
}
return false
}
#override
public void onPageFinished (WebView view, String url) {
if (url contains "form.html") {
flag = true;
}
}
this is the java code I got from SO , which Im planning to use in the android appication
Seems to be a problem in the handling of the response, not the generation of the JSON. Are you clicking a link to the JSON on a page that is has "form.html" in it? Because that is what seems to be assumed in the code you posted.
It seems to be better to just overload the shouldOverrideUrlLoading and check if the url matches your json page. Something like this:
#Override
public boolean shouldOverrideUrlLoading (WebView view, String url) {
if(url.toLowerCase().contains("www.site.com/test.php")) {
URL aURL = new URL(url);
URLConnection conn = aURL.openConnection();
conn.connect();
InputStream is = conn.getInputStream();
// read inputstream to get the json..
...
...
return true;
}
return false;
}
It might be a good idea to start an activity and load the JSON in that activity using, for example, an AsyncTask (network operations aren't allowed on the UI thread in the latest android APIs), instead of doing URL.openConnection immediately.

How to get data from Server using ID in Android

I am writing a Native Android App in which i am using PHP MYSQL to get data from server
In this [Appointment List] i am allowing user to Reschedule an Appointment, but whenever i do tap on item getting blank form, in short not getting data for that particular appointment which i have clicked in a List.
Question
How to show data in a form using AppointmentID ?
Below i am showing all required code written by me [Client & Server Side both]
UpcomingActivity.java:
#Override
public boolean onContextItemSelected(MenuItem item) {
AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo)item.getMenuInfo();
int menuItemIndex = item.getItemId();
String[] menuItems = Cmd;
String CmdName = menuItems[menuItemIndex];
// Check Event Command
if ("Cancel".equals(CmdName))
{
Toast.makeText(UpcomingActivity.this,"Selected Cancel",Toast.LENGTH_LONG).show();
}
else if ("Reschedule".equals(CmdName))
{
Toast.makeText(UpcomingActivity.this,"Selected Update",Toast.LENGTH_LONG).show();
String sAppointmentID = MyArrList.get(info.position).get("UserID").toString();
Log.d(tag, "sAppointmentID :: " + sAppointmentID);
Intent newActivity = new Intent(UpcomingActivity.this, UpdateActivity.class);
newActivity.putExtra("UserID", sAppointmentID);
startActivity(newActivity);
}
return true;
}
UpdateActivity.java:
public void showInfo()
{
final TextView tAppointmentID = (TextView)findViewById(R.id.txtUsername);
final TextView tType = (TextView)findViewById(R.id.txtName);
final TextView tDate = (TextView)findViewById(R.id.txtEmail);
final TextView tTime = (TextView)findViewById(R.id.txtTel);
Button btnSave = (Button) findViewById(R.id.btnSave);
Button btnCancel = (Button) findViewById(R.id.btnCancel);
String url = "http://10.0.2.2/appointments/getByMemberID.php";
Intent intent= getIntent();
final String AppointmentID = intent.getStringExtra("AppointmentID");
List<NameValuePair> params = new ArrayList<NameValuePair>();
params.add(new BasicNameValuePair("sAppointmentID", AppointmentID));
String resultServer = getHttpPost(url,params);
String strAppointmentID = "";
String strType = "";
String strDate = "";
String strTime = "";
JSONObject c;
try {
c = new JSONObject(resultServer);
strAppointmentID = c.getString("UserID");
Log.d(TAG, "String strAppointmentID" + strAppointmentID);
strType = c.getString("Type");
Log.d(TAG, "String strType" + strType);
strDate = c.getString("Date");
Log.d(TAG, "String strDate" + strDate);
strTime = c.getString("Time");
Log.d(TAG, "String strTime" + strTime);
if(!strAppointmentID.equals(""))
{
tAppointmentID.setText(strAppointmentID);
tType.setText(strType);
tDate.setText(strDate);
tTime.setText(strTime);
}
else
{
tAppointmentID.setText("-");
tType.setText("-");
tDate.setText("-");
tTime.setText("-");
btnSave.setEnabled(false);
btnCancel.requestFocus();
}
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
first of all make sure that you have valid AppointmentID and UserIdand
in UpcomingActivity.java at method onContextItemSelected you are not providing AppointmentID instead you are only providing UserID to the Intend
List but in Updateactivity at method showData you are requesting intent.getStringExtra("AppointmentID") which is invaild.
so your update your UpcomingActivity.java should look like this
public boolean onContextItemSelected(MenuItem item) {
AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo)item.getMenuInfo();
int menuItemIndex = item.getItemId();
String[] menuItems = Cmd;
String CmdName = menuItems[menuItemIndex];
// Check Event Command
if ("Cancel".equals(CmdName))
{
Toast.makeText(UpcomingActivity.this,"Selected Cancel",Toast.LENGTH_LONG).show();
}
else if ("Reschedule".equals(CmdName))
{
Toast.makeText(UpcomingActivity.this,"Selected Update",Toast.LENGTH_LONG).show();
String sAppointmentID = MyArrList.get(info.position).get("UserID").toString();
Log.d(tag, "sAppointmentID :: " + sAppointmentID);
Intent newActivity = new Intent(UpcomingActivity.this, UpdateActivity.class);
newActivity.putExtra("UserID", sAppointmentID);
newActivity.putExtra("AppointmentID", MyArrList.get(info.position).get("AppointmentID").toString());// <== here
startActivity(newActivity);
}
return true;
}
I noticed a couple of issues (might be typos, but I prefer to ask anyway):
You are calling a getByMemberID.php, but you have not included its source code in the question - you do have such service, right? :)
In the onContextItemSelected you are starting the UpdateActivity and pass UserID as extra. But in the showInfo method of that activity you are trying to get AppointmentID from the intent's extras, so it is not processing any data.
1) Try weather your PHP code is working fine or not...
You can do that by running directly on server and passing UserId and appoinmentId as a parameter by ?
For eg.... www.abc.com?sUserId=123?sAppointmentID=456
See weather it's showing you proper output.
2) you are calling getByMemberID.php but you have specified code of it but you are not passing "AppointmentID" for that also check with php code weather you are retriving it ??
3) On call of updateData.php in UpdateActivity.java: you are not providing "AppointmentID" but you are retriving it in php code it will get null value by default which will be an error ofcourse

Categories