// PPS.java
package com.domain.Servicecrasher;
import android.app.Service;
import android.view.Gravity;
import android.widget.Toast;
public abstract class PPS extends Service
{
#Override
public void onCreate()
{
Toast toasty = Toast.makeText(PPS.this, "service created!", 500);
toasty.setGravity(Gravity.CENTER, 0, 200);
toasty.show();
};
public void onDestroy()
{
Toast toasted = Toast.makeText(PPS.this, "service destroyed!", 500);
toasted.setGravity(Gravity.CENTER, 0, -200);
toasted.show();
};
};
tried to call the service using two methods:
method 1.
{
{
{
startService(new Intent(MainMenu.this, PPS.class));
}
}
}
method 2
{
{
{
Intent startPPS = new Intent(MainMenu.this, PPS.class);
startPPS.putExtra("com.domain.Servicecrasher.PPS", false);
startService(startPPS);
}
}
}
these both return an error on the emulator saying the app quit unexpectedly and i click force close, but the main activity doesn't close, so i'm assuming it's the service that i am force closing. below is the DDMS output:
java.lang.RuntimeException: Unable to instantiate service com.domain.Servicecrasher.PPS
at android.app.ActivityThread.handleCreateService(ActivityThread.java:1929)
at android.app.ActivityThread.access$2500(ActivityThread.java:117)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:985)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:123)
at android.app.ActivityThread.main(ActivityThread.java:3683)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:507)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(Zygote.java:839)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597)
at dalvik.system.NativeStart.main(Native Method)
caused by: java.lang.InstantiationException: com.domain.Servicecrasher.PPS
at java.lang.Class.newInstaceImp1(Native Method)
at java.lang.Class.newInstaceI(Class.java:1409)
at android.app.ActivityThread.handleCreateService(ActivityThread.java:1926)
... 10 more
just a couple simple questions.
what am i doing wrong?
what is the proper way to do this?
eventually i need the service to be capable of loading settings from a SQL base and continue recording audio to a file after the main activity loses focus or is closed.
for now i'd be happy if i could just launch a simple service.
Abstract classes, be they Services or other things, cannot be instantiated. Eclipse no doubt suggested that you add the abstract keyword to your class because you had not implemented all the necessary methods to make a concrete instance.
I don't know if Eclipse has an option like this (I assume it does), but IntelliJ IDEA has an option where you can select "implement methods" when you have an incomplete class and it'll add all the stubs you need to fill in. Try that, or consult the documentation for a full list.
Related
I am aware there are many forms on StackOverflow about this very topic but none of the fixed worked for me.
When I run the code:
muteText.setText("Testing")
I get an error.
MainActivity.java
//Class Variables
Button startTime;
Button endTime;
TextView muteTime;
TextView unmuteTime;
int hour;
int minute;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//Define Variables
startTime = (Button)findViewById(R.id.startButton);
endTime = (Button)findViewById(R.id.endTime);
muteTime = (TextView)findViewById(R.id.muteText);
Log.i("SchedMute", "muteTime: " + muteTime.getText().toString());
unmuteTime = (TextView)findViewById(R.id.unmuteTime);
//Button Listeners
startTime.setOnClickListener(this);
endTime.setOnClickListener(this);
//--\\
hour = 0;
minute = 0;
}
public void onClick(View v){
int id = v.getId();
if(id == R.id.startButton){ //Selecting time 2 Mute phone
showTimePickerDialog(v);
}
}
public void setStartTime(){
muteTime.setText("Testing Testing 123");
}
(Error occurs in last Method (setStartTime))
I am calling the method in another class by doing so:
MainActivity activity = new MainActivity();
activity.setStartTime();
I spend a good 30 minutes trying to figure this one out.
Error:
07-29 12:29:44.034 19958-19958/myApp.com.app E/AndroidRuntime﹕ FATAL EXCEPTION: main
Process: myApp.com.app, PID: 19958
java.lang.NullPointerException
at myApp.com.app.MainActivity$TimePickerFragment.onTimeSet(MainActivity.java:96)
at android.app.TimePickerDialog.tryNotifyTimeSet(TimePickerDialog.java:223)
at android.app.TimePickerDialog.onClick(TimePickerDialog.java:173)
at com.android.internal.app.AlertController$ButtonHandler.handleMessage(AlertController.java:170)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:146)
at android.app.ActivityThread.main(ActivityThread.java:5678)
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:1291)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1107)
at de.robv.android.xposed.XposedBridge.main(XposedBridge.java:132)
at dalvik.system.NativeStart.main(Native Method)
MainActivity activity = new MainActivity();
You can NOT correctly create an instance of an Activity by using new. Never attempt to do this, it will not give you the behaviour you expected.
If you need to call a method in an Activity from a Fragment that is attached to it, you should used the approved approach of using a 'callbacks' interface.
See the following for Communicating with Other Fragments - even though it is about communicating with other Fragments, it is also the way a Fragment should communicate with the Activity it is attached to.
You call to setText before the Activity finished it creation. You need to call the function from the new Activity onCreate().
You should never call the constructor of an Activity. If you do, none of its activity lifecycle will occur. I'm guessing you're doing that in the time picker dialog, you should make that activity be a listener (or pass in an anonymous inner class listener) to handle the set time.
I need to start another activity from the onPosExecute method of the AsyncTask. The AsyncTask is a seperate class and not in any activity class.
I have used an interface to do so. The codes are:
This is the onPostExecute() method
#Override
protected void onPostExecute(String json) {
Log.v("JSON", json);
Log.v("updateUI",""+updateUI);
updateUI.changeActivity();
}
This is the interface
public interface UpdateUIListener {
public void changeActivity();
}
And this is the part of the activity class where the interface is implemented
#Override
public void changeActivity() {
Intent blah=new Intent(this,SplashActivity.class);
startActivity(blah);
finish();
}
When I run the code, a null pointer exception shows up, at the line
Intent blah=new Intent(this,SplashActivity.class);
My stacktrace is:
java.lang.NullPointerException
at android.content.ContextWrapper.getPackageName(ContextWrapper.java:135)
at android.content.ComponentName.<init>(ComponentName.java:75)
at android.content.Intent.<init>(Intent.java:3546)
at com.autofoyer.SignUpActivity.changeActivity(SignUpActivity.java:79)
at com.autofoyer.common.MyClientTask.onPostExecute(MyClientTask.java:73)
at com.autofoyer.common.MyClientTask.onPostExecute(MyClientTask.java:23)
at android.os.AsyncTask.finish(AsyncTask.java:631)
at android.os.AsyncTask.access$600(AsyncTask.java:177)
at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:644)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:5099)
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:803)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:570)
at dalvik.system.NativeStart.main(Native Method)
I need to know what is causing and How to solve the null point exception. I need to start and activity from the onPostExecute method. Thanks in advance!
You probably instantiate updateUI with new SplashActivity() or similar. You can't do that. Instead you have to pass a Context into your AsyncTask and use that to call startActivity() . You probably start the AsyncTask from some Activity, so just pass that Activity as a Context when instantiating the AsyncTask.
I pass a handler created on mainUI thread from Activity and passed to a thread which performs some network operation and when i obtain result i send the result back to the activity using the handler.
This approach had issue in memory leaks when i went through these links: Inner ClassHandler Memory Leak Android Developers
So i had implemented WeakReference, and kept the activity instance using WeakReference. But i am still seeing Activity instance alive even after activity is destroyed.
I created a Handler inside activity and passed activity instance as weakreference to handler.
By the time my Handler responds with a message delivered to it after 10secs, Activity is destroyed. But the weak reference still has the Activity instance and i am seeing the Toast, after Activity is destroyed.
Is there some where my understanding wrong ? Can someone explain how to handle messages delivered to a handler,but the UI is not around ?
import java.lang.ref.WeakReference;
import android.os.Handler;
import android.os.Message;
public abstract class SingleParamHandler <T> extends Handler
{
private WeakReference<T> mActivityReference;
public SingleParamHandler(T activity) {
mActivityReference = new WeakReference<T>(activity);
}
#Override
public void handleMessage(Message msg) {
if (mActivityReference.get() == null) {
return;
}
handleMessage(mActivityReference.get(), msg);
}
protected abstract void handleMessage(T activity, Message msg);
}
import android.app.Activity;
import android.os.Bundle;
import android.os.Message;
import android.widget.Toast;
public class MainActivity extends Activity {
MyHandler<MainActivity> handler;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main1);
handler = new MyHandler<MainActivity>(this);
new Thread(new MyRunnable(handler)).start();
}
public void onDestroy() {
super.onDestroy();
System.out.println("######## Activity onDestroy() ###### ");
}
private class MyRunnable implements Runnable {
private Handler mHandler;
public MyRunnable(Handler handler) {
mHandler = handler;
}
public void run() {
try {
Thread.sleep(10000);
mHandler.sendMessage(Message.obtain(handler, 1));
} catch ( Exception e) {
e.printStackTrace();
}
}
}
private static class MyHandler<T> extends SingleParamHandler<T> {
public MyHandler(T activity) {
super(activity);
}
#Override
public void handleMessage(T act, Message msg) {
if(msg.what == 1) {
Toast.makeText((MainActivity)act, "Called after activity destroyed", Toast.LENGTH_LONG).show();;
}
}
}
}
Based on the response obtained, i am updating the answer here. You may do it in the way u liked. But this is one way.
Added the below function in SingleParamHandler
public void clear() {
mActivityReference.clear();
}
And in Activity onDestroy()
public void onDestroy() {
super.onDestroy();
System.out.println("######## Activity onDestroy() ###### ");
handler.clear();
}
You don't need a WeakReference here. The Handler can just contain a reference to the Activity. In activity's onDestroy() just call a method on MyHandler that sets the reference to the Activity to null. Check for null in handleMessage().
Another choice would be this: in activity's onDestroy() call a method that interrupts the sleeping thread so that it shuts down before sending the message.
There's no guarantee that Android will really delete an object from memory if it's not required to do so. In other words, Activity objects can stay in memory even after onDestroy() has been called (if there's enough memory available). On the other hand, there's no guarantee that onDestroy() will be called if there's not enough memory; quite to the contrary, Android is allowed to kill your whole process after calling onPause() on your current Activity (depending on the Android version).
I think there's a better path to follow for your purpose. What you may want to do is attach, detach and possibly re-attach (e.g. on configuration changes) Activities to your Service. Don't hope for the garbage collector to do the work for you. Rather, make it explicitly.
Subclass Activity and override the lifecycle methods as well as startActivity() and startActivityForResult() to let your Service know who's in charge right now. Of course, that's only a best-effort approach since some callbacks aren't guaranteed, but that only matters in certain situations which aren't dangerous. For example, your Activity won't detach from your Service in onPause(), but it could get killed right afterwards. But either your Service runs in the same process, so it gets killed at the same time. Or it runs in a different process, but then Android will notice the broken connection and may or may not kill the service as well; if not, then all you need to do is implement it in a robust fashion to be able to deal with the connection loss.
Update
After reading your comment: You're right, I didn't address that specifically.
i am figuring out how to avoid messages being sent to a handler which is created in a activity which is destroyed
Given your code above, and assuming that you really just want to display Toasts with an Activity as long as it exists, the following approach should help.
If your Thread is supposed to serve more than one Activity, extend it such that Activities can register with the Thread after it is created. If your Thread just serves one Activity, pass the Activity reference along with the Handler reference upon your Thread's (Runnable's) construction.
Before your Thread sends the message via the Handler, check activity.isDestroyed(). If the Activity is not destroyed, send the message. If the Activity is destroyed, do not send the message.
Depending on whether your Thread should server more than one Activity, either exit it's Runnable's run() method or set it's Activity reference to null if it finds that the Activity has been destroyed.
This should fix your above code. However, if your scenario grows, other approaches may be more suitable.
I got an null pointer exception on Android 3.2 emulator on a simple Android project created by Wizerd with a service in separated process, when I switch between "Stretch to fill screen" to "Zoom to fill screen". This crash will not happen if the service is put into the same process with main activity, namely "android:process" attribute not specified. While it only happens when I add "android:process" to manifest file for my test service.
The exception is:
FATAL EXCEPTION: main
java.lang.NullPointerException
at android.view.WindowManagerImpl.reportNewConfiguration(WindowManagerImpl.java:427)
at android.app.ActivityThread.handleUpdatePackageCompatibilityInfo(ActivityThread.java:2801)
at android.app.ActivityThread.access$2700(ActivityThread.java:122)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1151)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:132)
at android.app.ActivityThread.main(ActivityThread.java:4123)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:491)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:841)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:599)
at dalvik.system.NativeStart.main(Native Method)
My test code:
TestActivity.java (Generated by Wizerd)
package com.test;
import android.app.Activity;
public class TestActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Intent intent = new Intent(this, TestService.class);
startService(intent);
}
}
TestService.java (Most of the functions are empty)
Package com.test;
import android.content.ComponentName;
public class TestService extends Service {
private boolean m_connected = false;
private ServiceConnection m_connInitService = new ServiceConnection() {
public void onServiceConnection(ComponentName className, IBinder service) {
m_connected = true;
}
public void onServiceDisconnected(ComponentName className) {
}
};
public static class TestServiceBinder extends Binder {
}
public IBinder onBind(Intent intent) {
return new TestServiceBinder();
}
public void onDestroy() {
super.onDestroy();
}
public int onStartCommand(Intent intent, int flags, int startId) {
return 1;
}
}
If I run the test app without service or with service in the same process the screen compatibility switch will not cause any problem. However, I do not understand why service can cause system exception during screen compatibility switch. Is this because service process is a non-UI process? Which could potentially triggers a bug inside the Android core code?
I've found in the documentation the following thing:
android:process
If the name assigned to this attribute begins with a colon (':'), a
new process, private to the application, is created when it's needed
and the service runs in that process. If the process name begins with
a lowercase character, the service will run in a global process of
that name, provided that it has permission to do so. This allows
components in different applications to share a process, reducing
resource usage.
Thus, if you assign process name that starts with lowercase you should have permissions to do this. But I do not know where these permissions are checked. Maybe they are checked in the WindowManagerImpl and it cannot find this global process and thus returns null. This is just an assumption.
The reason causing this issue is Screen Compatibility Mode, see how to disable it for your app:
http://developer.android.com/guide/practices/screen-compat-mode.html#Disable
When I press the Home button, the app should be paused, save all state and work fine.
Instead I get this error:
java.lang.RuntimeException: Unable to
pause activity
{be.test.tester/be.test.tester.DataScreen}:
java.lang.IllegalStateException:
Derived class did not call
super.onSaveInstanceState() at
android.app.ActivityThread.performPauseActivity(ActivityThread.java:3641)
at
android.app.ActivityThread.performPauseActivity(ActivityThread.java:3598)
at
android.app.ActivityThread.handlePauseActivity(ActivityThread.java:3574)
at
android.app.ActivityThread.access$2500(ActivityThread.java:136)
at
android.app.ActivityThread$H.handleMessage(ActivityThread.java:2186)
at
android.os.Handler.dispatchMessage(Handler.java:99)
at
android.os.Looper.loop(Looper.java:143)
at
android.app.ActivityThread.main(ActivityThread.java:5068)
at
java.lang.reflect.Method.invokeNative(Native
Method) at
java.lang.reflect.Method.invoke(Method.java:521)
at
com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:858)
at
com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
at
dalvik.system.NativeStart.main(Native
Method)
Caused by:
java.lang.IllegalStateException:
Derived class did not call
super.onSaveInstanceState() at
android.view.View.dispatchSaveInstanceState(View.java:6087)
at
android.view.ViewGroup.dispatchSaveInstanceState(ViewGroup.java:1207)
at
android.view.ViewGroup.dispatchSaveInstanceState(ViewGroup.java:1207)
at
android.view.View.saveHierarchyState(View.java:6068)
at
com.android.internal.policy.impl.PhoneWindow.saveHierarchyState(PhoneWindow.java:1475)
at
android.app.Activity.onSaveInstanceState(Activity.java:1106)
at
android.app.Activity.performSaveInstanceState(Activity.java:1056)
at
android.app.Instrumentation.callActivityOnSaveInstanceState(Instrumentation.java:1289)
at
android.app.ActivityThread.performPauseActivity(ActivityThread.java:3623)
... 12 more
My activity reacts on touch:
public class DataScreen extends Activity implements OnGestureListener{
I'm getting some extra's from the intent:
totUsage = Integer.parseInt(getIntent().getStringExtra("extraTotUsage"));
limit = Integer.parseInt(getIntent().getStringExtra("extraLimit"));
Bundle bundle = getIntent().getExtras();
mylist = (ArrayList<HashMap<String, String>>) bundle.get("extraMyList");
A custom view is showing data (canvas). When you scroll on screen, data changes in custom view (set, get method) and redraws itself.
I don't really manage the onSaveInstanceState here, don't really know if I have to.
My app is onTop of the stack, because of:
i.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
I don't understand the error.
You should override onSaveInstanceState and call its super method like shown below. At least it helped me with the same problem.
#Override
public void onSaveInstanceState(Bundle savedInstanceState) {
super.onSaveInstanceState(savedInstanceState);
// your stuff or nothing
}
#Override
public void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
// your stuff or nothing
}
I've just been dealing with this problem. In my app the main activity allows a second activity to be called to display info/instructions etc, it also has a surface view that draws the runtime element of the app.
The main activity has a variable to hold the surface view, if that variable hasn't been set before the info/instructions activity is called I get this error. I simply moved the surface view variable assignment into the main activity onCreate and all is well.
It is also possible that one uses a custom preference (e.g. custom dialog preference) that does not call "super.onSavedInstanceState()" which leads to the same error.