When I change from wi-fi to 3g or vice versa the my AsyncTask will cause a error. So I want to trace this and restart the loading progress(or stop and proceed the asynctask if possible) when this happens. I looked it up on google and find that the BroadcastReceiver onReceive is called when this happens. The problem now is that I still don't get the exact moment when this happens.
Oncreate
registerReceiver(mConnReceiver,new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION));
AsyncTask point of error(it's called on the HttpClient line):
#Override
protected String doInBackground(String... params)
{
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost(params[0]);
try
{
if(!isCancelled())//I have set this after I found the error
{
HttpResponse response = httpclient.execute(httppost);
jsonResult = inputStreamToString(
response.getEntity().getContent()).toString();
}
}
The broadcastreceiver
private BroadcastReceiver mConnReceiver = new BroadcastReceiver()
{
#Override
public void onReceive(Context context, Intent intent)
{
boolean noConnectivity = intent.getBooleanExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, false);
NetworkInfo changes = intent.getParcelableExtra(ConnectivityManager.EXTRA_NETWORK_INFO);
Log.w("current", "" + changes);
if(noConnectivity)
{
task.cancel(true);
task2.cancel(true);
task3.cancel(true);
}
Log.w("taskIsCanceled","" + task.isCancelled());
}
};
So I have two problems tracing the event of the error and restarting or stopping and proceeding the asynctaskes. I have 3 asynctaskes which take turns.
When I switch from 3g to wi-fi the noConnectivity boolean always returns that I have connection. While when I go from wi-fi to 3g it first returns that I dont and shortly after that I have(so that it connected).
You can use reflections to monitor mobile data changes.
public class NetworkStateReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
if(intent.getExtras() != null){
final ConnectivityManager mConnectivityManager = (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);
boolean mobileDataEnabled = false;
try{
Class cmClass = Class.forName(mConnectivityManager.getClass().getName());
Method method = cmClass.getDeclaredMethod("getMobileDataEnabled");
method.setAccessible(true); // Make the method callable
mobileDataEnabled = (Boolean)method.invoke(mConnectivityManager);
} catch(Exception e){
return;
}
Toast.makeText(BackroundService.this, "Data state changed", Toast.LENGTH_LONG).show();
}
}
}
Related
I am trying to build my first app for Android and, firstly, I compiled the example application in the networkusage.zip file on the Android Developers website (location: http://developer.android.com/training/basics/network-ops/index.html). It worked fine, so I tried to modify it according to my goal.
The modified code works fine when connects to a Wi-Fi network, but if I set it to any network it fails displaying the message: "Lost connection."
I modified only "NetworkActivity.java"
public class NetworkActivity extends Activity {
public static final String WIFI = "Wi-Fi";
public static final String ANY = "Any";
private static final String URL ="http://www.kibao.org/simu/wap.php?lng=";
final Context context = this;
// Whether there is a Wi-Fi connection.
private static boolean wifiConnected = false;
// Whether there is a mobile connection.
private static boolean mobileConnected = false;
// Whether the display should be refreshed.
public static boolean refreshDisplay = true;
// The user's current network preference setting.
public static String sPref = null;
public static String pagina = "";
// The BroadcastReceiver that tracks network connectivity changes.
private NetworkReceiver receiver = new NetworkReceiver();
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Register BroadcastReceiver to track connection changes.
IntentFilter filter = new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION);
receiver = new NetworkReceiver();
this.registerReceiver(receiver, filter);
}
// Refreshes the display if the network connection and the
// pref settings allow it.
#Override
public void onStart() {
super.onStart();
// Gets the user's network preference settings
SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(this);
// Retrieves a string value for the preferences. The second parameter
// is the default value to use if a preference value is not found.
sPref = sharedPrefs.getString("listPref", "Wi-Fi");
updateConnectedFlags();
// Only loads the page if refreshDisplay is true. Otherwise, keeps previous
// display. For example, if the user has set "Wi-Fi only" in prefs and the
// device loses its Wi-Fi connection midway through the user using the app,
// you don't want to refresh the display--this would force the display of
// an error page instead of stackoverflow.com content.
if (refreshDisplay) {
loadPage();
}
}
#Override
public void onDestroy() {
super.onDestroy();
if (receiver != null) {
this.unregisterReceiver(receiver);
}
}
// Checks the network connection and sets the wifiConnected and mobileConnected
// variables accordingly.
private void updateConnectedFlags() {
ConnectivityManager connMgr =
(ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo activeInfo = connMgr.getActiveNetworkInfo();
if (activeInfo != null && activeInfo.isConnected()) {
wifiConnected = activeInfo.getType() == ConnectivityManager.TYPE_WIFI;
mobileConnected = activeInfo.getType() == ConnectivityManager.TYPE_MOBILE;
} else {
wifiConnected = false;
mobileConnected = false;
}
}
// Uses AsyncTask subclass to download the XML feed from stackoverflow.com.
// This avoids UI lock up. To prevent network operations from
// causing a delay that results in a poor user experience, always perform
// network operations on a separate thread from the UI.
private void loadPage() {
if (((sPref.equals(ANY)) && (wifiConnected || mobileConnected))
|| ((sPref.equals(WIFI)) && (wifiConnected))) {
// AsyncTask subclass
//new DownloadXmlTask().execute(URL);
String lng = getResources().getString(R.string.lng);
new DownloadWebpageTask().execute(URL.concat(lng));
} else {
showErrorPage();
}
}
// Displays an error if the app is unable to load content.
private void showErrorPage() {
setContentView(R.layout.main);
// The specified network connection is not available. Displays error message.
WebView myWebView = (WebView) findViewById(R.id.webview);
myWebView.loadData(getResources().getString(R.string.connection_error),
"text/html", null);
}
// Populates the activity's options menu.
#Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.mainmenu, menu);
return true;
}
// Handles the user's menu selection.
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.settings:
Intent settingsActivity = new Intent(getBaseContext(), SettingsActivity.class);
startActivity(settingsActivity);
return true;
case R.id.refresh:
loadPage();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
// Given a string representation of a URL, sets up a connection and gets
// an input stream.
private InputStream downloadUrl(String urlString) throws IOException {
URL url = new URL(urlString);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setReadTimeout(10000 /* milliseconds */);
conn.setConnectTimeout(15000 /* milliseconds */);
conn.setRequestMethod("GET");
conn.setDoInput(true);
// Starts the query
conn.connect();
InputStream stream = conn.getInputStream();
return stream;
}
/**
*
* This BroadcastReceiver intercepts the android.net.ConnectivityManager.CONNECTIVITY_ACTION,
* which indicates a connection change. It checks whether the type is TYPE_WIFI.
* If it is, it checks whether Wi-Fi is connected and sets the wifiConnected flag in the
* main activity accordingly.
*
*/
public class NetworkReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
ConnectivityManager connMgr =
(ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo = connMgr.getActiveNetworkInfo();
// Checks the user prefs and the network connection. Based on the result, decides
// whether
// to refresh the display or keep the current display.
// If the userpref is Wi-Fi only, checks to see if the device has a Wi-Fi connection.
if (WIFI.equals(sPref) && networkInfo != null
&& networkInfo.getType() == ConnectivityManager.TYPE_WIFI) {
// If device has its Wi-Fi connection, sets refreshDisplay
// to true. This causes the display to be refreshed when the user
// returns to the app.
refreshDisplay = true;
Toast.makeText(context, R.string.wifi_connected, Toast.LENGTH_SHORT).show();
// If the setting is ANY network and there is a network connection
// (which by process of elimination would be mobile), sets refreshDisplay to true.
} else if (ANY.equals(sPref) && networkInfo != null) {
refreshDisplay = true;
// Otherwise, the app can't download content--either because there is no network
// connection (mobile or Wi-Fi), or because the pref setting is WIFI, and there
// is no Wi-Fi connection.
// Sets refreshDisplay to false.
} else {
refreshDisplay = false;
Toast.makeText(context, R.string.lost_connection, Toast.LENGTH_SHORT).show();
}
}
}
// Implementation of AsyncTask used to download Webpage
private class DownloadWebpageTask extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(String... urls) {
try {
return loadWebpageFromNetwork(urls[0]);
} catch (IOException e) {
return getResources().getString(R.string.connection_error);
}
}
#Override
protected void onPostExecute(String result) {
setContentView(R.layout.main);
// Displays the HTML string in the UI via a WebView
WebView myWebView = (WebView) findViewById(R.id.webview);
//myWebView.loadData(result, "text/html", null);
//myWebView.loadDataWithBaseURL("http://www.kibao.org",result, "text/html", "utf-8",null);
String lng = getResources().getString(R.string.lng);
myWebView.loadUrl(URL.concat(lng));
}
}
// Uploads XML from stackoverflow.com, parses it, and combines it with
// HTML markup. Returns HTML string.
private String loadWebpageFromNetwork(String urlString) throws IOException {
InputStream stream = null;
try {
stream = downloadUrl(urlString);
pagina = getStringFromInputStream(stream);
// Makes sure that the InputStream is closed after the app is
// finished using it.
} finally {
if (stream != null) {
stream.close();
}
}
// StackOverflowXmlParser returns a List (called "entries") of Entry objects.
// Each Entry object represents a single post in the XML feed.
// This section processes the entries list to combine each entry with HTML markup.
// Each entry is displayed in the UI as a link that optionally includes
// a text summary.
return pagina;
}
// convert InputStream to String
private static String getStringFromInputStream(InputStream is) {
BufferedReader br = null;
StringBuilder sb = new StringBuilder();
String line;
try {
br = new BufferedReader(new InputStreamReader(is));
while ((line = br.readLine()) != null) {
sb.append(line);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (br != null) {
try {
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return sb.toString();
}
}
Please help me to understand my mistake.
Thanks a lot,
Nino V
I found my mistake: it was a very stupid one! It was in my arrays.xml where I localized both names and values, so the code didn't recognize the value "ANY" which in my Italian phone was "Qualsiasi"!
Thank you for your attention.
Nino V
My Application drains the battery.I have used services where a request is sent to url.The service is called from my class which extends Application.Below is my code.
public class GApplication extends Application {
private static final String TAG ="GApplication";
private HttpClient httpClient;
private DatabaseHelper databaseHelper;
#Override
public void onCreate(){
super.onCreate();
startService(new Intent(this, GService.class));
httpClient = createHttpClient();
databaseHelper = new DatabaseHelper(this);
}
#Override
public void onLowMemory(){
super.onLowMemory();
shutdownHttpClient();
}
#Override
public void onTerminate(){
super.onTerminate();
stopService(new Intent(this, GService.class));
shutdownHttpClient();
databaseHelper.close();
}
private void shutdownHttpClient(){
if(httpClient != null && httpClient.getConnectionManager() != null){
httpClient.getConnectionManager().shutdown();
}
}
public DatabaseHelper getDatabaseHelper(){
if(databaseHelper == null){
databaseHelper = new DatabaseHelper(this);
}
return databaseHelper;
}
public HttpClient getHttpClient(){
return httpClient;
}
public HttpClient createHttpClient(){
HttpParams params = new BasicHttpParams();
HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
HttpProtocolParams.setContentCharset(params, HTTP.DEFAULT_CONTENT_CHARSET);
HttpProtocolParams.setUseExpectContinue(params, true);
SchemeRegistry registry = new SchemeRegistry();
registry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
registry.register(new Scheme("https", PlainSocketFactory.getSocketFactory(), 443));
return new DefaultHttpClient(new ThreadSafeClientConnManager(params, registry), params);
}
public boolean isOnline(){
boolean isConnected = false;
try{
ConnectivityManager manager = (ConnectivityManager)getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo info = manager.getActiveNetworkInfo();
isConnected = (info != null && info.isAvailable() && info.isConnected());
}
catch(Exception e){
isConnected = false;
if(e.getMessage() != null) Log.e(TAG, e.getMessage());
}
return isConnected;
}
}
My Gservice Class
public class GService extends Service {
private static final String TAG = "Gservice";
public IBinder onBind(Intent intent) {
return null;
}
public void onCreate(){
super.onCreate();
Log.i(TAG, "starting GService");
if(isOnline()){
URI uri = URI.create("http://myserver/Android/UploadImage/newAlert.php");
new UpdateCheckAsyncTask(getHttpClient()).execute(uri);
}
}
boolean isOnline(){
return ((GApplication)getApplication()).isOnline();
}
HttpClient getHttpClient(){
return ((GApplication)getApplication()).getHttpClient();
}
DatabaseHelper getDatabaseHelper(){
return ((GApplication)getApplication()).getDatabaseHelper();
}
class UpdateCheckAsyncTask extends WebAsyncTaskBase{
public UpdateCheckAsyncTask(HttpClient httpClient) {
super(httpClient);
}
protected String doInBackground(URI... params) {
return getHttpContent(params[0]);
}
protected void onProgressUpdate(Integer... progress){
}
protected void onPostExecute(String result){
if(result == null){
Log.i(TAG, "Call returned null");
return;
}
try {
Log.i(TAG, "Processsing request");
JSONObject json = new JSONObject(result);
new BlogDbAsyncTask(getDatabaseHelper()).execute(json);
} catch (JSONException e) {
if(e.getMessage() != null) Log.e(TAG, e.getMessage());
}
}
class BlogDbAsyncTask extends DbAsyncTaskBase<JSONObject, Boolean, BlogInfo>{
public BlogDbAsyncTask(DatabaseHelper database) {
super(database);
}
#Override
protected BlogInfo doInBackground(JSONObject... json) {
BlogInfo blogInfo = new BlogInfo();
BlogDAO dao = new BlogDAO(GService.this, getDatabaseHelper());
try {
Log.i(TAG, "Adding new blog entry");
Blog blog = dao.Select(json[0].getInt("FeedId"));
if(blog.UID == null){
blog.UID = json[0].getInt("FeedId");
blog.Text = json[0].getString("Text");
blog.Title = json[0].getString("Header");
blog.PostedOn = json[0].getString("DisplayDate");
blog.PostedBy = "Gservice";
dao.Insert(blog);
blogInfo.Blog = blog;
blogInfo.IsNew = true;
}
} catch (JSONException e) {
if(e.getMessage() != null) Log.e(TAG, e.getMessage());
}
return blogInfo;
}
protected void onPostExecute(BlogInfo result){
}
}
class BlogInfo{
public Blog Blog;
public boolean IsNew;
}
}
Probably the Onterminate method is never called in GApplication class which makes the service run continuously.Please Suggest if any issues can be found with this code.Also Suggest how to stop service if onterminate is never called in device..Thanks in advance.
onTerminate isn't supposed to be called on real devices:
This method is for use in emulated process environments. It will never
be called on a production Android device, where processes are removed
by simply killing them; no user code (including this callback) is
executed when doing so.
you should consider using services instead, and use the appropriate one according to your needs.
if you wish to know when the app was "closed", you need to track the state of the activities. for example, you could have a global counter that counts the number of active activities. for each onCreate, you increase its value. for each onDestroy, you decrease its value. when it reaches 0, it means that no activity is currently active.
however, you should be warned that it's not quite accurate, since activities will be destroyed and re-created when the configuration has changed, so you will need to handle it too.
as i've mentioned, you should consider using a service instead. maybe bind to it on each activity that you need, and unbind when the activity was destroyed. maybe even make it run in the foreground and close it on demand... all depends on your requirements.
You need to use an IntentService instead of Service. This way the service will shut itself down once it completes the task.
I have created an intent download service and I want to pass download data to Toast and into Text in main activity. Download service should start from alarm manager repeatedly. How do I do this?
Currently, it does not show in Toast, but I have network traffic; data is downloaded but not shown.
Relevant code:
public class DownloadService extends IntentService {
public String response;
public DownloadService() {
super("DownloadService");
}
// Will be called asynchronously be Android
#Override
protected void onHandleIntent(Intent intent) {
//String urldown = intent.getStringExtra("url");
String urldown="http://......";
DefaultHttpClient client = new DefaultHttpClient();
HttpGet httpGet = new HttpGet(urldown);
try {
HttpResponse execute = client.execute(httpGet);
InputStream content = execute.getEntity().getContent();
BufferedReader buffer = new BufferedReader(new InputStreamReader(content));
String s = "";
while ((s = buffer.readLine()) != null) {
response += s;
}
} catch (IOException e) {
e.printStackTrace();
}
Intent intentsend=new Intent("update");
intentsend.putExtra( "downdata",response);
sendBroadcast(intentsend);
}
This can be implemented with BroadcastReceiver:
In your activity, add the following code:
private BroadcastReceiver updateReceiver;
//...
#Override
protected void onResume() {
super.onResume();
updateReceiver=new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
//get extras, do some stuff
}
};
IntentFilter updateIntentFilter=new IntentFilter("update");
registerReceiver(updateReceiver, updateIntentFilter);
}
#Override
protected void onPause() {
super.onPause();
if (this.updateReceiver!=null)
unregisterReceiver(updateReceiver);
}
And then, in your IntentService, just send broadcast with the same action:
Intent intent=new Intent("update");
intent.putExtra(...);
sendBroadcast(intent);
For me personally the receiver was not working so instead I created a singleton class where I was using the setter methods to set variables and the getter methods to get them to the particular activity.
I have a specific question about wifi connection in Android.I'm working on a project which is downloading some data from web server and every time before starting the synchronization I'm checking about internet connection like this :
public static boolean isOnline(Context context) {
ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo netInfo = cm.getActiveNetworkInfo();
if (netInfo != null && netInfo.isConnectedOrConnecting()) {
return true;
}
return false;
}
public static boolean chkNetworkStatus(Context context) {
boolean result = false;
new Thread() {
#Override
public void run() {
for(int i=0;i<3;i++){
HttpGet requestForTest = new HttpGet("http://m.google.com");
try {
new DefaultHttpClient().execute(requestForTest);
responded = true;
} catch (Exception e) {
responded = false;
}
}
}
}.start();
boolean isOnline = isOnline(context);
if(responded && isOnline){
result = true;
} else {
result = false;
}
Log.e("","responded : "+responded);
return result;
}
But in this situation when I'm still connected to wifi and i'm walking (loosing connection) and press sync button it's still returning true because I'm connected, but actually it's not doing anything.
Is there anyway that I can detect this or I should use connectionTimeOut function in HttpURLConnection class which I'm using?
Actually, I don't know this one solve your problem or not but, you can set connection time-out with your HttpGet request,
This works in my case, So i don't need to check Internet availability..
try
{
HttpGet request = new HttpGet(url));
HttpParams httpParameters = new BasicHttpParams();
// Set the timeout in milliseconds until a connection is established.
// The default value is zero, that means the timeout is not used.
int timeoutConnection = 60000;
HttpConnectionParams.setConnectionTimeout(httpParameters, timeoutConnection);
// Set the default socket timeout (SO_TIMEOUT)
// in milliseconds which is the timeout for waiting for data.
int timeoutSocket = 60000;
HttpConnectionParams.setSoTimeout(httpParameters, timeoutSocket);
// create object of DefaultHttpClient
DefaultHttpClient httpClient = new DefaultHttpClient(httpParameters);
request.addHeader("Content-Type", "application/json");
HttpResponse response = httpClient.execute(request);
// get response entity
HttpEntity entity = response.getEntity();
// convert entity response to string
if (entity != null)
{
result = EntityUtils.toString(entity);
}
}
catch (SocketException e)
{
return "-222" + e.toString();
}
catch (Exception e)
{
return "-333" + e.toString();
}
Note: the request and other code may be different in your case, It just the idea of how HttpGet params used for set Connection TimeOut..
Basically you will receive broadcast when network connectivity changes if you register.
android.net.conn.CONNECTIVITY_CHANGE
For Solution
Here you go.
You will need to register for and handle BroadCastReceiver android.net.conn.CONNECTIVITY_CHANGE
Step 1
Include following permission in manifest
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
Step2
Let Android know which class will be register for BroadCast Receiver.
<receiver android:name="ConnectivityReceiver_package_name.ConnectivityReceiver">
<intent-filter>
<action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
</intent-filter>
</receiver>
Step 3
Put your logic for various Network States.
public class ConnectivityReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
boolean noConnectivity = intent.getBooleanExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY,false);
if(noConnectivity){
//Show Warning Message
//Take appropriate actions.
}
}
}
try to do it like this:
public static void isNetworkAvailable(final Handler handler, final int timeout)
{
// ask fo message '0' (not connected) or '1' (connected) on 'handler'
// the answer must be send before before within the 'timeout' (in
// milliseconds)
new Thread()
{
private boolean responded = false;
#Override
public void run()
{
// set 'responded' to TRUE if is able to connect with google
// mobile (responds fast)
new Thread()
{
#Override
public void run()
{
HttpGet requestForTest = new HttpGet("http://m.google.com");
try
{
new DefaultHttpClient().execute(requestForTest); // can
// last...
responded = true;
}
catch (Exception e)
{
}
}
}.start();
try
{
int waited = 0;
while (!responded && (waited < timeout))
{
sleep(100);
if (!responded)
{
waited += 100;
}
}
}
catch (InterruptedException e)
{
} // do nothing
finally
{
if (!responded)
{
handler.sendEmptyMessage(0);
}
else
{
handler.sendEmptyMessage(1);
}
}
}
}.start();
}
Handler h = new Handler()
{
#Override
public void handleMessage(Message msg)
{
if (msg.what != 1)
{ // code if not connected
}
else
{ // code if connected
}
}
};
And in your Activity, call it like that:
isNetworkAvailable(h, 2000);
I'm trying to implement a service to handle the communication with the server for the following code. I don't know much about the design architecture for these.
Here is my service class
public class BgService extends Service {
private static final String TAG = BgService.class.getSimpleName();
private Timer timer;
SendJsonRequest sjr;
private TimerTask updateTask = new TimerTask(){
#Override
public void run(){
try{
SendJsonRequest sjr = new SendJsonRequest();
sjr.carMake();
Log.i(TAG, "LOOK AT ME");
}
catch(Exception e){
Log.w(TAG,e);
}
}
};
#Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
#Override
public void onCreate(){
super.onCreate();
Log.i(TAG, "Service creating");
timer = new Timer("Server listening timer");
timer.schedule(updateTask, 1000L, 60*1000L);
}
#Override
public void onDestroy(){
super.onDestroy();
Log.i(TAG, "Service Destroying");
timer.cancel();
timer = null;
}
}
Here is my SendJsonRequest class
public class SendJsonRequest{
private static final String TAG = "SendJsonRequest";
private static String URL = "xxxxxxxxx";
private static String infoRec;
public static void createJsonObj(String path, Map x){
infoRec = CreateJsonRequest.jsonRequest(URL+path, x );
System.out.println(infoRec);
}
public static void carMake(){
String path = "/CarMake";
Map<String, Object> z = new HashMap<String,Object>();
z.put("Name", "Ford");
z.put("Model", "Mustang");
createJsonObj(path, z);
}
}
Here is my CreateJsonObject class
public class CreateJsonRequest {
public static String jsonRequest(String URL, Map<String,Object> params){
try{
DefaultHttpClient httpClient = new DefaultHttpClient();
HttpPost httpPost = new HttpPost(URL);
JSONObject holder = new JSONObject();
for (Map.Entry<String, Object> m : params.entrySet()){
try {
holder.put(m.getKey(), m.getValue());
}
catch (JSONException e) {
Log.e("Hmmmm", "JSONException : "+e);
}
}
StringEntity se;
se = new StringEntity(holder.toString());
httpPost.setEntity(se);
httpPost.setHeader("Accept", "text/json");
httpPost.setHeader("Content-type", "text/json");
HttpResponse response = (HttpResponse) httpClient.execute(httpPost);
HttpEntity entity = response.getEntity();
if(entity != null){
InputStream is = entity.getContent();
Header contentEncoding = response.getFirstHeader("Content-Encoding");
String result= convertToString(is);
is.close();
System.out.println(result);
return result;
}
}
catch(Exception e)
{
e.printStackTrace();
}
return null;
}
Sorry for the massive amount of code. How I implemented my service is obviously not correct, I just have no clue where to start to get a service handling the json requests to the server. Thanks in advance.
To be more clear, this did work on a button click, now I'm trying to get it to all run in the background with the service. So I guess my question is what goes where in the service?
My activity successfully starts the service, the service would work and print "look at me" to the logcat every minute. Then I added the try{ sjr.carMake()} and it catches an exception.
You can use a broadcast receiver. This is a way to have your code start at certain times indicated by Android OS - for example, you can have it start when Android finished booting up (this is where I run my services usually.
The best way is to use the AlarmManager class, and tell your service how often to run.
Tell us more about what you're trying to do, and what the problem is, and we can give you a more concise answer...
UPDATE:
Have you created an entry in the manifest.xml file for the service?
UPDATE
Here is how I'm doing it in my application. This is your "hook" to the OS. It's going to fire when it finishes booting (don't forget to make in entry in the manifest for this!)
public class TmBroadcastReceiver extends BroadcastReceiver {
#Override
public void onReceive(final Context context, final Intent bootintent) {
try{
Log.i("Taskmotion-ROBOT", "Robot Broadcast signal received on Boot. Trying to start Alarm scheduler");
Intent mServiceIntent = new Intent(context, ServiceAlarm.class);
context.startService(mServiceIntent);
}
catch(Exception e)
{
Log.i("Taskmotion", "Failed to start service...");
}
}
}
This Broadcast receiver calls a service that implements the AlarmManager class. The alarm manager sets up a schedule to run my service at a specified interval. Note that the alarms are deleted when the phone is shut down - but then recreated again when process is repeated as the phone boots back up and runs the BroadcastReceiver again.
public class ServiceAlarm extends Service {
private PendingIntent mAlarmSender;
#Override
public void onCreate() {
try{
Log.i("Taskmotion-ROBOT", "Setting Service Alarm Step 1");
mAlarmSender = PendingIntent.getService(this.getApplicationContext(),
0, new Intent(this.getApplicationContext(), BackgroundService.class), 0);
}
catch(Exception e)
{
Log.i("Taskmotion-ROBOT", "Problem at 1 :" + e.toString());
}
long firstTime = SystemClock.elapsedRealtime();
Log.i("Taskmotion-ROBOT", "Setting Service Alarm Step 2");
// Schedule the alarm!
AlarmManager am = (AlarmManager)getSystemService(ALARM_SERVICE);
am.setRepeating(AlarmManager.ELAPSED_REALTIME,
firstTime, AlarmManager.INTERVAL_HOUR, mAlarmSender);
this.stopSelf();
}
#Override
public IBinder onBind(Intent arg0) {
// TODO Auto-generated method stub
return null;
}
}
I haven't refactored this code yet, it was my first go at it. I see now that I'm looking at it again that I could probably do the scheduling inside the BroadcastReceiver, but for the sake of getting you something that works, I'll continue.
As indicated by AlarmManager.INTERVAL_HOUR, my service will run once an hour. The service that I want to run is defined in the pendingIntent (BackgroundService.class). This is where you put your own service class.
I reworked your service class for you, and removed the timer (functionality replaced by the BroadcastReceiver & AlarmManager).
public class BgService extends Service {
private static final String TAG = BgService.class.getSimpleName();
SendJsonRequest sjr;
#Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
#Override
public void onCreate(){
super.onCreate();
Log.i(TAG, "Service creating");
//DO YOUR WORK WITH YOUR JSON CLASS HERE
//**************************************
//Make sure to call stopSelf() or your service will run in the background, chewing up
//battery life like rocky mountain oysters!
this.stopSelf();
}
#Override
public void onDestroy(){
super.onDestroy();
}
}