Call Interface function from main class from sub object - java

Solution:
The following worked fine, but I had two Activities already using my helper class, but forgot to add the Interface to one Activity.
So I got the TypeCastException.
But I did not realize I always looked at the wrong Activity, so I could not find the issue.
I currently write my first android service, which works fine.
Now I realized, that I have to bind unbind, check binding all over and so I thought to put all into a subclass and only do an interface with callbacks for the only functions I need.
But now i am stuck to call my interface functions
onTcBlueServiceConnected()
onTcBlueServiceDisconnected()
I simply want to prevent to write the same code over and over again.
Each activity I have to use the service, I extend from this helper class, instead of the AppCompatActivity.
Maybe I chose the wrong path, but lost with the right words for a search.
As far as I understand bound services, I have to bind from each activity I access the service, and unbind of course when it is destroyed.
So I thought this is a good approach
public abstract class TcBlueServiceHelper extends AppCompatActivity {
private static String LOG_TAG = "TcBlueServiceHelper";
TcBlueService mTcBlueService;
TcBlueService.TcBlueBinder myBinder;
boolean mServiceBound = false;
Context mCallingContext;
public TcBlueServiceHelper(Context callingContext) {
mCallingContext = callingContext;
}
public TcBlueServiceHelper(){
mCallingContext = this;
}
public void bindServiceSave(){
if (mServiceBound == false) {
Intent intent = new Intent(this, TcBlueService.class);
startService(intent);
bindService(intent, mServiceConnection, Context.BIND_AUTO_CREATE);
}
}
public void unbindServiceSave(){
if (mServiceBound) {
unbindService(mServiceConnection);
mServiceBound = false;
}
}
public TcBlueService.TcBlueBinder getBinder(){
return myBinder;
}
private ServiceConnection mServiceConnection = new ServiceConnection() {
#Override
public void onServiceDisconnected(ComponentName name) {
mServiceBound = false;
((ITcBlueServiceHelper)mCallingContext).onTCBServiceDisconnected(name);
}
#Override
public void onServiceConnected(ComponentName name, IBinder service) {
myBinder = (TcBlueService.TcBlueBinder) service;
mTcBlueService = myBinder.getService();
mServiceBound = true;
((ITcBlueServiceHelper)mCallingContext).onTCBServiceConnected(name, service);
}
};
public interface ITcBlueServiceHelper{
public void onTCBServiceConnected(ComponentName name, IBinder service);
public void onTCBServiceDisconnected(ComponentName name);
}
}
My first thought to cast result in a "ClassCastException"
E/AndroidRuntime: FATAL EXCEPTION: main
java.lang.ClassCastException: de.mobacomp.android.freightweight.StartActivity cannot be cast to de.mobacomp.android.freightweight.TcBlueServiceHelper$ITcBlueServiceHelper
at de.mobacomp.android.freightweight.TcBlueServiceHelper$1.onServiceConnected(TcBlueServiceHelper.java:72)
at android.app.LoadedApk$ServiceDispatcher.doConnected(LoadedApk.java:1068)
at android.app.LoadedApk$ServiceDispatcher$RunConnection.run(LoadedApk.java:1085)
at android.os.Handler.handleCallback(Handler.java:605)
at android.os.Handler.dispatchMessage(Handler.java:92)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:4424)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551)
at dalvik.system.NativeStart.main(Native Method)

Related

How can I implement in fragment with my interface in another fragment

I created a interface in a fragment like following:
public interface SGFCallBackInterface {
void itemSelected(Item item);
}
private SGFCallBackInterface mCallbackInterface;
#Override
public void onAttach(Context context) {
super.onAttach(context);
if (context instanceof SGFCallBackInterface) {
mCallbackInterface = (SGFCallBackInterface) context;
} else {
throw new RuntimeException(context.toString() + " must implement SelectGdsFragment.SGFCallBackInterface");
}
}
public void setSGFCallBackInterface(SGFCallBackInterface mCallbackInterface) {
this.mCallbackInterface = mCallbackInterface;
}
and I would implement that in another fragment like the following
public class SaleMenageFragment extends Fragment implements SelectGdsFragment.SGFCallBackInterface {
...
SelectGdsFragment selectGdsFragment = new SelectGdsFragment();
selectGdsFragment.setSGFCallBackInterface(SaleMenageFragment.this);
...
}
#Override
public void onItemSelected(Item item) {
...
}
But it's still not working, this is the error log:
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.leo.test, PID: 3853
java.lang.RuntimeException: com.leo.test.Control.IndexActivity#2a66aece must implement SelectGdsFragment.SGFCallBackInterface
at com.leo.test.Control.Fragment.SaleManagement.SelectGdsClsFragment.onAttach(SelectGdsFragment.java:42)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1019)
at android.support.v4.app.BackStackRecord.setLastIn(BackStackRecord.java:779)
at android.support.v4.app.BackStackRecord.calculateFragments(BackStackRecord.java:819)
at android.support.v4.app.BackStackRecord.run(BackStackRecord.java:660)
at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1617)
at android.support.v4.app.FragmentManagerImpl$1.run(FragmentManager.java:517)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5254)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)
I think the error log means my IndexActivity is not implementing SelectGdsFragment.SGFCallBackInterface.
But I don't want to implement that in IndexActivity.
I want to implement that in SaleMenageFragment.
How can I do that?
I am afraid you have to implement it in your Activity
See the doc
Communicating with Fragments
Hope it helps!
Just remove the part in onAttach(Context context) method like this:
public interface SGFCallBackInterface {
void itemSelected(Item item);
}
private SGFCallBackInterface mCallbackInterface;
#Override
public void onAttach(Context context) {
super.onAttach(context);
if (context instanceof SGFCallBackInterface) {
mCallbackInterface = (SGFCallBackInterface) context;
} // this wont throw an exception if the activity does not implement that interface
}
public void setSGFCallBackInterface(SGFCallBackInterface mCallbackInterface) {
this.mCallbackInterface = mCallbackInterface;
}

FragmentTransaction in WebViewClient.shouldOverrideUrlLoading throws IllegalStateException

I seem to be fighting with a race condition, the cause of which I can't seem to pin down. When executing the below code, I intermittently get the stack trace below.
Is there some obvious rule of the Fragment lifecycle I am disobeying? I am not clear on what would explicitly forbid me from performing a transaction here to handle the event.
I am using a WebViewClient to detect external URLs clicked within a local .html document - as in, URLs which point to a non-local host. I am using Otto's EventBus to post those actions to an Activity. When the Activity receives those events, I want to show those external URLs in a different Fragment, by calling FragmentTransaction.replace()
DefaultWebViewClient.java
#Override
public boolean shouldOverrideUrlLoading(final WebView view, final String url) {
boolean shouldOverride;
if (urlIsLocal(url)) {
shouldOverride = super.shouldOverrideUrlLoading(view, url);
} else {
// trigger an event for the fragment to swap out
// return true to tell the webview not to load it...
EventBus.getInstance().post(new LoadExternalUrlEvent(url));
shouldOverride = true;
}
return shouldOverride;
}
FragmentActivity.java
#Subscribe
public void onLoadExternalUrlEvent(LoadExternalUrlEvent externalLoadEvent) {
final BrowserFragment browserFragment = new BrowserFragment();
Bundle args = new Bundle();
args.putSerializable(BrowserFragment.ARG_LOAD_EXTERNAL_URL_EVENT, externalLoadEvent);
browserFragment.setArguments(args);
getSupportFragmentManager().beginTransaction()
.replace(R.id.fragment_container, browserFragment, BrowserFragment.FRAGMENT_TAG)
.addToBackStack(null).commit();
}
LoadExternalUrlEvent.java
public class LoadExternalUrlEvent implements Serializable {
private static final long serialVersionUID = 1L;
public final String url;
public LoadExternalUrlEvent(String url) {
this.url = url;
}
#Override
public String toString() {
return "LoadExternalUrlEvent [url=" + url + "]";
}
}
EventBus.java
import com.squareup.otto.Bus;
public class EventBus {
private static Bus _INSTANCE;
public static synchronized Bus getInstance() {
if (null == _INSTANCE) {
_INSTANCE = new Bus();
}
return _INSTANCE;
}
}
Stack trace
java.lang.RuntimeException: Could not dispatch event: class <omitted>.LoadExternalUrlEvent to handler [EventHandler public void <omitted>Activity.onLoadExternalUrlEvent(<omitted>LoadExternalUrlEvent)]: Can not perform this action after onSaveInstanceState
at com.squareup.otto.Bus.throwRuntimeException(Bus.java:456)
at com.squareup.otto.Bus.dispatch(Bus.java:386)
at com.squareup.otto.Bus.dispatchQueuedEvents(Bus.java:367)
at com.squareup.otto.Bus.post(Bus.java:336)
at <omitted>DefaultWebViewClient.shouldOverrideUrlLoading(DefaultWebViewClient.java:51)
at com.android.webview.chromium.WebViewContentsClientAdapter.shouldOverrideUrlLoading(WebViewContentsClientAdapter.java:293)
at com.android.org.chromium.android_webview.AwContentsClientBridge.shouldOverrideUrlLoading(AwContentsClientBridge.java:96)
at com.android.org.chromium.base.SystemMessageHandler.nativeDoRunLoopOnce(Native Method)
at com.android.org.chromium.base.SystemMessageHandler.handleMessage(SystemMessageHandler.java:27)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:157)
at android.app.ActivityThread.main(ActivityThread.java:5356)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1265)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1081)
at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState
at android.support.v4.app.FragmentManagerImpl.checkStateLoss(FragmentManager.java:1360)
at android.support.v4.app.FragmentManagerImpl.enqueueAction(FragmentManager.java:1378)
at android.support.v4.app.BackStackRecord.commitInternal(BackStackRecord.java:595)
at android.support.v4.app.BackStackRecord.commit(BackStackRecord.java:574)
at <omitted>Activity.run(<omitted>Activity.java:162)
at <omitted>Activity.onLoadExternalUrlEvent(<omitted>Activity.java:156)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.squareup.otto.EventHandler.handleEvent(EventHandler.java:89)
at com.squareup.otto.Bus.dispatch(Bus.java:384)
... 15 more
A/libc(2689): Fatal signal 6 (SIGABRT) at 0x00000a81 (code=-6), thread 2689
I discovered the problem.
Because I was calling EventBus.register() in Activity.onCreate() I was getting multiple instances of the Activity on my backstack which would act as responders to these events.
The solution is to either register your Activity as late as possible with
#Override
protected void onResume() {
super.onResume();
EventBus.getInstance().register(this);
}
#Override
protected void onPause() {
EventBus.getInstance().unregister(this);
super.onPause();
}
or to declare your Activity as a single instance with
android:launchMode="singleTask"

Android spinner throws a Null pointer exception

So I have a service that contains a Timer. The service is meant to run even when the app in the background and is supposed to pull the user to the app when the timer executes the method(from another activity). The service is triggered on and off by a toggle button. Currently my R.id reference to my spinner keeps throwing a NullPointerException that i don't know how to fix. Can someone please help me out?
The Method the Timer is running:
public String TemperatureCatch()
{
/*this line throws the error */ Spinner reeferchoice = (Spinner)findViewById(R.id.optionselecti);
String reeferChoicei = reeferchoice.getSelectedItem().toString();
if (reeferChoicei.equals("Yes")) {
final ToneGenerator tg = new ToneGenerator(AudioManager.STREAM_NOTIFICATION, 500);
tg.startTone(ToneGenerator.TONE_CDMA_ABBR_ALERT);
AlertDialog.Builder alert = new AlertDialog.Builder(this);
alert.setTitle("Temperature");
alert.setMessage("Input Temperature in F° (-20 to 65) ");
final EditText input = new EditText(this);
input.setInputType(InputType.TYPE_CLASS_PHONE);
alert.setView(input);
alert.setPositiveButton("Check-In", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
temperaturei = input.getText().toString();
Toast.makeText(getBaseContext(), "Updated", Toast.LENGTH_SHORT).show();
Updater(temperaturei);
}
});
alert.show();
} else if (reeferChoicei.equals("No")) {
temperaturei = "DRY";
Updater(temperaturei);
}
return temperaturei;
}
My service code:
import android.app.IntentService;
import android.app.Service;
import android.content.Intent;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import java.util.Timer;
import java.util.TimerTask;
public class MyService extends Service {
Locator locator;
Timer myTimer;
#Override
public void onCreate() {
locator = new Locator();
myTimer = new Timer();
}
private class MyTimerTask extends TimerTask
{
#Override
public void run() {
Handler handler = new Handler(Looper.getMainLooper());
handler.postDelayed(new Runnable() {
#Override
public void run() {
locator.TemperatureCatch();
}
}, 1000);
}
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
MyTimerTask myTimerTask = new MyTimerTask();
myTimer.scheduleAtFixedRate(myTimerTask, 0, 15000);
return START_STICKY;
}
#Override
public void onDestroy() {
super.onDestroy();
myTimer.cancel();
}
}
the button:
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked)
{
if (isChecked)
{
startService(new Intent(this, MyService.class));
Toast.makeText(this,"Check-In will be done every 15 seconds",Toast.LENGTH_SHORT).show();
}
else
{
stopService(new Intent(this, MyService.class));
Toast.makeText(this,"Manual Check-In enabled",Toast.LENGTH_SHORT).show();
}
}
the stack trace:
Process: com.example.adrian.trucktracker, PID: 9617
java.lang.NullPointerException
at android.app.Activity.findViewById(Activity.java:1952)
at com.example.adrian.trucktracker.Locator.TemperatureCatch(Locator.java:192)
at com.example.adrian.trucktracker.MyService$MyTimerTask$1.run(MyService.java:32)
at android.os.Handler.handleCallback(Handler.java:733)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:157)
at android.app.ActivityThread.main(ActivityThread.java:5872)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:852)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:668)
at dalvik.system.NativeStart.main(Native Method)
You should not create a instance of Activity class.
locator = new Locator(); // do not do this
This results in NullPointerException when you initialize views.
Can i Create the object of a activity in other class?
Also what you are doing seems to be a design issue.
As previous comments already pointed out, service wont have any UI, so you cannot make findViewById method call.
If you want your service to change the UI, bind to this service from your activity and using callbacks/delegates, you can notify the activity to change the UI from the service.
Activity objects are not supposed to be initialized by calling its constructor. By doing so, your overriden method onCreate() never get called, so the views are not initialized and findViewById will fail.
You should instead start the activity in the service instead of calling its contructor, something like this:
Intent t = new Intent (this, Locator.class);
t.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(t);
You can have a static getter in Locator class to get the instance of the Activity, so that you can use it in the Service.

Threads in Background Service Android

Hi I am trying to use the service class for first time and have been facing problems. What I want is an infinitely running (unless killed by Android System) service with an active Network connection. I have written the code which works fine on Android 4.3 and 4.4 but the application crashes when I try running on Android 2.2. My code is as follows:
public class BackgroundMusicService extends Service {
private MediaPlayer mp;
private int id;
private static class BackgroundAsyncTaskClass extends AsyncTask<Void, Void, Void>{
protected Void doInBackground(Void... params) {
Log.v("Async","Async Called");
/*Network connection will be created here*/
return null;
}
}
private class ForThread implements Runnable{
public void run() {
while (true) {
try {
Log.v("ThreadSleeping","5 sec");
BackgroundAsyncTaskClass task = new BackgroundAsyncTaskClass();
task.execute();
Thread.sleep(5000);
} catch (InterruptedException e) {
}finally{
Log.v("Finally called","Finally called");
}
}
}
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
super.onCreate();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.v("onStartCommand Called","onStart Command Called");
Thread t;
ForThread ft = new ForThread();
t = new Thread(ft);
t.start();
return START_NOT_STICKY;
}
#Override
public void onDestroy() {
super.onDestroy();
if(null != mp){
mp.stop();
mp.release();
Log.v("Destroyed","onDestroy Called");
}
}
public void onTaskRemoved(Intent rootIntent) {
Intent restartServiceIntent = new Intent(getApplicationContext(),
this.getClass());
restartServiceIntent.setPackage(getPackageName());
PendingIntent restartServicePendingIntent = PendingIntent.getService(
getApplicationContext(), 1, restartServiceIntent,
PendingIntent.FLAG_ONE_SHOT);
AlarmManager alarmService = (AlarmManager) getApplicationContext()
.getSystemService(Context.ALARM_SERVICE);
alarmService.set(AlarmManager.ELAPSED_REALTIME,
SystemClock.elapsedRealtime() + 1000,
restartServicePendingIntent);
super.onTaskRemoved(rootIntent);
}
}
and the exception thrown by Android 2.2 is as follows:
04-28 09:51:41.435: W/dalvikvm(280): threadid=7: thread exiting with uncaught exception (group=0x4001d800)
04-28 09:51:41.435: E/AndroidRuntime(280): FATAL EXCEPTION: Thread-8
04-28 09:51:41.435: E/AndroidRuntime(280): java.lang.ExceptionInInitializerError
04-28 09:51:41.435: E/AndroidRuntime(280): at com.example.backgroundservicedemo.BackgroundMusicService$ForThread.run(BackgroundMusicService.java:45)
04-28 09:51:41.435: E/AndroidRuntime(280): at java.lang.Thread.run(Thread.java:1096)
04-28 09:51:41.435: E/AndroidRuntime(280): Caused by: java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
04-28 09:51:41.435: E/AndroidRuntime(280): at android.os.Handler.<init>(Handler.java:121)
04-28 09:51:41.435: E/AndroidRuntime(280): at android.os.AsyncTask$InternalHandler.<init>(AsyncTask.java:421)
04-28 09:51:41.435: E/AndroidRuntime(280): at android.os.AsyncTask$InternalHandler.<init>(AsyncTask.java:421)
04-28 09:51:41.435: E/AndroidRuntime(280): at android.os.AsyncTask.<clinit>(AsyncTask.java:152)
Also, when I try using handler.post(new Runnable(){.... run(){}....} The UI hangs up but the background thread continues running and exits after it becomes out of memory.
Another thing that I have doubts about is:
When the application restarts, I want this active Service to stop, but how do I get a reference to this thread running in Background and how do I stop this? I would appreciate if anyone can redirect me to a suitable link/reference or could help me out with the code. Thanks
You have this inside a thread's run method
BackgroundAsyncTaskClass task = new BackgroundAsyncTaskClass();
task.execute();
Threading rules from the docs
The AsyncTask class must be loaded on the UI thread. This is done automatically as of JELLY_BEAN.
The task instance must be created on the UI thread.
execute(Params...) must be invoked on the UI thread.
Do not call onPreExecute(), onPostExecute(Result), doInBackground(Params...), onProgressUpdate(Progress...) manually.
The task can be executed only once (an exception will be thrown if a second execution is attempted.)

Android JAVA - Service return OutOfMemoryError exception after some while

I am developing my first android app. I have been created a Service class which role is to check if any new information on an external webpage. The HTTP request and service work as i should, but after a while I get these OutOfMemoryError.
Are someone able to see where the Service gather all that memory?
Error message 1.
java.lang.OutOfMemoryError: pthread_create (stack size 16384 bytes) failed: Try again
at java.lang.VMThread.create(Native Method)
at java.lang.Thread.start(Thread.java:1029)
at org.apache.http.impl.conn.tsccm.AbstractConnPool.enableConnectionGC(AbstractConnPool.java:140)
at org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager.createConnectionPool(ThreadSafeClientConnManager.java:120)
at org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager.(ThreadSafeClientConnManager.java:98)
at com.loopj.android.http.AsyncHttpClient.(AsyncHttpClient.java:210)
at com.loopj.android.http.AsyncHttpClient.(AsyncHttpClient.java:149)
at com.loopj.android.http.AsyncHttpClient.(AsyncHttpClient.java:119)
at com.quickit.app.MyService.checkUpdates(MyService.java:89)
at com.quickit.app.MyService.access$1(MyService.java:75)
at com.quickit.app.MyService$TimeDisplayTimerTask$1.run(MyService.java:68)
at android.os.Handler.handleCallback(Handler.java:733)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:136)
at android.app.ActivityThread.main(ActivityThread.java:5105)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:792)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:608)
at dalvik.system.NativeStart.main(Native Method)
Error message 2.
java.lang.OutOfMemoryError: thread creation failed
at java.lang.VMThread.create(Native Method)
at java.lang.Thread.start(Thread.java:1050)
at java.util.concurrent.ThreadPoolExecutor.addWorker(ThreadPoolExecutor.java:913)
at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1295)
at java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:81)
at com.loopj.android.http.AsyncHttpClient.sendRequest(AsyncHttpClient.java:893)
at com.loopj.android.http.AsyncHttpClient.post(AsyncHttpClient.java:688)
at com.loopj.android.http.AsyncHttpClient.post(AsyncHttpClient.java:671)
at com.loopj.android.http.AsyncHttpClient.post(AsyncHttpClient.java:658)
at com.quickit.app.MyService.checkUpdates(MyService.java:90)
at com.quickit.app.MyService.access$1(MyService.java:75)
at com.quickit.app.MyService$TimeDisplayTimerTask$1.run(MyService.java:68)
at android.os.Handler.handleCallback(Handler.java:725)
at android.os.Handler.dispatchMessage(Handler.java:92)
at android.os.Looper.loop(Looper.java:213)
at android.app.ActivityThread.main(ActivityThread.java:5092)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:797)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:564)
at dalvik.system.NativeStart.main(Native Method)
My service class.
public class MyService extends Service {
boolean login = false;
// constant
public static final long NOTIFY_INTERVAL = 10 * 1000; // 10 seconds
String address = Utilities.getAPIUrl();
// run on another Thread to avoid crash
private Handler mHandler = new Handler();
// timer handling
private Timer mTimer = null;
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
SharedPreferences prefs = getSharedPreferences("com.quickit.app", Context.MODE_PRIVATE);
login = prefs.getBoolean("login", false);
// cancel if already existed
if(mTimer != null) {
mTimer.cancel();
} else {
// recreate new
mTimer = new Timer();
}
// schedule task
mTimer.scheduleAtFixedRate(new TimeDisplayTimerTask(), 0, NOTIFY_INTERVAL);
}
public class TimeDisplayTimerTask extends TimerTask {
#Override
public void run() {
// run on another thread
mHandler.post(new Runnable() {
#Override
public void run() {
if(login) {
checkUpdates();
}
}
});
}
}
private void checkUpdates() {
final SharedPreferences prefs = getSharedPreferences("com.quickit.app", Context.MODE_PRIVATE);
final String from_id = prefs.getInt("user", 0)+"";
final String lastCheck = prefs.getString("last_check", "0");
RequestParams params = new RequestParams();
params.put("type", "get_ask_questions");
params.put("fromid", from_id);
params.put("last_check", lastCheck);
AsyncHttpClient client = new AsyncHttpClient();
client.post(address, params, new AsyncHttpResponseHandler() {
#Override
public void onSuccess(String response) {
try {
notification(response);
} catch (JSONException e) {
e.printStackTrace();
}
}
});
}
Your code is constantly creating a new AsyncHttpClient object every time that timer expires! If the object never finishes its work, at some point, you will run out of memory.
Since you are just periodically checking for updates, you should make the AsyncHttpClient object static and just reuse it.
Look at http://loopj.com/android-async-http/ specifically, the Recommended Usage section.

Categories

Resources