Cancel AsyncTask when internet connection is lost in the process of running - android

I am developing a news app which performs Async task, but during the running of the Async task if the internet connection is lost the app crashes. I tried solving the issue by Using a broadcast receiver and cancel the async task when connection is lost but the problem still persist. Below is my full activity source code.
public class News extends AppCompatActivity{
// Declare Variables
JSONObject jsonobject;
JSONArray jsonarray;
GridView gridview;
GridViewAdapter adapter;
ProgressDialog mProgressDialog;
ArrayList<HashMap<String, String>> arraylist;
Toolbar mToolbar;
static String NEWS = "news";
static String ID = "id";
static String PROFILE_PIC = "news_pic";
DownloadNews downloader;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.news);
IntentFilter filter = new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION);
registerReceiver(networkStateReceiver, filter);
mToolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(mToolbar);
getSupportActionBar().setDisplayShowHomeEnabled(true);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
gridview = (GridView) findViewById(R.id.discoverGrid);
downloader = new DownloadNews();
ConnectionDetector cd = new ConnectionDetector(getApplicationContext());
if (!cd.isConnectingToInternet()) {
Toast.makeText(getApplicationContext(),"Couldn't refresh",Toast.LENGTH_SHORT).show();
}
else
{
downloader.execute();
Handler handler = new Handler();
handler.postDelayed(new Runnable()
{
#Override
public void run() {
if ( downloader.getStatus() == AsyncTask.Status.RUNNING ){
downloader.cancel(true);
linlaHeaderProgress.setVisibility(View.GONE);
Toast.makeText(getApplicationContext(),"Internet Connection is Down",Toast.LENGTH_SHORT).show();
}
else if(downloader.getStatus() == AsyncTask.Status.FINISHED){
linlaHeaderProgress.setVisibility(View.GONE);
}
}
}, 15000 );
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.news, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
int id = item.getItemId();
if (id == R.id.action_search) {
return true;
}
else if (id == android.R.id.home) {
onBackPressed();
finish();
return true;
}
return super.onOptionsItemSelected(item);
}
private class DownloadNews extends AsyncTask<Void, Void, Void> {
#Override
protected void onPreExecute() {
super.onPreExecute();
mProgressDialog.show();
}
#Override
protected Void doInBackground(Void... params) {
while(true){
if (isCancelled())
break;
}
arraylist = new ArrayList<HashMap<String, String>>();
// Retrieve JSON Objects from the given URL address
try {
try {
jsonobject = JSONfunctions
.getJSONfromURL("http://www.example.com/app/news.php");
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} catch (ConnectTimeoutException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (SocketTimeoutException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
try {
// Locate the array name in JSON
jsonarray = jsonobject.getJSONArray("news");
for (int i = 0; i < jsonarray.length(); i++) {
HashMap<String, String> map = new HashMap<String, String>();
jsonobject = jsonarray.getJSONObject(i);
// Retrieve JSON Objects
map.put("id", jsonobject.getString("id"));
map.put("profile_pic", jsonobject.getString("news_pic"));
// Set the JSON Objects into the array
arraylist.add(map);
}
} catch (JSONException e) {
Log.e("Error", e.getMessage());
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(Void args) {
adapter = new GridViewAdapter(News.this, arraylist);
gridview.setAdapter(adapter);
mProgressDialog.dismiss();
}
#Override
protected void onCancelled(){
downloader.cancel(true);
}
}
#Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
finish();
return true;
}
return super.onKeyDown(keyCode, event);
}
BroadcastReceiver networkStateReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
boolean noConnectivity = intent.getBooleanExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, false);
if(!noConnectivity) {
onConnectionFound();
} else {
onConnectionLost();
}
}
};
public void onConnectionLost() {
Toast.makeText(this, "Connection lost", Toast.LENGTH_LONG).show();
downloader.cancel(true);
}
public void onConnectionFound() {
Toast.makeText(this, "Connection found", Toast.LENGTH_LONG).show();
}
#Override
protected void onDestroy() {
super.onDestroy();
unregisterReceiver(networkStateReceiver);
}
}

Your code is broken. Your while(true) loop is miswritten, its looping until you're canceled then trying to do a network request. That's probably not what you want. What you want to do is just remove that loop entirely (which may need further debugging after that). If you really want to continually download the data over and over, you want a Thread and not an AsyncTask, and the body of your function should all be inside that while loop.

Related

Android AlertDialog freezes when saving data in database

In my App my I am using AlertDialog in Async. But it freezes at a point when data is saving in database. what can I do to keep it running? It runs perfectly for sometime but stops after certain time when database is accessed.
Here's my code:
class BackGroundTasks extends AsyncTask<String, String, Void> {
#Override
protected void onPreExecute() {
// TODO Auto-generated method stub
super.onPreExecute();
if (dialog == null) {
dialog = ProgressDialog.show(mActivity, null,
"Please wait ...", true);
}
}
#Override
protected Void doInBackground(String... params) {
// TODO Auto-generated method stub
CheckInternetConnection internet = new CheckInternetConnection(
mActivity);
if (!internet.HaveNetworkConnection()) {
return null;
}
return null;
}
protected void onPostExecute(Void result) {
super.onPostExecute(result);
try {
CheckInternetConnection internet = new CheckInternetConnection(
getApplicationContext());
if (!internet.HaveNetworkConnection()) {
showToast("No Internet Connection.");
return;
} else {
setUpdatedBarcodes();
}
}
}
}
private boolean setUpdatedBarcodes(
ArrayList<Model_BarcodeDetail> changedBarcodeList2) {
try {
int i = 0;
BarcodeDatabase barcodeDatabase = new
BarcodeDatabase(mActivity);
barcodeDatabase.open();
for (Model_BarcodeDetail model : changedBarcodeList2) {
barcodeDatabase.updateEntry(model, userId);
}
barcodeDatabase.close();
if (RefList1.equals(RefList)) {
if (dialog != null) {
dialog.dismiss(); // cancelling Async dialog here after
data is saved in DB
}
showToast("Barcodes updated successfully");
}
} catch (Exception e) {
Log.i("Exception caught in: ", "setDownloadedBarcodes method");
e.printStackTrace();
return false;
}
return true;
}
DB operations should be done in the background thread. Put it in doInBackground() method too.
I modify your code. may it helps..
class BackGroundTasks extends AsyncTask<String, String, Void> {
#Override
protected void onPreExecute() {
// TODO Auto-generated method stub
super.onPreExecute();
if (dialog == null) {
dialog = ProgressDialog.show(mActivity, null,
"Please wait ...", true);
}
}
#Override
protected Void doInBackground(String... params) {
// TODO Auto-generated method stub
CheckInternetConnection internet = new CheckInternetConnection(
mActivity);
if (!internet.HaveNetworkConnection()) {
showToast("No Internet Connection.");
} else {
setUpdatedBarcodes();
}
return null;
}
protected void onPostExecute(Void result) {
super.onPostExecute(result);
if (dialog != null) {
dialog.dismiss(); // cancelling Async dialog here
}
}
}
private boolean setUpdatedBarcodes(
ArrayList<Model_BarcodeDetail> changedBarcodeList2) {
try {
int i = 0;
BarcodeDatabase barcodeDatabase = new
BarcodeDatabase(mActivity);
barcodeDatabase.open();
for (Model_BarcodeDetail model : changedBarcodeList2) {
barcodeDatabase.updateEntry(model, userId);
}
barcodeDatabase.close();
if (RefList1.equals(RefList)) {
showToast("Barcodes updated successfully");
}
} catch (Exception e) {
Log.i("Exception caught in: ", "setDownloadedBarcodes method");
e.printStackTrace();
return false;
}
return true;
}
when saving data in database don't do it on main thread do it on background thread. try code
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
// do your work
}
},0);
or
new Thread(new Runnable() {
public void run() {
// do your work here
}
}).start();

Android - Error receiving broadcast Intent?

I have a service that pass String of Json to MainActivity:
GetSubjects.class :
public class GetSubjects extends Service {
String URL = "http://webservice.jim.com/YYY/XXXX.asmx";
String Webresponse = "IS NULL ?";
int scode = 1597536485;
String result;
public final static String MY_ACTION = "MY_ACTION";
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public int onStartCommand(final Intent intent, int flags, final int startId) {
Runnable r = new Runnable() {
#Override
public void run() {
handleStart(intent, startId);
}
};
Thread t = new Thread(r);
t.start();
return START_NOT_STICKY;
}
#Override
public void onDestroy() {
super.onDestroy();
}
void handleStart(Intent intent, int startId) {
try {
Params_GetSubjects param = new Params_GetSubjects(scode);
result = new mGetSubjects().execute(param).get();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
public class mGetSubjects extends AsyncTask<Params_GetSubjects, String, String> {
String NAMESPACE = "http://tempuri.org/";
String METHOD_NAME = "Get";
String SOAP_ACTION = "http://tempuri.org/Get";
#Override
protected String doInBackground(Params_GetSubjects... params) {
SoapObject request = new SoapObject(NAMESPACE, METHOD_NAME);
request.addProperty("scode", params[0].Scode);
SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);
envelope.dotNet = true;
envelope.setOutputSoapObject(request);
HttpTransportSE conn = new HttpTransportSE(URL);
Object object;
try {
conn.call(SOAP_ACTION, envelope);
//SoapPrimitive response = (SoapPrimitive) envelope.getResponse();
object = envelope.getResponse();
Webresponse = object.toString();
} catch (Exception e) {
e.printStackTrace();
return "NULL";
}finally {
ThreadFinish threadfinish = new ThreadFinish();
threadfinish.start();
return Webresponse;
}
}
}
public class ThreadFinish extends Thread{
#Override
public void run() {
try {
Intent intent = new Intent();
intent.setAction(MY_ACTION);
intent.putExtra("DATAPASSED", result);
sendBroadcast(intent);
}catch (Exception e){
e.printStackTrace();
}finally {
stopSelf();
}
}
}
}
Here is my MainActivity :
public class MainActivity extends AppCompatActivity {
MyReceiver myReceiver;
private RecyclerView.LayoutManager layoutManager;
private DrawerAdapter mDrawerAdapter;
private RecyclerView mRecyclerView;
List<DrawerItem> draweritemList;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
startService(new Intent(MainActivity.this, GetSubjects.class));
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
switch (id) {
case android.R.id.home:
mDrawerLayout.openDrawer(GravityCompat.START);
return true;
case R.id.action_settings:
return true;
}
return super.onOptionsItemSelected(item);
}
#Override
protected void onStart() {
myReceiver = new MyReceiver();
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(GetSubjects.MY_ACTION);
registerReceiver(myReceiver, intentFilter);
super.onStart();
}
#Override
protected void onStop() {
this.unregisterReceiver(myReceiver);
super.onStop();
}
private class MyReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context arg0, Intent arg1) {
String datapassed = arg1.getExtras().getString("DATAPASSED");
Log.i("ASDQWRRYGH",datapassed);
draweritemList = JsonParser.parseFeed(datapassed);
for (int i=0;i < draweritemList.size();i++)
{
Log.i("ASDQWRRYGH",draweritemList.get(i).getTitle());
}
}
}
}
And here is my JsonParer :
public class JsonParser {
public static List<DrawerItem> parseFeed(String content) {
try {
JSONObject jsonRootObject = new JSONObject(content);
JSONArray jsonArray = jsonRootObject.optJSONArray("Rows");
List<DrawerItem> draweritemList = new ArrayList<>();
for (int i = 0; i < jsonArray.length(); i++) {
JSONObject obj = jsonArray.getJSONObject(i);
DrawerItem draweritem = new DrawerItem();
draweritem.setId(obj.getString("Id"));
draweritem.setTitle(obj.getString("Title"));
draweritemList.add(draweritem);
}
return draweritemList;
} catch (JSONException e) {
e.printStackTrace();
return null;
}
}
}
often get me result from service but often get me bellow error ,what can i do?:
You've got three additional threads executing in your Service; the AsyncTask and two Threads. The first Thread is executing your AsyncTask, but it's blocking because you're calling get() on it to assign the return value to the return String. When the network transaction finishes in the AsyncTask, it starts another Thread to send the broadcast, and this happens before doInBackground() can return to set the value of the return String, which ends up getting broadcasted while it's still null.
The simplest fix is to move the broadcast to after the result = ... line, and get rid of the ThreadFinish class.
It might be preferable, though, to execute everything sequentially in a single thread; either in the AsyncTask, or the Thread executing your Runnable.

Splash screen doesn't display logo : thread.execute.get()

My splash screen syncronize my app :
When I use :
sd.execute("init_sync", null).get();
My logo (defined in xml) disappear. If I quit .get(), it appears.
Here is my code :
public class SplashScreen extends Activity {
private Context ctx = null;
private Usuario mUser = null;
SharedPreferences prefs;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.splash);
ctx = this;
prefs = PreferenceManager.getDefaultSharedPreferences(this);
new Handler().post(new Runnable() {
#Override
public void run() {
// Check if user exists
Gson gson = new Gson();
String jsonUser = prefs.getString("usuario", "");
mUser = gson.fromJson(jsonUser, Usuario.class);
if (NetworkUtils.isOnline(ctx)) {
if (mUser != null) {
SyncData sd = new SyncData(ctx);
try {
sd.execute("init_sync", null).get();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
} else {
Intent i = new Intent(SplashScreen.this, LoginActivity.class);
startActivity(i);
}
} else {
if (mUser != null) {
Intent i = new Intent(SplashScreen.this, DashBoard.class);
startActivity(i);
} else {
Toast.makeText(ctx, "Necesita Internet para loguearse", Toast.LENGTH_LONG).show();
finish();
}
}
}
});
}
}
I have several asyncTask that I use to upload pics, and sync MySQL database with my SQLite database. So, I need to wait till all the processes end to know if there is any error.
The thing is I put it in a thread, so that it would not affect UI. Where am I wrong?
When you use get() it causes the UI thread to wait. Don't use get(). You need to override the onPostExecute method in AsyncTask.
private Boolean task1Finished = false;
private Boolean task2Finished = false;
private Boolean task3Finished = false;
//...
SyncData sd1 = new SyncData(ctx) {
#Override
protected void onPostExecute(Object result) {
task1Finished = true;
goToNextActivity();
}
};
SyncData sd2 = new SyncData(ctx) {
#Override
protected void onPostExecute(Object result) {
task2Finished = true;
goToNextActivity();
}
};
SyncData sd3 = new SyncData(ctx) {
#Override
protected void onPostExecute(Object result) {
task3Finished = true;
goToNextActivity();
}
};
try {
sd1.execute();
sd2.execute();
sd3.execute();
}
catch (InterruptedException e) {
e.printStackTrace();
}
catch (ExecutionException e) {
e.printStackTrace();
}
//...
private void goToNextActivity() {
if (task1Finished && task2Finished && task3Finished)
// all tasks complete
}
Like #ashishduh says, I was in UI Thread. So I changed:
new Handler().post(new Runnable() {
#Override
public void run() {
....
}
}
by
Runnable sync = new Runnable() {
#Override
public void run() {
....
}
};
Thread t = new Thread(sync);
t.start();
And it solved my problem!

Button needs to be clicked twice for Async Task to complete loading

Below is the code for my LoginActivity wherein I'm basically getting a JSON and an Image from a URl
in an AsyncTask. The strange thing is that the else part of my onClick() always executes(i.e The toast shows).Only if I click the button again does it jump to the next activity.
public class LoginActivity extends Activity
{
Button getBunks;
CheckBox detailscheck;
EditText regText, bdayText;
String storedReg, storedBDay;
public static final String PREFS_NAME = "MyPrefsFile";
String predataURL;
String prephotoURL;
public static URL dataUrl;
public static String dataUri = "http://ankit.im/websisAPI/parser.php";
ProgressDialog progressDialog;
JSONObject temp = null;
Bitmap tmpPhoto;
boolean doneFlag = false;
#Override
protected void onCreate(Bundle savedInstanceState)
{
this.requestWindowFeature(Window.FEATURE_NO_TITLE);
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
getBunks = (Button) findViewById(R.id.getBunkButton);
detailscheck = (CheckBox) findViewById(R.id.rememberOpts);
regText = (EditText) findViewById(R.id.regNo);
bdayText = (EditText) findViewById(R.id.bday);
detailscheck.setChecked(true); // To avoid Nag
try
{
dataUrl = new URL("http://ankit.im/websisAPI/parser.php");
} catch (MalformedURLException e)
{
e.printStackTrace();
}
// Check if login details are already stored
SharedPreferences prefs = this.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE);
storedReg = prefs.getString("regno", null);
storedBDay = prefs.getString("bday", null);
// The Following Listeners Check if the user has entered
// appropriate Data in the Fields
// Check is on enter key press and on Focus Change
SharedPreferences settings = getSharedPreferences(PREFS_NAME, 0);
final SharedPreferences.Editor editor = settings.edit();
regText.setOnFocusChangeListener(new OnFocusChangeListener()
{
#Override
public void onFocusChange(View v, boolean hasFocus)
{
if (detailscheck.isChecked())
{
if (!hasFocus)
{
if (regText.getText().toString() != "" || regText.getText() != null)
{
editor.putString("regno", regText.getText().toString());
editor.commit();
// Toast.makeText(getApplicationContext(),
// "Reg No Stored", Toast.LENGTH_SHORT).show();
}
}
}
}
});
bdayText.setOnEditorActionListener(new OnEditorActionListener()
{
#Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event)
{
if (actionId == EditorInfo.IME_ACTION_SEARCH || actionId == EditorInfo.IME_ACTION_DONE || event.getAction() == KeyEvent.ACTION_DOWN
&& event.getKeyCode() == KeyEvent.KEYCODE_ENTER)
{
editor.putString("bday", bdayText.getText().toString());
editor.commit();
// Hide Virtual Keyboard
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(regText.getWindowToken(), 0);
return true;
}
return false;
}
});
bdayText.setOnFocusChangeListener(new OnFocusChangeListener()
{
#Override
public void onFocusChange(View v, boolean hasFocus)
{
if (detailscheck.isChecked())
{
if (!hasFocus)
{
if (bdayText.getText().toString() != "" || bdayText.getText().toString() != null)
{
editor.putString("bday", bdayText.getText().toString());
editor.commit();
// Toast.makeText(getApplicationContext(),
// "BDay Stored", Toast.LENGTH_SHORT).show();
}
}
}
}
});
// Handle the button click
getBunks.setOnClickListener(new OnClickListener()
{
#Override
public void onClick(View v)
{
new DownloadStudentData().execute();
if (doneFlag == true)
{
// GlobalVars.showAttendanceData();
Intent actChange = new Intent(v.getContext(), DetailsTabViewActivity.class);
startActivity(actChange);
finish();
} else if (doneFlag == false)
{
Toast.makeText(getApplicationContext(), "Error in Downloading, Please Check Details or Try Again", Toast.LENGTH_LONG).show();
}
}
});
}
#Override
public boolean onCreateOptionsMenu(Menu menu)
{
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
#Override
protected void onStart()
{
super.onStart();
if (storedReg != null && storedBDay != null)
{
regText.setText(storedReg);
bdayText.setText(storedBDay);
}
}
private class DownloadStudentData extends AsyncTask<Void, Void, Void>
{
// ProgressDialog progressDialog;
final JSONParser jsp = new JSONParser();
#Override
protected void onPreExecute()
{
// super.onPreExecute();
progressDialog = new ProgressDialog(LoginActivity.this);
progressDialog.setCancelable(true);
progressDialog.setTitle(" Downloading Data ");
progressDialog.setMessage("Please Wait, Loading...");
progressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
// progressDialog.setProgress(0);
progressDialog.show();
}
#Override
protected Void doInBackground(Void... voids)
{
temp = new JSONObject();
temp = jsp.getJSONFromUrl(dataUri); // get the data
prephotoURL ="http://218.248.47.9/websis/control/img/P12703.JPGimgId=P12703";
try
{
InputStream in = new java.net.URL(prephotoURL).openStream();
tmpPhoto = BitmapFactory.decodeStream(in);
} catch (Exception e)
{
Log.e("Error", e.getMessage());
e.printStackTrace();
}
return null;
}
protected void onPostExecute(Void v)
{
GlobalVars.setJSON(temp);
GlobalVars.setPhotoURL(prephotoURL);
GlobalVars.setBitmap(tmpPhoto);
doneFlag = true;
try
{
GlobalVars.setPhotoURL(temp.getString("photolink"));
} catch (JSONException e)
{
e.printStackTrace();
}
progressDialog.dismiss();
}
}
#Override
protected void onPause()
{
super.onPause();
if (progressDialog != null)
progressDialog.dismiss();
}
}
GlobalVars is just a global class containing public static variables and methods.
Also I'm not sure if that is the correct method to download an Image from a URL in the background,any better alternatives would be appreciated(URLImageViewHelper is not suitable for my needs).
The AsyncTask runs on a different Thread and will not complete in time to change the value of doneFlag. (This is why it is asynchronous.)
new DownloadStudentData().execute(); // Takes time to complete
if (doneFlag == true) { ... } // Happens milliseconds later, AsyncTask still running
else if (doneFlag == false) { ... }
You need to run any "completion" code in onPostExecute().
A couple quick tips:
if (doneFlag) is shorthand for if (doneFlag == true).
A boolean can only have two states, you don't need to use else if(), simply use else {...}

When running my Android App in the Eclipse Debugger, I have a service that notifies. Outside of the debugger it does not send a notification

I'm making an app that sends a notification to the status bar, it sends the notification when stepping through the code in the debugger, however it never sends the notification when run in realtime.
Here is my runnable that generates the notification, again when stepping through this code in the debugger the notification runs however in realtime nothing happens.
public class NewsEvents_Service extends Service {
private static final String NEWSEVENTS = "newsevents";
private static final String KEYWORDS = "keywords";
private NotificationManager mNM;
private ArrayList<NewsEvent> neList;
private int count;
#Override
public void onCreate() {
mNM = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
neList = new ArrayList<NewsEvent>();
getKeywords();
//getNewsEvents();
Thread thr = new Thread(null, mTask, "NewsEvents_Service");
thr.start();
Log.d("Thread", "IT STARTED!!!!!!????!!!!!!!!!!!!!!!?!!?");
}
#Override
public void onDestroy() {
// Cancel the notification -- we use the same ID that we had used to start it
mNM.cancel(R.string.ECS);
// Tell the user we stopped.
Toast.makeText(this, "Service Done", Toast.LENGTH_SHORT).show();
}
/**
* The function that runs in our worker thread
*/
Runnable mTask = new Runnable() {
public void run() {
getNewsEventsFromWeb();
for(NewsEvent ne : neList){
Log.d("Thread Running", "Service Code running!!!!!!!!!!!!!!!");
String body = ne.getBody().replaceAll("\\<.*?>", "");
String title = ne.getTitle();
for(String s : keyWordList){
if(body.contains(s) || body.contains(s.toLowerCase()) ||
title.contains(s) || title.contains(s.toLowerCase())){
ne.setInterested(true);
}
}
if(ne.isInterested() == true ){
Notification note = new Notification(R.drawable.icon,
"New ECS News Event", System.currentTimeMillis());
Intent i = new Intent(NewsEvents_Service.this, FullNewsEvent.class);
i.putExtra("ne", ne);
PendingIntent pi = PendingIntent.getActivity(NewsEvents_Service.this, 0,
i, 0);
note.setLatestEventInfo(NewsEvents_Service.this, "New Event", ne.getTitle(), pi);
note.flags = Notification.FLAG_AUTO_CANCEL;
mNM.notify(R.string.ECS, note);
}
}
}
};
#Override
public IBinder onBind(Intent intent) {
return mBinder;
}
/**
* Show a notification while this service is running.
*/
private void getNewsEventsFromWeb() {
HttpClient client = new DefaultHttpClient();
HttpGet get;
try {
get = new HttpGet(getString(R.string.jsonnewsevents));
ResponseHandler<String> response = new BasicResponseHandler();
String responseBody = client.execute(get, response);
String page = responseBody;
Bundle data = new Bundle();
data.putString("page",page);
Message msg = new Message();
msg.setData(data);
handler.sendMessage(msg);
}
catch (Throwable t) {
Log.d("UpdateNews", "PROBLEMS");
}
}
private Handler handler = new Handler(){
#Override
public void handleMessage(Message msg) {
String page = msg.getData().getString("page");
try {
JSONArray parseArray = new JSONArray(page);
for (int i = 0; i < parseArray.length(); i++) {
JSONObject jo = parseArray.getJSONObject(i);
String title = jo.getString("title");
String body =jo.getString("body");
String pd = jo.getString("postDate");
String id = jo.getString("id");
NewsEvent ne = new NewsEvent(title, pd , body, id);
boolean unique = true;
for(NewsEvent ne0 : neList){
if(ne.getId().equals(ne0.getId())){
unique = false;
}else{
unique = true;
}
}
if(unique == true){
neList.add(ne);
}
}
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
};
private ArrayList<String> keyWordList;
public void getNewsEvents(){
try {
InputStream fi = openFileInput(NEWSEVENTS);
if (fi!=null) {
ObjectInputStream in = new ObjectInputStream(fi);
neList = (ArrayList<NewsEvent>) in.readObject();
in.close();
}
}
catch (java.io.FileNotFoundException e) {
// that's OK, we probably haven't created it yet
}
catch (Throwable t) {
Toast
.makeText(this, "Exception: "+t.toString(), Toast.LENGTH_LONG)
.show();
}
if(neList == null){
neList = new ArrayList<NewsEvent>();
}
}
public ArrayList<String> getKeywords(){
try {
InputStream fi = openFileInput(KEYWORDS);
if (fi!=null) {
ObjectInputStream in = new ObjectInputStream(fi);
keyWordList = (ArrayList<String>) in.readObject();
in.close();
}
}
catch (java.io.FileNotFoundException e) {
// that's OK, we probably haven't created it yet
}
catch (Throwable t) {
Toast
.makeText(this, "Exception: "+t.toString(), Toast.LENGTH_LONG)
.show();
}
if(keyWordList == null){
keyWordList = new ArrayList<String>();
return keyWordList;
}
return keyWordList;
}
/**
* This is the object that receives interactions from clients. See RemoteService
* for a more complete example.
*/
private final IBinder mBinder = new Binder() {
#Override
protected boolean onTransact(int code, Parcel data, Parcel reply,
int flags) throws RemoteException {
return super.onTransact(code, data, reply, flags);
}
};
}
Here is my activity that schedules the service to run
public class NewsEvents extends ListActivity{
private URL JSONNewsEvents;
private ArrayList<NewsEvent> neList;
private ArrayList<String> keyWordList;
private Worker worker;
private NewsEvents ne;
public static final String KEYWORDS = "keywords";
private static final String NEWSEVENTS = "newsevents";
public static final int ONE_ID = Menu.FIRST+1;
private PendingIntent newsAlarm;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.newsevents);
ne = this;
neList = new ArrayList<NewsEvent>();
try {
JSONNewsEvents = new URL(getString(R.string.jsonnewsevents));
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
worker = new Worker(handler, this);
setListAdapter(new IconicAdapter());
getKeywords();
worker.execute(JSONNewsEvents);
}
#Override
protected void onStop() {
super.onStop();
writeNewsEvents() ;
}
#Override
protected void onPause(){
super.onPause();
writeNewsEvents();
}
private void writeNewsEvents() {
try {
OutputStream fi = openFileOutput(NEWSEVENTS, 0);
if (fi!=null) {
ObjectOutputStream out = new ObjectOutputStream(fi);
out.writeObject(neList);
out.close();
}
}
catch (java.io.FileNotFoundException e) {
// that's OK, we probably haven't created it yet
}
catch (Throwable t) {
Toast
.makeText(this, "Exception: "+t.toString(), Toast.LENGTH_LONG)
.show();
}
}
/**
* #return
*/
public ArrayList<String> getKeywords(){
try {
InputStream fi = openFileInput(KEYWORDS);
if (fi!=null) {
ObjectInputStream in = new ObjectInputStream(fi);
keyWordList = (ArrayList<String>) in.readObject();
in.close();
}
}
catch (java.io.FileNotFoundException e) {
// that's OK, we probably haven't created it yet
}
catch (Throwable t) {
Toast
.makeText(this, "Exception: "+t.toString(), Toast.LENGTH_LONG)
.show();
}
if(keyWordList == null){
keyWordList = new ArrayList<String>();
return keyWordList;
}
return keyWordList;
}
public void onListItemClick(ListView parent, View v,
int position, long id) {
startFullNewsEvent(neList.get(position));
}
/**
* #param newsEvent
*/
public void startFullNewsEvent(NewsEvent ne) {
Intent intent = new Intent(this, FullNewsEvent.class);
intent.putExtra("ne", ne);
this.startActivity(intent);
finish();
}
private Handler handler = new Handler(){
#Override
public void handleMessage(Message msg) {
String page = msg.getData().getString("page");
try {
JSONArray parseArray = new JSONArray(page);
for (int i = 0; i < parseArray.length(); i++) {
JSONObject jo = parseArray.getJSONObject(i);
String title = jo.getString("title");
String body =jo.getString("body");
String pd = jo.getString("postDate");
String id = jo.getString("id");
NewsEvent ne = new NewsEvent(title, pd , body, id);
boolean unique = true;
for(NewsEvent ne0 : neList){
if(ne.getId().equals(ne0.getId())){
unique = false;
}else{
unique = true;
}
}
if(unique == true){
neList.add(ne);
}
}
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
ne.setListAdapter(new IconicAdapter());
}
};
public class IconicAdapter extends ArrayAdapter<NewsEvent> {
IconicAdapter() {
super(NewsEvents.this, R.layout.rownews, neList);
}
public View getView(int position, View convertView,ViewGroup parent) {
LayoutInflater inflater=getLayoutInflater();
View row=inflater.inflate(R.layout.rownews, parent, false);
TextView label=(TextView)row.findViewById(R.id.label);
ImageView image= (ImageView)row.findViewById(R.id.icon);
String body = neList.get(position).getBody();
body.replaceAll("\\<.*?>", "");
String title = neList.get(position).getTitle();
for(String s : keyWordList){
if(body.contains(s) || body.contains(s.toLowerCase()) ||
title.contains(s) || title.contains(s.toLowerCase())){
neList.get(position).setInterested(true);
}
}
if(neList.get(position).isInterested() == true){
image.setImageResource(R.drawable.star);
}
label.setText(neList.get(position).getTitle());
return(row);
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
populateMenu(menu);
return(super.onCreateOptionsMenu(menu));
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
return(applyMenuChoice(item) || super.onOptionsItemSelected(item));
}
//Creates our activity to menus
private void populateMenu(Menu menu) {
menu.add(Menu.NONE, ONE_ID, Menu.NONE, "Home");
}
private boolean applyMenuChoice(MenuItem item) {
switch (item.getItemId()) {
case ONE_ID: startHome(); return(true);
}
return(false);
}
public void startHome() {
Intent intent = new Intent(this, ECS.class);
this.startActivity(intent);
finish();
}
}
Race conditions, I'm making an HTTP Request and then handing it off to a handler, immediately following that I iterator through the array list, which at full speed is empty because the HTTP hasn't completed. In debugging it all slows down so the HTTP is complete and all works well.
Threads and Network Connections, a deadly combination.

Categories

Resources