I am following the patterns that are used in the Compass example in a new project and have most of the logic working. However, when I tap while my live card is displayed I hear the 'click' noise but my menu activity doesn't display. I think that I am missing a piece of the puzzle, but I have not been able to figure out what as of yet.
When I tap, besides the click, I also see this in logcat:
01-08 10:02:26.796: I/ActivityManager(196): START {flg=0x10008000 cmp=com.example.speeddisplay/.SpeedDisplayMenuActivity} from pid -1
So it looks like it should be starting my activity, but it doesn't show up. Here are some pieces of relevant code...although I am not sure where the issue is.
Service portion in AndroidManifest.xml:
<service
android:name="com.example.speeddisplay.service.SpeedService"
android:enabled="true"
android:icon="#drawable/ic_drive_50"
android:label="#string/app_name" >
<intent-filter>
<action android:name="com.google.android.glass.action.VOICE_TRIGGER" />
</intent-filter>
<meta-data
android:name="com.google.android.glass.VoiceTrigger"
android:resource="#xml/voiceinput_speeddisplay" />
</service>
onStartCommand method in SpeedService.java:
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (Constants.DEBUG) {
Log.d(TAG, "onStartCommand");
}
if (liveCard == null) {
liveCard = timelineManager.createLiveCard(LIVE_CARD_ID);
speedRenderer = new SpeedRenderer(this, speedManager);
liveCard.setDirectRenderingEnabled(true);
liveCard.getSurfaceHolder().addCallback(speedRenderer);
// Display the options menu when the live card is tapped.
Intent menuIntent = new Intent(this, SpeedDisplayMenuActivity.class);
menuIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
liveCard.setAction(PendingIntent.getActivity(this, 0, menuIntent, 0));
liveCard.publish(PublishMode.REVEAL);
if(Constants.DEBUG){
Log.d(TAG, "liveCard published");
}
}
return START_STICKY;
}
Here is my SpeedDisplayMenuActivity.java. None of these methods are getting called.
public class SpeedDisplayMenuActivity extends Activity {
private SpeedService.SpeedBinder speedService;
private boolean mResumed;
private ServiceConnection mConnection = new ServiceConnection() {
#Override
public void onServiceConnected(ComponentName name, IBinder service) {
if (Constants.DEBUG) {
Log.e("Service Stuff", "Service connected.");
}
if (service instanceof SpeedService.SpeedBinder) {
speedService = (SpeedService.SpeedBinder) service;
openOptionsMenu();
}
if (Constants.DEBUG) {
Log.e("Service Stuff", "service was an instance of " + service.getClass().getName());
}
}
#Override
public void onServiceDisconnected(ComponentName name) {
// Do nothing.
}
};
#Override
protected void onCreate(Bundle savedInstanceState) {
if(Constants.DEBUG){
Log.e("Menu", "Created.");
}
super.onCreate(savedInstanceState);
bindService(new Intent(this, SpeedService.class), mConnection, 0);
}
#Override
protected void onResume() {
if(Constants.DEBUG){
Log.e("Menu", "Resumed.");
}
super.onResume();
mResumed = true;
openOptionsMenu();
}
#Override
protected void onPause() {
if(Constants.DEBUG){
Log.e("Menu", "Paused.");
}
super.onPause();
mResumed = false;
}
#Override
public void openOptionsMenu() {
if (Constants.DEBUG) {
Log.e("Options Menu", "Open");
}
if (mResumed && speedService != null) {
if (Constants.DEBUG) {
Log.e("Options Menu", "Open with correct params");
}
super.openOptionsMenu();
} else {
if (Constants.DEBUG) {
Log.e("Options Menu", "Open with INCORRECT params");
}
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
if (Constants.DEBUG) {
Log.e("Options Menu", "Created");
}
getMenuInflater().inflate(R.menu.speed, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
if (Constants.DEBUG) {
Log.e("Options Menu", "Item Selected");
}
switch (item.getItemId()) {
// case R.id.read_aloud:
// mCompassService.readHeadingAloud();
// return true;
case R.id.stop:
if (Constants.DEBUG) {
Log.e("Options Menu", "Stop");
}
stopService(new Intent(this, SpeedService.class));
return true;
default:
return super.onOptionsItemSelected(item);
}
}
#Override
public void onOptionsMenuClosed(Menu menu) {
if (Constants.DEBUG) {
Log.e("Options Menu", "Closed");
}
super.onOptionsMenuClosed(menu);
unbindService(mConnection);
// We must call finish() from this method to ensure that the activity
// ends either when an
// item is selected from the menu or when the menu is dismissed by
// swiping down.
finish();
}
Does anybody see what I am missing?
That is right, declaring the SpeedDisplayMenuActivity is the problem in this case.
I have seen cases where many other types of exceptions / crash that normally happens in Android environment is gracefully handled in Glass.
That is definitely good for the user experience, but makes little tough on development. Hopefully some kind of settings come in future to enable exceptions as well in future!
Related
I want to play 6 different sounds triggered by 6 different buttons in background, so that if the app is on background the sound keeps playing.
When one sound is already playing, pressing another button will stop it and play its own sound,
Tapping the same button 2K times it stops, 2K+1 times: starts again.. (K is a non-null integer)
All of the code is done and seems to be working correctly, except that the player stops after one and a half minute. (This is not because of low memory)
Can anyone please tell me what am I doing wrong?
public class PlayService extends Service {
private MediaPlayer player;
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
super.onCreate();
player = new MediaPlayer();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
super.onStartCommand(intent, flags, startId);
int btnId = intent.getExtras().getInt("ID");
Toast.makeText(this, "onStart service" + btnId, Toast.LENGTH_SHORT).show();
selectResId(btnId);
return START_STICKY;
}
#Override
public void onDestroy() {
super.onDestroy();
Toast.makeText(this, "Service destroyed", Toast.LENGTH_SHORT).show();
if (player != null) {
player.stop();
player.release();
}
player = null;
}
#Override
public void onLowMemory() {
super.onLowMemory();
Toast.makeText(this, "Low mem", Toast.LENGTH_SHORT).show();
}
private void selectResId(int resId){
switch (resId){
case 1: playMediaFromResource(R.raw.number_one);
case 2: playMediaFromResource(R.raw.number_two);
case 3: playMediaFromResource(R.raw.number_three);
case 4: playMediaFromResource(R.raw.number_four);
case 5: playMediaFromResource(R.raw.number_five);
case 6: playMediaFromResource(R.raw.number_six);
default: break;
}
}
private void playMediaFromResource(int resId) {
Uri mediaPath = Uri.parse("android.resource://" + getPackageName() + "/" + resId);
try {
player.setDataSource(getApplicationContext(), mediaPath);
player.setLooping(true);
player.prepare();
player.start();
} catch (Exception e) {
e.printStackTrace();
}
}
}
And the MainActivity:
public class MainActivity extends AppCompatActivity {
private Button btnStart1;
private Button btnStart2;
private Button btnStart3;
private Button btnStart4;
private Button btnStart5;
private Button btnStart6;
private Intent intent;
private int previousID = 0;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
findViewsByIds();
setOnClickListeners();
}
private void findViewsByIds() {
btnStart1 = findViewById(R.id.btn_start_1);
btnStart2 = findViewById(R.id.btn_start_2);
btnStart3 = findViewById(R.id.btn_start_3);
btnStart4 = findViewById(R.id.btn_start_4);
btnStart5 = findViewById(R.id.btn_start_5);
btnStart6 = findViewById(R.id.btn_start_6);
}
private void setOnClickListeners() {
btnStart1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
checkIntentState(1);
}
});
btnStart2.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
checkIntentState(2);
}
});
btnStart3.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
checkIntentState(3);
}
});
btnStart4.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
checkIntentState(4);
}
});
btnStart5.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
checkIntentState(5);
}
});
btnStart6.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
checkIntentState(6);
}
});
}
private void checkIntentState(int ID) {
if (intent == null) {
createNewIntent(ID);
} else {
stopService(intent);
intent = null;
if (ID != previousID) {
createNewIntent(ID);
}
}
}
private void createNewIntent(int ID) {
intent = new Intent(MainActivity.this, PlayService.class);
intent.putExtra("ID", ID);
startService(intent);
previousID = ID;
}
}
I want to answer to my own question just in case anyone else runs into the problem.
It turns out, that Android added some new features (restricted access to background resources for battery life improvement purposes since Oreo(i.e. Android 8.0+ || API level 26)).
As the documentation says:
"Apps that are running in the background now have limits on how freely they can access background services."
So, in this case we will need to use foreground services.
I am a beginner in android and right now working on a music streaming app. I have taken a course on Udemy for beginners for that and
the instructor goes line by line showing each step of creation,and i do exactly what he does. Now that we have reached the step of creating a notification for the
app, he uses something called 'NotificationCompat.Builder(this)'. Now when I type the same exact code, I get an error saying that the
NotificationCompat.Builder(context) has been deprecated now in android O. Due to this I am not getting the notifications on my phone when I
run it. Also the music is not being streamed. Due to this I am not able to proceed with further lectures.
I tried to ask the instructor on the forum for some help regarding this, but he does not seem to reply back. Also I tried to research
about the notification channels in android O, but I am unable to understand the concepts due to the lack of knowledge on basic android.
So it would be great if I could get some help regarding my problem.
I am uploading my code along with this.
The error is in PlayerService.java
(1). activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.music.zirakmistry.musicstreamingapp.MainActivity">
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="#style/AppTheme.AppBarOverlay">
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:popupTheme="#style/AppTheme.PopupOverlay" />
</android.support.design.widget.AppBarLayout>
<include layout="#layout/content_main" />
<android.support.design.widget.FloatingActionButton
android:id="#+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
android:layout_margin="#dimen/fab_margin"
app:srcCompat="#android:drawable/ic_media_play" />
</android.support.design.widget.CoordinatorLayout>
(2). MainActivity.java
public class MainActivity extends AppCompatActivity {
static FloatingActionButton playPauseButton;
PlayerService mBoundService;
boolean mServiceBound=false;
private ServiceConnection mServiceConnection=new ServiceConnection() {
#Override
public void onServiceConnected(ComponentName name, IBinder service) {
PlayerService.MyBinder myBinder=(PlayerService.MyBinder)service;
mBoundService=myBinder.getService();
mServiceBound=true;
}
#Override
public void onServiceDisconnected(ComponentName name){
mServiceBound=false;
}
};
private BroadcastReceiver mMessageReceiver=new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
boolean isPlaying=intent.getBooleanExtra("isPlaying",false);
flipPlayPauseButton(isPlaying);
}
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
playPauseButton = (FloatingActionButton) findViewById(R.id.fab);
playPauseButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view){
if(mServiceBound)
mBoundService.togglePlayer();
}
});
startStreamingService("https://www.mymusicstreamingapp.com/music_app/cute.mp3");
}
private void startStreamingService(String url)
{
Intent i=new Intent(this,PlayerService.class);
i.putExtra("url",url);
i.setAction(Constants.ACTION.STARTFOREGROUND_ACTION);
startService(i);
bindService(i,mServiceConnection,Context.BIND_AUTO_CREATE);
}
#Override
protected void onStop() {
super.onStop();
if(mServiceBound){
unbindService(mServiceConnection);
mServiceBound=false;
}
}
#Override
protected void onResume() {
super.onResume();
LocalBroadcastManager.getInstance(this).registerReceiver(mMessageReceiver,new IntentFilter("changePlayButton"));
}
#Override
protected void onPause() {
super.onPause();
LocalBroadcastManager.getInstance(this).unregisterReceiver(mMessageReceiver);
}
public static void flipPlayPauseButton(boolean isPlaying){
if(isPlaying){
playPauseButton.setImageResource(android.R.drawable.ic_media_pause);
}
else{
playPauseButton.setImageResource(android.R.drawable.ic_media_play);
}
}
#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);
}
}
(3). PlayerService.java
public class PlayerService extends Service {
MediaPlayer mediaPlayer=new MediaPlayer();
private final IBinder mBinder=new MyBinder();
public class MyBinder extends Binder
{
PlayerService getService()
{
return PlayerService.this;
}
}
public PlayerService()
{
}
#Override
public int onStartCommand(Intent intent, int flags, int startId)
{
if(intent.getStringArrayExtra("url")!=null)
playStream(intent.getStringExtra("url"));
if(intent.getAction().equals(Constants.ACTION.STARTFOREGROUND_ACTION))
{
Log.i("info","Start foregroung service");
showNotification();
}
else if(intent.getAction().equals(Constants.ACTION.PREV_ACTION))
{
Log.i("info","Prev pressed");
}
else if(intent.getAction().equals(Constants.ACTION.PLAY_ACTION))
{
Log.i("info","Play pressed");
}
else if(intent.getAction().equals(Constants.ACTION.NEXT_ACTION))
{
Log.i("info","Next pressed");
}
else if(intent.getAction().equals(Constants.ACTION.STARTFOREGROUND_ACTION))
{
Log.i("info","Stop foreground received");
stopForeground(true);
stopSelf();
}
return START_REDELIVER_INTENT;
}
private void showNotification()
{
Intent notificationIntent=new Intent(this,MainActivity.class);
notificationIntent.setAction(Constants.ACTION.MAIN_ACTION);
notificationIntent.setFlags((Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK));
PendingIntent pendingIntent=PendingIntent.getActivity(this,0,notificationIntent,0);
Intent previousIntent=new Intent(this,MainActivity.class);
previousIntent.setAction(Constants.ACTION.PREV_ACTION);
PendingIntent ppreviousIntent=PendingIntent.getActivity(this,0,previousIntent,0);
Intent playIntent=new Intent(this,MainActivity.class);
playIntent.setAction(Constants.ACTION.PLAY_ACTION);
PendingIntent pplayIntent=PendingIntent.getActivity(this,0,playIntent,0);
Intent nextIntent=new Intent(this,MainActivity.class);
nextIntent.setAction(Constants.ACTION.NEXT_ACTION);
PendingIntent pnextIntent=PendingIntent.getActivity(this,0,nextIntent,0);
Bitmap icon= BitmapFactory.decodeResource(getResources(),R.drawable.logo);
Notification notification=new NotificationCompat.Builder(this)
.setContentTitle("Music Player")
.setTicker("Playing music")
.setContentText("My Song")
.setSmallIcon(R.drawable.logo)
.setLargeIcon(Bitmap.createScaledBitmap(icon,128,128,false))
.setContentIntent(pendingIntent)
.setOngoing(true)
.addAction(android.R.drawable.ic_media_previous,"Previous",ppreviousIntent)
.addAction(android.R.drawable.ic_media_play,"Play",pplayIntent)
.addAction(android.R.drawable.ic_media_next,"Next",pnextIntent)
.build();
startForeground(Constants.NOTIFICATION_ID.FOREGROUND_SERVICE,notification);
}
#Override
public IBinder onBind(Intent intent)
{
return mBinder;
}
public void playStream(String url)
{
if(mediaPlayer!=null)
{
try
{
mediaPlayer.stop();
}
catch(Exception e)
{
}
mediaPlayer=null;
}
mediaPlayer=new MediaPlayer();
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
try
{
mediaPlayer.setDataSource(url);
mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener()
{
#Override
public void onPrepared(MediaPlayer mp)
{
playPlayer();
}
});
mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener()
{
#Override
public void onCompletion(MediaPlayer mp)
{
flipPlayPauseButton(false);
}
});
mediaPlayer.prepareAsync();
}
catch(IOException e)
{
e.printStackTrace();
}
}
public void pausePlayer()
{
try
{
mediaPlayer.pause();
flipPlayPauseButton(false);
}
catch(Exception e)
{
Log.d("EXCEPTION","failed to pause media player");
}
}
public void playPlayer()
{
try
{
mediaPlayer.start();
flipPlayPauseButton(true);
}
catch(Exception e)
{
Log.d("EXCEPTION","failed to pause media player");
}
}
public void flipPlayPauseButton(boolean isPlaying)
{
// code to communicate with main thread
Intent intent=new Intent("changePlayButton");
//add data
intent.putExtra("isPlaying",isPlaying);
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
}
public void togglePlayer()
{
try
{
if(mediaPlayer.isPlaying())
pausePlayer();
else
playPlayer();
}
catch(Exception e)
{
Log.d("Exception","failed to toggle media player");
}
}
}
(4). Player.java
public class Player {
MediaPlayer mediaPlayer=new MediaPlayer();
public static Player player;
String url="";
public Player()
{
this.player = this;
}
public void playStream(String url)
{
if(mediaPlayer!=null)
{
try
{
mediaPlayer.stop();
}
catch(Exception e)
{
}
mediaPlayer=null;
}
mediaPlayer=new MediaPlayer();
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
try
{
mediaPlayer.setDataSource(url);
mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener()
{
#Override
public void onPrepared(MediaPlayer mp)
{
playPlayer();
}
});
mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener()
{
#Override
public void onCompletion(MediaPlayer mp)
{
MainActivity.flipPlayPauseButton(false);
}
});
mediaPlayer.prepareAsync();
}
catch(IOException e)
{
e.printStackTrace();
}
}
public void pausePlayer()
{
try
{
mediaPlayer.pause();
MainActivity.flipPlayPauseButton(false);
}
catch(Exception e)
{
Log.d("EXCEPTION","failed to pause media player");
}
}
public void playPlayer()
{
try
{
mediaPlayer.start();
MainActivity.flipPlayPauseButton(true);
}
catch(Exception e)
{
Log.d("EXCEPTION","failed to pause media player");
}
}
public void togglePlayer()
{
try
{
if(mediaPlayer.isPlaying())
pausePlayer();
else
playPlayer();
}
catch(Exception e)
{
Log.d("Exception","failed to toggle media player");
}
}
}
(5). Constants.java
public class Constants {
public interface ACTION {
public static String MAIN_ACTION="com.music.zirakmistry.musicstreamingapp.action.main";
public static String PREV_ACTION="com.music.zirakmistry.musicstreamingapp.action.prev";
public static String PLAY_ACTION="com.music.zirakmistry.musicstreamingapp.action.play";
public static String NEXT_ACTION="com.music.zirakmistry.musicstreamingapp.action.next";
public static String STARTFOREGROUND_ACTION="com.music.zirakmistry.musicstreamingapp.action.startforeground";
public static String STOPFOREGROUND_ACTION="com.music.zirakmistry.musicstreamingapp.action.stopforeground";
}
public interface NOTIFICATION_ID
{
public static int FOREGROUND_SERVICE=101;
}
}
(6). AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.music.zirakmistry.musicstreamingapp">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity
android:name=".MainActivity"
android:label="#string/app_name"
android:theme="#style/AppTheme.NoActionBar"
android:launchMode="singleTask">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service
android:name=".PlayerService"
android:enabled="true"
android:exported="true" />
</application>
</manifest>
In order to facilitate the new feature called Notification Channels in Android Oreo the previous method was deprecated.
Notification Channels allow us to group notifications based on their intended behavior. So whenever a user don't need to see a specific type of notification they can disable the corresponding channel.
So for example consider an e-commerce app. It shows notifications for promotions/offers, order status, etc. Promotion and offer notifications are grouped into a channel named "promotion". So if the user don't want to see only these notifications they can disable the "promotion" channel from the app settings.
If you use the deprecated method, the notification will fail silently in Oreo. To make it work, use the new Builder constructor. Change your code as below:
Notification notification=new NotificationCompat.Builder(this, CHANNEL_ID)
// set title, message, etc.
.build();
And create a notification channel like this for Oreo:
NotificationManager manager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
// Support for Android Oreo: Notification Channels
NotificationChannel channel = new NotificationChannel(
CHANNEL_ID,
"Channel_name_to_be_displayed_in_Settings",
NotificationManager.IMPORTANCE_DEFAULT);
manager.createNotificationChannel(channel);
}
i need to close and activity and start another only when the user presses back twice. I am using this code
#Override
public void onBackPressed() {
if (doubleBackToExitPressedOnce) {
Log.e("Entering","Yes");
DatabaseHandler db=new DatabaseHandler(AddBreakfastActivity.this);
db.deleteTodaysUnsavedMenu(Integer.parseInt(newDay),Integer.parseInt(newIntMonth));
Intent intent=new Intent(AddBreakfastActivity.this,ProvidersUpdateActivity.class);
startActivity(intent);
finish();
}
else {
this.doubleBackToExitPressedOnce = true;
Log.e("BOOLEANVALUE", String.valueOf(doubleBackToExitPressedOnce));
Toast.makeText(this, "Please click BACK again to exit", Toast.LENGTH_SHORT).show();
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
doubleBackToExitPressedOnce = false;
}
}, 2000);
}
}
On pressing back once the app exits and shows the Toast message.
It doesnt wait for the second press. How can i resolve this?
Thank you.
EDIT
Found it to be working as expected when the back button is pressed. However shows aforesaid issue when called from
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if(id==android.R.id.home){
onBackPressed();
}
}
you can also do this with on keydown event as code below remove backpressed
#Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
// TODO Auto-generated method stub
if(event.getAction()==KeyEvent.ACTION_DOWN && keyCode==KeyEvent.KEYCODE_BACK)
{
if (doubleBackToExitPressedOnce) {
Log.e("Entering","Yes");
DatabaseHandler db=new DatabaseHandler(AddBreakfastActivity.this);
db.deleteTodaysUnsavedMenu(Integer.parseInt(newDay),Integer.parseInt(newIntMonth));
Intent intent=new Intent(AddBreakfastActivity.this,ProvidersUpdateActivity.class);
startActivity(intent);
finish();
}
else {
this.doubleBackToExitPressedOnce = true;
Log.e("BOOLEANVALUE", String.valueOf(doubleBackToExitPressedOnce));
Toast.makeText(this, "Please click BACK again to exit", Toast.LENGTH_SHORT).show();
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
doubleBackToExitPressedOnce = false;
}
}, 2000);
return false;
}
}
return super.onKeyDown(keyCode, event);
}
Here's an example of "Press Twice to Exit" with fragments:
boolean doublePressToQuit = false;
#Override
public void onBackPressed() {
if (getSupportFragmentManager().getBackStackEntryCount() > 0) {
getSupportFragmentManager().popBackStack();
} else {
if (doublePressToQuit) {
DashBoardActivity.this.finish();
} else {
this.doublePressToQuit = true;
Toast.makeText(this, getString(R.string.quit_notification), Toast.LENGTH_SHORT).show();
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
doublePressToQuit = false;
}
}, 2000);
}
}
}
Include super.onBackPressed(); inside your IF statement to override the onBackPressed() event.
Try the below code, it works for me
boolean firstBackPressed = false;
.
.
.
#Override
public void onBackPressed() {
if (!firstBackPressed) {
firstBackPressed = true;
Toast.makeText(MainMenu.this, "Press back again to exit", Toast.LENGTH_SHORT).show();
} else {
super.onBackPressed();
}
}
Please find this
private boolean isShownExit;
#Override
public void onBackPressed() {
if (drawerLayout.isDrawerOpen(Gravity.LEFT)) {
drawerLayout.closeDrawer(Gravity.LEFT);
isShownExit = false;
return;
} else {
if (getSupportFragmentManager().getBackStackEntryCount() == 1) {
if (!isShownExit) {
isShownExit = true;
showToast(this, "Press again to exit");
} else {
hideSoftKeyboardDialogDismiss(this);
startAnotherActivityHereWhichDoYouwant();
}
} else {
getSupportFragmentManager().popBackStack();
}
}
}
This question already has answers here:
What is a NullPointerException, and how do I fix it?
(12 answers)
Closed 8 years ago.
I have been trying to create a basic flashlight app using an image button (beginner). Where i have no syntax errors in the code but do have have some NULL pointer exception in the run time.
Here is my main activity class :-
public class FlashLight extends Activity{
Camera camera = null;
Parameters params = null;
boolean isFlashOn = false;
boolean hasFlash;
ImageButton btnSwitch = (ImageButton) findViewById(R.id.imageButton1);
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
hasFlash = getApplicationContext().getPackageManager()
.hasSystemFeature(PackageManager.FEATURE_CAMERA_FLASH);
if(!hasFlash)
{
AlertDialog alert = new AlertDialog.Builder(FlashLight.this).create();
alert.setTitle("Error");
alert.setMessage("Application Not Supported");
alert.setButton("OK", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
// closing the application
finish();
}
});
return;
}
// get the camera
getCamera();
// displaying button image
toggleButtonImage();
// Switch button click event to toggle flash on/off
btnSwitch.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (isFlashOn) {
// turn off flash
turnOffFlash();
} else {
// turn on flash
turnOnFlash();
}
}
});
}
private void getCamera() {
if(camera == null)
{
try{
camera = Camera.open();
params = camera.getParameters();
}
catch (RuntimeException e) {
Log.e("Camera Error. Failed to Open. Error: ", e.getMessage());
}
}
}
private void toggleButtonImage() {
try{
if(isFlashOn){
btnSwitch.setImageResource(R.drawable.switchon);
}else{
btnSwitch.setImageResource(R.drawable.switchoff);
}
}
catch(RuntimeException e){
Log.e("Could not toggle Button image ", e.getMessage());
}
}
private void turnOnFlash() {
try{
if (!isFlashOn) {
if (camera == null || params == null) {
return;
}
params = camera.getParameters();
params.setFlashMode(Parameters.FLASH_MODE_TORCH);
camera.setParameters(params);
camera.startPreview();
isFlashOn = true;
// changing button/switch image
toggleButtonImage();
}
}
catch(RuntimeException e){
Log.e("Could not turn on Flash ", e.getMessage());
}
}
private void turnOffFlash() {
try{
if (isFlashOn) {
if (camera == null || params == null) {
return;
}
params = camera.getParameters();
params.setFlashMode(Parameters.FLASH_MODE_OFF);
camera.setParameters(params);
camera.stopPreview();
isFlashOn = false;
// changing button/switch image
toggleButtonImage();
}
}
catch(RuntimeException e){
Log.e("Could not turn off flash ", e.getMessage());
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.flash_light, 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();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
#Override
protected void onDestroy() {
super.onDestroy();
}
#Override
protected void onPause() {
super.onPause();
// on pause turn off the flash
turnOffFlash();
}
#Override
protected void onRestart() {
super.onRestart();
}
#Override
protected void onResume() {
super.onResume();
// on resume turn on the flash
if(hasFlash)
turnOnFlash();
}
#Override
protected void onStart() {
super.onStart();
// on starting the app get the camera params
getCamera();
}
#Override
protected void onStop() {
super.onStop();
// on stop release the camera
if (camera != null) {
camera.release();
camera = null;
}
}
}
while here is my manifest file :-
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.flashlight"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="14" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-feature android:name="android.hardware.camera" />
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity
android:name="FlashLight"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
Please, help in the identification of the following error in the logcat menu:-
02-10 23:18:23.409: E/AndroidRuntime(13237): java.lang.RuntimeException: Unable to instantiate activity ComponentInfo{com.example.flashlight/com.example.flashlight.FlashLight}: java.lang.NullPointerException
ImageButton btnSwitch gives you NULL Pointer, you don't have
setContentView(R.layout.name_of_your_activity);
Change this and it will work:
Camera camera = null;
Camera.Parameters params = null;
boolean isFlashOn = false;
boolean hasFlash;
ImageButton btnSwitch; //add this
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.name_of_your_xml_layout_for_activity);//add this
btnSwitch=(ImageButton)findViewById(R.id.imageButton1);//add this
hasFlash = getApplicationContext().getPackageManager()
.hasSystemFeature(PackageManager.FEATURE_CAMERA_FLASH);...
below is my code for media player. It doesn't start again after I stop. How to solve this? Even though I have called the prepare method before calling the start method. Also why doesn't the music stop playing even after I exit the programme. Please advice.
public class MainActivity extends Activity {
Button play,pause,stop;
CheckBox c1,c2,c3;
MediaPlayer song1,song2,song3;
AlertDialog.Builder builder;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
play=(Button)findViewById(R.id.button1);
pause=(Button)findViewById(R.id.button2);
stop=(Button)findViewById(R.id.button3);
c1=(CheckBox)findViewById(R.id.checkBox1);
c2=(CheckBox)findViewById(R.id.checkBox2);
c3=(CheckBox)findViewById(R.id.checkBox3);
song1=MediaPlayer.create(this, R.raw.finalcountdown);
song2=MediaPlayer.create(this, R.raw.invincible);
song3=MediaPlayer.create(this, R.raw.somewhereibelong);
builder=new AlertDialog.Builder(this);
}
#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;
}
public void start(View view) throws IllegalStateException, IOException
{
if(c1.isChecked())
{
if(!song1.isPlaying())
{
song1.prepare();
song1.start();
}
else{
song1.start();
}
}
if(c2.isChecked())
{
if(!song2.isPlaying())
{
song2.prepare();
song2.start();
}
else{
song2.start();
}
}
if(c3.isChecked())
{
if(!song3.isPlaying())
{
song3.prepare();
song3.start();
}
else{
song3.start();
}
}
else{
builder.setMessage("Please mark a checkbox");
}
}
public void stop(View view)
{
if(c1.isChecked())
song1.stop();
else if (c2.isChecked())
song2.stop();
else if (c3.isChecked())
song3.stop();
else
builder.setMessage("Error message ");
}
public void pause(View view)
{
if(c1.isChecked())
{
song1.pause();
}
else if(c2.isChecked())
{
song2.pause();
}
else if(c3.isChecked())
{
song3.pause();
}
else
builder.setMessage("error message");
}
}
you need to put song1.release() and release methods for other songs inside the stop method. Refer the life cycle of media player for further info.
http://developer.android.com/reference/android/media/MediaPlayer.html
You have to release the player OnPause or OnDestroy method.
#Override
public void onDestroy() {
if(c1!= null)c1.release();
else if (c2!= null)c2.release();
else if (c3!= null)c3.release();
else
//something
}