How can I fetch data from a web server in an android application?
I would recommend these tutorials:
Connect android with PHP and MySql, JSON in android and PHP and MySQLi
I used these tutorials and managed to get what you are trying to do working without too much difficulty.
Between them they describe each step in how to do what you are attempting at each stage, the android application, the database and the web server side and has extra information included for what you can then do to process and use the received information
The only thing I would add is that the Connect android with PHP and MySql tutorial makes use of mysql_ in php which is deprecated. Much better to use MySqli which is why I included the third link.
The basic outline of what you want to do is this:
1) in the android app make a request to a server php script using a class like this:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.util.List;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.utils.URLEncodedUtils;
import org.apache.http.impl.client.DefaultHttpClient;
import org.json.JSONException;
import org.json.JSONObject;
import android.util.Log;
public class JSONParser {
// Response from the HTTP Request
static InputStream httpResponseStream = null;
// JSON Response String to create JSON Object
static String jsonString = "";
// Method to issue HTTP request, parse JSON result and return JSON Object
public JSONObject makeHttpRequest(String url, String method,
List<NameValuePair> params) {
try {
// get a Http client
DefaultHttpClient httpClient = new DefaultHttpClient();
// If required HTTP method is POST
if (method == "POST") {
// Create a Http POST object
HttpPost httpPost = new HttpPost(url);
// Encode the passed parameters into the Http request
httpPost.setEntity(new UrlEncodedFormEntity(params));
// Execute the request and fetch Http response
HttpResponse httpResponse = httpClient.execute(httpPost);
// Extract the result from the response
HttpEntity httpEntity = httpResponse.getEntity();
// Open the result as an input stream for parsing
httpResponseStream = httpEntity.getContent();
}
// Else if it is GET
else if (method == "GET") {
// Format the parameters correctly for HTTP transmission
String paramString = URLEncodedUtils.format(params, "utf-8");
// Add parameters to url in GET format
url += "?" + paramString;
// Execute the request
HttpGet httpGet = new HttpGet(url);
// Execute the request and fetch Http response
HttpResponse httpResponse = httpClient.execute(httpGet);
// Extract the result from the response
HttpEntity httpEntity = httpResponse.getEntity();
// Open the result as an input stream for parsing
httpResponseStream = httpEntity.getContent();
}
// Catch Possible Exceptions
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
try {
// Create buffered reader for the httpResponceStream
BufferedReader httpResponseReader = new BufferedReader(
new InputStreamReader(httpResponseStream, "iso-8859-1"), 8);
// String to hold current line from httpResponseReader
String line = null;
// Clear jsonString
jsonString = "";
// While there is still more response to read
while ((line = httpResponseReader.readLine()) != null) {
// Add line to jsonString
jsonString += (line + "\n");
}
// Close Response Stream
httpResponseStream.close();
} catch (Exception e) {
Log.e("Buffer Error", "Error converting result " + e.toString());
}
try {
// Create jsonObject from the jsonString and return it
return new JSONObject(jsonString);
} catch (JSONException e) {
Log.e("JSON Parser", "Error parsing data " + e.toString());
// Return null if in error
return null;
}
}
}
Which handles communication, opens a connection and receives a JSON string which it then processes into a JSON object.
2) in the php server, open an mysqli connection to your SQL database, run an mysqli->query() and do something like the following with the result:
if (mysqli_num_rows($result) > 0) {
// looping through all results
$response["apps"] = array();
while ($row = mysqli_fetch_array($result)) {
$apps = array();
$apps["name"] = $row["name"];
$apps["package"] = $row["package"];
$apps["version"] = $row["version"];
$apps["dateversion"] = $row["dateversion"];
$apps["sdkver"] = $row["sdkver"];
$apps["pathroot"] = $row["pathroot"];
$apps["rootname"] = $row["rootname"];
$apps["apkmd5"] = $row["apkmd5"];
$apps["extraapkmd5"] = $row["extraapkmd5"];
$apps["instructionsmd5"] = $row["instructionsmd5"];
$apps["assetsmd5"] = $row["assetsmd5"];
$apps["root"] = $row["root"];
$apps["current"] = $row["current"];
// push single product into final response array
array_push($response["apps"], $apps);
}
// success
$response["success"] = 1;
// echoing JSON response
echo json_encode($response);
This iterates through the database response and encodes it into a JSON string which is sent back to the android app which can then process it.
How to create something like this is all explained in the tutorials linked
Send data from a web server to an android app
There is two best approach you can follow.
- from server to app: in this case make
corn job(timer service)
which send push notification to android app. when app get push notification create onebackground service
which download any data from server.
Note: if you have small text with limit of 100 char then no need to create service just send using push notification
- fetch data from server: in this case make one
background service(auto start service)
in android app. which run within some interval period like 1 hour or more(whatever your requirement). that service fetch data from server.(in this case android app eat battery of user device because of background service)
i will suggest you to use 1st approach because its easy and best way(in case of performance) your server do everything & android app have to just receive data.
how to implement push notification best tutorial using PHP & android(its old but just read official docs)
Android app retrieve data from server, save in database and display to user
Updated Answer
After reading comments and updated question I figured out that you want to fetch a small list of data and store it to database and show all the data stored in the database. If this is what you want, you can perform the following (omitted DataSouce for brevity) -
In PostDao
You can return a LiveData<List<MyData>>
instead of List<MyData>
and observe that LiveData
in the Activity to update the RecyclerView
. Just make sure you remove the suspend
keyword as room
will take care of threading when it returns LiveData
.
@Dao
interface PostsDao {
@Query("SELECT * FROM " + Post.TABLE_NAME + " ORDER BY " + Post.COLUMN_ID + " desc")
fun getAllData(): LiveData<List<MyData>>
@Insert
suspend fun insertData(data: List<MyData>)
}
In Repository make 2 functions one for fetching remote data and storing it to the database and the other just returns the LiveData
returned by the room
. You don't need to make a request to room
when you insert the remote data, room
will automatically update you as you are observing a LiveData
from room
.
class DataRepository(private val dao: PostsDao, private val dto: PostDto) {
fun getDataFromDatabase() = dao.getAllData()
suspend fun getDataFromServer(since: Long) = withContext(Dispatchers.IO) {
val data = dto.getRemoteData(since)
saveDataToDatabase(data)
}
private suspend fun saveDataToDatabase(data: List<MyData>) = dao.insertData(data)
}
Your ViewModel should look like,
class DataViewModel(private val repository : DataRepository) : ViewModel() {
val dataList = repository.getDataFromDatabase()
fun data(since: Long) = viewModelScope.launch {
repository.getDataFromServer(since)
}
}
In the Activity make sure you use ListAdapter
private lateinit var mDataViewModel: DataViewModel
private lateinit var mAdapter: ListAdapter
override fun onCreate(savedInstanceBundle: Bundle?) {
...
mDataViewModel.data(getSince())
mDataViewModel.dataList.observe(this, Observer(adapter::submitList))
}
Initial Answer
First of all, I would recommend you to look into Android Architecture Blueprints v2. According to Android Architecture Blueprints v2 following improvements can be made,
DataRepository
should be injected rather than instantiating internally according to the Dependency Inversion principle.You should decouple the functions in the
ViewModel
. Instead of returning theLiveData
, thedata()
function can update an encapsulatedLiveData
. For example,class DataViewModel(private val repository = DataRepository) : ViewModel() {
private val _dataList = MutableLiveData<List<MyData>>()
val dataList : LiveData<List<MyData>> = _dataList
fun data(since: Long) = viewModelScope.launch {
val list = repository.getData(since)
_dataList.value = list
}
...
}Repository
should be responsible for fetching data from remote data source and save it to local data source. You should have two data source i.e.RemoteDataSource
andLocalDataSource
that should be injected in the Repository. You can also have an abstractDataSource
. Let's see how can you improve your repository,interface DataSource {
suspend fun getData(since: Long) : List<MyData>
suspend fun saveData(list List<MyData>)
suspend fun delete()
}
class RemoteDataSource(dto: PostsDto) : DataSource { ... }
class LocalDataSource(dao: PostsDao) : DataSource { ... }
class DataRepository(private val remoteSource: DataSource, private val localSource: DataSource) {
suspend fun getData(since: Long) : List<MyData> = withContext(Dispatchers.IO) {
val data = remoteSource.getData(since)
localSource.delete()
localSource.save(data)
return@withContext localSource.getData(since)
}
...
}In your
Activity
, you just need to observe thedataList: LiveData
and submit it's value toListAdapter
.private lateinit var mDataViewModel: DataViewModel
private lateinit var mAdapter: ListAdapter
override fun onCreate(savedInstanceBundle: Bundle?) {
...
mDataViewModel.data(since)
mDataViewModel.dataList.observe(this, Observer(adapter::submitList))
}
Best way to request data from server
The best way to achieve this is to use an HttpURLConnection
to make your web calls inside an AsyncTask
and then pass the result back to your calling Activity through a callback. Here's some code to help you get started:
The first thing you should understand is how to properly use a callback with an AsyncTask
. Here is an example AsyncTask
that defines a callback interface:
import android.os.AsyncTask;
public class TestTask extends AsyncTask<String, Void, String> {
TestTaskCallback listener;
public TestTask(TestTaskCallback listener) {
this.listener = listener;
}
protected String doInBackground(String... args) {
String input = args[0];
String output = "simulated return value";
return output;
}
protected void onPostExecute(String result) {
listener.onResultReceived(result);
}
public interface TestTaskCallback {
void onResultReceived(String result);
}
}
The way this works is, you define a public interface that you then implement in your Activity. This acts as a "listener" that is waiting for any data that is sent through to it. We define the interface TestTaskCallback
because we are going to be sending our data from our AsyncTask
to our calling Activity.
Then in the Activity, we need to implement this interface, and pass in a reference to our implementation to the task when we create it. That way, when the task fires, it knows where to send the result, which is back to our Activity. An example implementation might look like this:
public class TestActivity extends AppCompatActivity implements TestTask.TestTaskCallback {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.your_layout);
new TestTask(this).execute("Some input");
}
public void onResultReceived(String result) {
Log.d("TEST TASK RESULT", result);
}
}
So our Activity implements the interface that we defined inside our AsyncTask
, and notice that our AsyncTask
takes the reference to this implementation (passed in through the constructor) and sends data to it in the onPostExecute()
method. This will allow your result to be sent to the main UI thread so that you can update your Activity appropriately.
The only thing left is to actually make the web calls. I would recommend using an HttpURLConnection
for this. You would put this code inside the doInBackground()
method of your AsyncTask
.
I'll show you an example web service call I have set up. This shows how to make a web service call to retrieve a JSON response. It looks something like this:
//The JSON we will get back as a response from the server
JSONObject jsonResponse = null;
//Http connections and data streams
URL url;
HttpURLConnection httpURLConnection = null;
OutputStreamWriter outputStreamWriter = null;
try {
//open connection to the server
url = new URL("your_url_to_web_service");
httpURLConnection = (HttpURLConnection) url.openConnection();
//set request properties
httpURLConnection.setDoOutput(true); //defaults request method to POST
httpURLConnection.setDoInput(true); //allow input to this HttpURLConnection
httpURLConnection.setRequestProperty("Content-Type", "application/json"); //header params
httpURLConnection.setRequestProperty("Accept", "application/json"); //header params
httpURLConnection.setFixedLengthStreamingMode(jsonToSend.toString().getBytes().length); //header param "content-length"
//open output stream and POST our JSON data to server
outputStreamWriter = new OutputStreamWriter(httpURLConnection.getOutputStream());
outputStreamWriter.write(jsonToSend.toString());
outputStreamWriter.flush(); //flush the stream when we're finished writing to make sure all bytes get to their destination
//prepare input buffer and get the http response from server
StringBuilder stringBuilder = new StringBuilder();
int responseCode = httpURLConnection.getResponseCode();
//Check to make sure we got a valid status response from the server,
//then get the server JSON response if we did.
if(responseCode == HttpURLConnection.HTTP_OK) {
//read in each line of the response to the input buffer
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(httpURLConnection.getInputStream(),"utf-8"));
String line;
while ((line = bufferedReader.readLine()) != null) {
stringBuilder.append(line).append("\n");
}
bufferedReader.close(); //close out the input stream
try {
//Copy the JSON response to a local JSONObject
jsonResponse = new JSONObject(stringBuilder.toString());
} catch (JSONException je) {
je.printStackTrace();
}
}
} catch (IOException ioe) {
ioe.printStackTrace();
} finally {
if(httpURLConnection != null) {
httpURLConnection.disconnect(); //close out our http connection
}
if(outputStreamWriter != null) {
try {
outputStreamWriter.close(); //close our output stream
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
}
//Return the JSON response from the server.
return jsonResponse;
This is pretty much all you need to know to do exactly what it is you are trying to do. I realize this is a ton of info to throw at you all at once, but if you take your time and work through it piece by piece, you'll find it's not too difficult after all and is actually a VERY powerful tool that you'll use all the time programming Android apps!
Hope this helps. Feel free to ask questions for any parts you don't fully understand yet!
How to fetch data from a website in android app after entering his personal details during registration?
You can write a RESTful web service on your server which takes the arguments like (age,income,etc) and store these arguments to a new variable then use those variable when connecting the government's website. After that you can use your government's APIs if there are any, if not: you can write a web scraper for that particular website.
You can check this tutorial for web scraping with Node JS:
https://scotch.io/tutorials/scraping-the-web-with-node-js
how can android app read data from database on the server?
Basically you need a Web Service that read/write into your DB. Android then read the data through JSONObject and parser.
Direct connection through JDBC is insecure.
Below is tutorial on How Android connect to mySql on server
- http://www.tutorialspoint.com/android/android_php_mysql.htm
- http://www.helloandroid.com/tutorials/connecting-mysql-database
- http://www.androidhive.info/2012/05/how-to-connect-android-with-php-mysql/
You may also take a look on this thread
- How to connect Android app to MySQL database?
Android app . fetching data from database
If you wanna use the database as centralized then it should be a server but not Local DB.
Local db can be accessible within the device as we all know and the below can help you to handle the server.
Step 1: First buy a server in either GoDaddy or 000webhost.com(Free server will be available)
step 2: Create a database and make some tables which matches your requirement.
step 3: Remaining all coding and integrating part is in this Url
Android Php connect
This is the basic API for the starters, keep going.
Android API integration using Java servlet
Step 1: Download Eclipse EE(Express Edition) or Add Eclipse EE plugin to your Existing Eclipse
Step 2: In your Eclipse go to File > New > Project > Web > Dynamic Web Project > next.
Step 3: Name your Project and select Apache Tomcat v7.0 as the target runtime and click finish.
Step 4: Now right click on project > New > Other > Web > Servelt. Name the Servlet as your wish.
Step 5: As an Example I placed here two multiply the number with 2
import java.io.IOException;
import java.io.OutputStreamWriter;
import javax.servlet.ServletException;
import javax.servlet.ServletInputStream;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebServlet("/DoubleMeServlet")
public class DoubleMeServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
public DoubleMeServlet() {
super();
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.getOutputStream().println("Hurray !! This Servlet Works");
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
try {
int length = request.getContentLength();
byte[] input = new byte[length];
ServletInputStream sin = request.getInputStream();
int c, count = 0 ;
while ((c = sin.read(input, count, input.length-count)) != -1) {
count +=c;
}
sin.close();
String recievedString = new String(input);
response.setStatus(HttpServletResponse.SC_OK);
OutputStreamWriter writer = new OutputStreamWriter(response.getOutputStream());
Integer doubledValue = Integer.parseInt(recievedString) * 2;
writer.write(doubledValue.toString());
writer.flush();
writer.close();
} catch (IOException e) {
try{
response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
response.getWriter().print(e.getMessage());
response.getWriter().close();
} catch (IOException ioe) {
}
}
}
}
Step 6: Right click on Servlet project > Run as > Run on Server. Run on Server Dialog should pop up. Select "Manually define a new server" and also Tomcat v7.0 under server type." Before that make sure your tomcat server is up and running. Open your web browser and type http://localhost:8080. You should see a default page displayed by tomcat server.
And below is the sample code, you should call your servlet file from your android app like this mentioned way
package com.app.myapp;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.URL;
import java.net.URLConnection;
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
public class DoubleMeActivity extends Activity implements OnClickListener {
EditText inputValue=null;
Integer doubledValue =0;
Button doubleMe;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.calculate);
inputValue = (EditText) findViewById(R.id.inputNum);
doubleMe = (Button) findViewById(R.id.doubleme);
doubleMe.setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch (v.getId()){
case R.id.doubleme:
new Thread(new Runnable() {
public void run() {
try{
URL url = new URL("http://10.0.2.2:8080/MyServletProject/DoubleMeServlet");
URLConnection connection = url.openConnection();
String inputString = inputValue.getText().toString();
//inputString = URLEncoder.encode(inputString, "UTF-8");
Log.d("inputString", inputString);
connection.setDoOutput(true);
OutputStreamWriter out = new OutputStreamWriter(connection.getOutputStream());
out.write(inputString);
out.close();
BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
String returnString="";
doubledValue =0;
while ((returnString = in.readLine()) != null)
{
doubledValue= Integer.parseInt(returnString);
}
in.close();
runOnUiThread(new Runnable() {
public void run() {
inputValue.setText(doubledValue.toString());
}
});
}catch(Exception e)
{
Log.d("Exception",e.toString());
}
}
}).start();
break;
}
}
}
Refer the below link for complete reference
Connect android app with servlet
Fetch Data from website to android app
Yes, it is possible. You will need the following components:
The website won't notify you when something changes. Thus, you have to poll the website frequently to find out if something changed.
Since the website offers no API, you will have to download the HTML and parse it.
Using these keywords in your search, you should find lots of material on StackOverflow, e.g.
- Android Polling from a Server periodically
- How can I parse webpage content in Android
I can't retrieve data from server to android studio although data is shown in a browser
you can use StringRequest instead of jsonObject with the new library of volley
compile 'com.android.volley:volley:1.0.0'
How to make an Activity fetch data from the server automatically in android
you have to call the service on second activity's on create method after setContentView() and fetch the data from the shared preferences and pass that data to the php script and catch response and show the data to the apropreate location.
and the credentials you want to give for one day duration then check the entry with the system date and validate it. if it is belong to the same date then it will pass to the thank you page otherwise it allow user to move to second activity.
Related Topics
Difference Between App-Debug.Apk and App-Debug-Unaligned.Apk
How to Get The Dimensions of a Drawable in an Imageview
Android 4.4.2 - Java.Lang.Runtimeexception: Performing Stop of Activity That Is Not Resumed
How to Place App Icon on Launcher Home Screen
Android Studio (Not Installed), When Run Flutter Doctor While Android Studio Installed on Machine
Easier Way to Get View's Id (String) by Its Id (Int)
How to Call a Wcf Service Using Ksoap2 on Android
How to Convert Time to " Time Ago " in Android
How to Store Object in Sqlite Database
Set Starting Height of Collapsingtoolbarlayout
No Repository Found Error in Installing Adt in Eclipse Indigo
How to Change Color of Vector Drawable Path on Button Click
How to Programmatically Pair a Bluetooth Device on Android
How to Set Android Tablayout in The Bottom of The Screen
How to Find Out Carrier's Name in Android
Onclick Method Not Working Properly After Nestedscrollview Scrolled