I just updated my app on the play store and i started receiving crash reports from people, one was a person i know, so he started helping me to solve this problem, and i discovered that the problem is caused by something i didn't even modify.
The code looks like this
The part that's causing the problem is the bulb.onClickListener
public class Bulb extends Activity {
public boolean isAwake = false;
boolean timerActivated = false;
static ImageView glow;
public static boolean bulbActIsRunning = false;
public void startWake() {
Intent wS=new Intent(getBaseContext(), WakeService.class);
startService(wS);
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ImageButton bulb = (ImageButton) findViewById(R.id.bulb);
ImageButton ghl = (ImageButton) findViewById(R.id.ghl);
glow = (ImageView) findViewById(R.id.glow);
if (WakeService.isAwake) {
glow.setVisibility(View.VISIBLE);
}
else {
glow.setVisibility(View.INVISIBLE);
}
bulb.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
startWake();
if (WakeService.isAwake) {
glow.setVisibility(View.INVISIBLE);
}
else {
glow.setVisibility(View.VISIBLE);
}
}
});
ghl.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("http://www.geekshavelanded.com/"));
startActivity(browserIntent);
}
});
}
#Override
protected void onResume() {
// TODO Auto-generated method stub
super.onResume();
glow = (ImageView) findViewById(R.id.glow);
if (WakeService.isAwake) {
glow.setVisibility(View.VISIBLE);
}
else {
glow.setVisibility(View.INVISIBLE);
}
}
#Override
public void onStart() {
super.onStart();
bulbActIsRunning = true;
}
#Override
public void onStop() {
super.onStop();
bulbActIsRunning = false;
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.activity_main, menu);
return true;
}
}
After my friends clicks the bulb button the app crashes without reason, i've put some toast notification at the beginning of the onClickListener to see if it appeared before crashing, but it didn't
The crash reports look like this
java.lang.RuntimeException: Unable to start service com.doublep.wakey.WakeService#41740bb8 with Intent { cmp=com.doublep.wakey/.WakeService }: java.lang.NullPointerException
at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:2933)
at android.app.ActivityThread.access$1900(ActivityThread.java:151)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1438)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:155)
at android.app.ActivityThread.main(ActivityThread.java:5454)
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:1029)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:796)
at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.NullPointerException
at android.os.Parcel.readException(Parcel.java:1436)
at android.os.Parcel.readException(Parcel.java:1384)
at com.android.internal.appwidget.IAppWidgetService$Stub$Proxy.updateAppWidgetIds(IAppWidgetService.java:513)
at android.appwidget.AppWidgetManager.updateAppWidget(AppWidgetManager.java:333)
at android.appwidget.AppWidgetManager.updateAppWidget(AppWidgetManager.java:400)
at com.doublep.wakey.WakeService.keepAwake(WakeService.java:86)
at com.doublep.wakey.WakeService.onStartCommand(WakeService.java:48)
at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:2912)
... 10 more
Can anyone see something suspicious?
I didn't even touch the code of this activity when i was updating my app, and everything else works fine, because i can call the service from a widget aswell.
So the problem must be here
I also modified the min SDK from 8 to 7 (but to see if it works i've put it back to 8)
And i compressed some graphics a little bit more to save space
EDIT oh i forgot to say, this happens only to few devices, on most it seems working fine
UPDATE 2 this is the piece of code that caused those issues
AppWidgetManager mgr=AppWidgetManager.getInstance(this);
mgr.updateAppWidget(ToggleWidget.appWidgetId, ToggleWidget.remoteViews);
Please check the parameter to updateAppWidget(). Ether remote view is null or you are setting null bitmap.
Related
Changing night-light mode perfectly works in my emulator, but when i try to do the same on physical device(xiaomi) I get next exception:
E/ActivityInjector: get life cycle exception
java.lang.ClassCastException: android.os.BinderProxy cannot be cast to android.app.servertransaction.ClientTransaction
at android.app.ActivityInjector.checkAccessControl(ActivityInjector.java:24)
at android.app.Activity.onResume(Activity.java:1859)
at androidx.fragment.app.FragmentActivity.onResume(FragmentActivity.java:456)
at android.app.Instrumentation.callActivityOnResume(Instrumentation.java:1454)
at android.app.Activity.performResume(Activity.java:8050)
at android.app.ActivityThread.performResumeActivity(ActivityThread.java:4269)
at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:4311)
at android.app.servertransaction.ResumeActivityItem.execute(ResumeActivityItem.java:52)
at android.app.servertransaction.TransactionExecutor.executeLifecycleState(TransactionExecutor.java:176)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:97)
at android.app.ClientTransactionHandler.executeTransaction(ClientTransactionHandler.java:57)
at android.app.ActivityThread.handleRelaunchActivityLocally(ActivityThread.java:5353)
Here is my code in activity and presenter where i change mode of my my application:
public class MoviesListActivity extends AppCompatActivity implements MovieListView {
#Override
public boolean onOptionsItemSelected(#NonNull MenuItem item) {
if (item.getItemId() == R.id.darkMode) {
presenter.changeToDarkMode();
}
else if(item.getItemId() == R.id.lightMode) {
presenter.changeToLightMode();
}
return super.onOptionsItemSelected(item);
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.movie_list);
presenter = new MoviesListPresenter(this, getApplicationContext());
if (presenter.getCurrentMode() == 0) {
presenter.changeToLightMode();
} else {
presenter.changeToDarkMode();
}
}
//Other code...
}
Presenter:
public class MoviesListPresenter {
public void changeToLightMode() {
currentMode = context.getSharedPreferences(Constants.MODE, Context.MODE_PRIVATE);
currentMode.edit().putInt(Constants.MODE, 0).apply();
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO);
}
public void changeToDarkMode() {
currentMode = context.getSharedPreferences(Constants.MODE, Context.MODE_PRIVATE);
currentMode.edit().putInt(Constants.MODE, 1).apply();
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES);
}
public int getCurrentMode() {
currentMode = context.getSharedPreferences(Constants.MODE, Context.MODE_PRIVATE);
return currentMode.getInt(Constants.MODE, 0);
}
}
I will be thankful for any help!
This seem caused by calling Activity.recreate() in Xiaomi's firmware. This problem also happen to my library which recreate the activity to apply the language changing.
See https://github.com/akexorcist/Localization/issues/89
In my case, no app crashing and code working properly. So I skipped this problem.
Related questions
MIUI 11/12 Theme Switch Results in LifeCycleException, ClassCastException
Getting Lifecycle Exception While Recreating The Activity
Good day! As usual - I am starting to learn Android programming and have faced unexpected difficulty while trying to create basic MediaPlayer app. Audio file is stored in res/raw. It is accessed with create(). I have read a few manuals on how to build a media player app and was convinced that using prepare() and prepareAsync() was not necessary in case if file is stored in res/raw folder. So here is my initial code
private MediaPlayer playerM = new MediaPlayer();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button playButton = (Button) findViewById(R.id.playButton);
playButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
playMusic(R.raw.sleep_away);
}
});
Button stopButton = (Button) findViewById(R.id.pauseButton);
stopButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
stopMusic();
}
});
}
private void playMusic(int rid) {
playerM.create(this, rid);
playerM.start();
}
private void stopMusic() {
playerM.stop();
}
}
Since that I have made numerous changes, but nothing helped. According to dev.android manual on MediaPlayer the code above should work. However it results in the following errors:
E/MediaPlayer: start called in state 1, mPlayer(0x0)
E/MediaPlayer: error (-38, 0)
E/MediaPlayer: Error (-38,0)
Probably I am just making some blunt mistake. Any help would be much appreciated.
Solved by myself
playButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
try{
Uri myUri = Uri.parse("android.resource://" + v.getContext().getPackageName() + "/" + R.raw.sleep_away);
System.out.println(myUri);
playerM.setDataSource(v.getContext(), myUri);
playerM.prepare();
playerM.setOnPreparedListener(new MediaPlayer.OnPreparedListener(){
#Override
public void onPrepared(MediaPlayer playerM){
playerM.start();
}
});
}catch(IOException e){
e.printStackTrace();
}
}
});
I know I should add other methods to change State, but the main purpose was to get it to play file.
This is my code, I tried ti build simple application that plays a song whenever I click one button (clicking twice will play the song a new from the beginning) & stop playing when another button is pushed.
I wanted that when the user put the activity in the background the media player will "save its state" - continue playing/not playing - and when the activity returns to the foreground the interaction will remain the same.
Instead it works fine until I put the activity in the background (then it keeps playing/not playing) but when I return it back it seems like "a new media player object was created" and if I click play while the song is played, it starts to play the song from the beginning simultaneously with the previous one, and clicking stop - stopping only the new "instance" of the song. Like I loose connection with the media player after the activity is in the background.
what could be the problem?
public class MainActivity extends ActionBarActivity {
private MediaPlayer mediaPlayer;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button buttonStart = new Button(this);
Button buttonStop = new Button(this);
buttonStart.setText(R.string.button_start_text);
buttonStop.setText(R.string.button_stop_text);
buttonStart.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
startPlaying();
}
});
buttonStop.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
stopPlaying();
}
});
ViewGroup layout = (ViewGroup) findViewById(R.id.mainLayout);
layout.addView(buttonStart);
layout.addView(buttonStop);
}
void startPlaying(){
stopPlaying();
mediaPlayer = MediaPlayer.create(this,R.raw.dreams);
mediaPlayer.start();
}
void stopPlaying(){
if (mediaPlayer != null){
try {
if (mediaPlayer.isPlaying()) {
mediaPlayer.stop();
mediaPlayer.reset();
mediaPlayer.release();
}
}
catch (Exception e){
e.printStackTrace();
}
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
#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();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
I changed the code also, like this (now there are 3 buttons: play, stop, pause:
void startPlaying(){
if (mediaPlayer == null) {
mediaPlayer = MediaPlayer.create(this, R.raw.dreams);
}
mediaPlayer.start();
}
void stopPlaying(){
if (mediaPlayer != null){
try {
if (mediaPlayer.isPlaying()) {
mediaPlayer.stop();
mediaPlayer.prepare();
}
}
catch (Exception e){
e.printStackTrace();
}
}
}
void pausePlaying(){
if (mediaPlayer != null) mediaPlayer.pause();
}
but still same behaviour.
Some insight I got:
before the user place the activity in the background the member mediaPlayer is some constructed android object.
when the activity returns to the foregound mediaPlayer is null.
Why is this?
Maybe I got wrong the idea of activity but I thought it keeps its members with their values during its life cycle.
Your are creating and destroying your mediaplayer everytime. Try to create two methods for pause and resume/start like that.
below you can find the code that is working fine for me. I am developing a game that starts a main theme when the activity loads. Each time the activity resumes, the media player continue to play the song at the paused position. I override onDestroy() to stop, onResume to start/resume and onPause() to pause when the activity goes Background.
public MediaPlayer mp=null;
#Override
protected void onDestroy() {
if (mp!=null)
mp.stop();
super.onStop();
}
#Override
protected void onResume() {
super.onResume();
if (mp==null){
self=this;
Thread thMusic= new Thread(new Runnable(){
public void run(){
mp= MediaPlayer.create(self,R.raw.dizzy );
mp.start();
}
});
thMusic.start();
}
else
mp.start();
}
#Override
protected void onPause() {
if (mp!=null)
mp.pause();
super.onPause();
}
i hope this will help you.
http://developer.android.com/guide/components/activities.html
Saving activity state gives a detailed information that could explain what happened.
In short when activity is in the background it might be killed and created again by OS when user navigate it back to foreground.
onSaveInstanceState() should be implemented unless only UI objects are restored
but not class members
I know my question might be stupid but I am new in Android App development and the Eclipse things but reached to e problem that can't find solution in internet.
I am making multi-activity application and reached to a point where when i have two buttons in one of the activities and want each of them to lead to different other activities, the application crashes. When I lead them both to one activity, everything is fine. Here is my code and hope really my question not to be so stupid as I am thinking.
public class Home extends ActionBarActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_home);
Button myButton = (Button) findViewById(R.id.tables);
myButton.setOnClickListener(goToTables);
Button mySecondButton = (Button) findViewById(R.id.reservations);
mySecondButton.setOnClickListener(goToMenu);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.home, menu);
return true;
}
private OnClickListener goToTables = new OnClickListener(){
#Override
public void onClick(View v) {
doButton();
}};
private void doButton()
{
startActivity(new Intent(this, Tables.class));
}
private OnClickListener goToMenu = new OnClickListener(){
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
doSecondButton();
}};
private void doSecondButton()
{
startActivity(new Intent(this, Menu.class));
}
}
The goToTables works perfectly but I am missing something important to change in goToMenu. My other activities are: Tables and Menu. Can somebody please tell me where I am wrong? Thanks in advance!
android:onClick="dobutton" try adding this in your button tag in xml code rather then using onclicklistner.
Try changing the name of your Menu activity or add the full name path of Menu.class in your intent, eg. com.myapp.Menu.class
I have this preferences class (below) that saves two ListPreferences, but if the ListPreferences are changed and the back button is pressed, the changes don't take affect unless the application is restarted. Did I miss something? Have been looking everywhere, but just can't seem to find an answer the fits or works. Please help.
public class Preferences extends PreferenceActivity {
#Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.preferences);
}
#Override
public void onPause() {
super.onPause();
}
#Override
public void onResume() {
super.onResume();
}
}
Application Code
public class Quotes extends Activity implements OnClickListener {
ProgressDialog dialog;
private WebView webview;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
SharedPreferences SP = PreferenceManager.getDefaultSharedPreferences(getBaseContext());
String q = SP.getString("appViewType","http://www.google.com");
String c = SP.getString("appRefreshRate","20");
webview = (WebView) findViewById(R.id.scroll);
webview.getSettings().setJavaScriptEnabled(true);
webview.setWebViewClient(new QuotesWebView(this));
webview.loadUrl(q);
ScheduledExecutorService timer = Executors.newSingleThreadScheduledExecutor();
timer.scheduleAtFixedRate(new Runnable() {
#Override
public void run() {
webview.reload();
}
}, 10, Long.parseLong(c),TimeUnit.SECONDS);
findViewById(R.id.refresh).setOnClickListener(this);
}
#Override
public void onPause(){
super.onPause();
}
#Override
public void onResume(){
super.onResume();
}
public void onClick(View v){
switch(v.getId()){
case R.id.refresh:
webview.reload();
break;
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.menu, menu);
MenuItem about = menu.getItem(0);
about.setIntent(new Intent(this, About.class));
MenuItem preferences = menu.getItem(1);
preferences.setIntent(new Intent(this, Preferences.class));
return true;
}
}
You need to somehow reload your preferences when the preferences activity finishes. I thought Dirol's suggestion of loading them in onResume() instead of onCreate() was excellent; have you tried it? Or am I misunderstanding the problem as well.
In my own case, I launched the preferences activity with startActivityForResult() and then on the activity result callback, I reloaded the preferences.
Code snippets:
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case MENU_PREFERENCES:
Intent intent = new Intent().setClass(this, CalcPreferences.class);
startActivityForResult(intent, MENU_PREFERENCES);
break;
default: return super.onOptionsItemSelected(item);
}
return true;
}
#Override
protected void onActivityResult(int req, int result, Intent data) {
switch( req ) {
case MENU_PREFERENCES:
SharedPreferences sp =
PreferenceManager.getDefaultSharedPreferences(this);
updatePreferences(sp);
break;
default:
super.onActivityResult(req, result, data);
break;
}
}
#Override
protected void updatePreferences(SharedPreferences sp) {
super.updatePreferences(sp);
keyclick = sp.getBoolean("keyclick", keyclick);
}
Anyway, this is what works for me. I may try moving my updatePreferences() call to onResume() myself to see if that works too.
Try overriding the onBackPressed() method.
If your "Up" button (top left <-) provides the correct result, then you can set the Back button to behave like the Up button.
#Override
public void onBackPressed() {
super.onBackPressed();
NavUtils.navigateUpFromSameTask(this);
}
You load preferences only on onCreate() method. That method called only when a fresh activity starts up. The addPreferencesFromResource inflates the xml file into the preferences, so you only get the info, which is already has been stored in the xml at the moment addPreferencesFromResource was called, not after.
Try to move that method to onResume. But watch for the memory leak. I don't know exactly what the addPreferencesFromResource do, but from the documentation - I would be very suspicious about that method activity.
I had the same problem and solved it as follows:
The main activity class implements OnSharedPreferenceChangeListener:
public class Activity_name extends Activity implements OnSharedPreferenceChangeListener {
...
}
Inside the main activity class the onSharedPreferenceChanged is run whenever a preference entry changes. I simply update all my variables from the preferences as i did in onCreate:
#Override
public void onSharedPreferenceChanged(SharedPreferences prefs, String key) {
<read all preferences as you did in onCreate()>
}
This does the trick and I hope it saves you some time in searching for a solution.
I've had the same problem...
Try to create preference instance and load its data in every class and every activity where you need it.
It worked for me...Hope it helps.
You will need to reload your view or whatever object which uses those preferences, preferably when preference activity closes.
Preference activities do not change nothing but an internal file with your preferences(key=value list). When it is changed, preferenceActivity calls onPreferenceChaged() and nothing more. It doesn't refresh your stuff by itself. You need to reload prefs and to reuse them in onResume() method or equivalent.