I`m trying to build an app, and one activity is "Radio" where I have a streaming online Radio. If i click play, everything works fine, it plays, when I click stop, it stops. But the problem is when I change the activity, ex: from "Radio" to "Home", or "Contact" and come back to "Radio", radio still runs, and if I want to stop it, doesn't work. but if I hit play, the music duplicates and therefore I have the same radio open two times. It looks like the application doesn't know that Radio already runs. Do I need a service object, or what? If I need a service can someone explain me where exactly in the code should I implement it? Here is my Java code:
public class radioActivity extends AppCompatActivity {
int length;
Button b1;
private Button Button1;
private Button Button2;
private String STREAM_URL = "http://192.99.35.93:6370/;stream.mp3";
private MediaPlayer mPlayer;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_radio);
Button button1 = (Button) findViewById(R.id.buttonpredica1);
Button button2 = (Button) findViewById(R.id.buttonpredica2);
mPlayer = new MediaPlayer();
mPlayer.setWakeMode(getApplicationContext(), PowerManager.PARTIAL_WAKE_LOCK);
WifiManager.WifiLock wifiLock = ((WifiManager) getSystemService(Context.WIFI_SERVICE))
.createWifiLock(WifiManager.WIFI_MODE_FULL, "mylock");
wifiLock.acquire();
wifiLock.release();
button1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
try {
mPlayer.reset();
mPlayer.setDataSource(STREAM_URL);
mPlayer.prepareAsync();
mPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mPlayer) {
mPlayer.start();
}
});
} catch (IOException e) {
e.printStackTrace();
}
}
});
button2.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
mPlayer.stop();
}
});
Your MediaPlayer is being created each time you click on start button, so multiple instance of MediaPlayer are playing Radio
If you dont want your MediaPlayer to be running when you switch Activities you can call mPlayer.stop(); in onPause() of your Activity
You can have a couple of options here, one would be to create a Singleton Instance of your MediaPlayer object so when you go to and fro from your RadioActivity, the same instance of the MediaPlayer Object is being used which will help you control the MediaPlayer
Singleton design pattern in Java. Singleton Pattern says that just"define a class that has only one instance and provides a global point of access to it". In other words, a class must ensure that only single instance should be created and single object can be used by all other classes.
Related
In Android Studio, I am trying to open the second activity when corresponding button is pressed.However, I cannot reach that listener that I create in "onCreate" from onPause. I am following an approach like this:
public class MainActivity extends Activity {
private View.OnClickListener openSecondPage = new View.OnClickListener() {
#Override
public void onClick(View v) {
Button button_newPage = findViewById(R.id.button_newpage);
button_newPage.setText("Clicked");
Intent secondPage = new Intent(getApplicationContext(), SecondActivity.class );
startActivity(secondPage);
}
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button button_newPage = findViewById(R.id.button_newpage);
button_newPage.setOnClickListener(openSecondPage);
}
public void onPause(){
super.onPause();
Button button_newPage = findViewById(R.id.button_newpage);
//Destroy the on click listener
button_newPage.setOnClickListener(null);
}
}
Also user will be able to come back to main activity and then go back to the second activity again. In that case I don't want to open a new activity. Instead I want to open previously created activity. For that case should I create a onResume() method and in that, call startActivity(secondPage). But in that case, since the secondPage is declared in onStart I won't be able to use in onResume. How can I handle that situation?
So there are actually 2 questions.. sorry about that, I didn't want to open 2 different questions for it.
Put Button button_newPage = findViewById(R.id.button_newpage); and button_newPage.setOnClickListener(openSecondPage); inside onResume instead of onCreate, like so:
#Override
protected void onResume() {
super.onResume();
Button button_newPage = findViewById(R.id.button_newpage);
button_newPage.setOnClickListener(openSecondPage);
}
That should solve at least part of your problem.
I have successfully implemented a custom Dialog box that appears when the user tries to leave an activity via a back button or by using onBackPressed(). They can simply cancel the dialog box or continue, and leave the activity. This function has been implemented in multiple activities, however its making my code a lot longer than it needs to be. I wanted to know how to create a util that can be referenced in different activities, without the need for the chunk of code to copy pasted multiple times. Please note that I am retrieving the dialog title and description from string.xml
This is my code:
Dialog customDialog;
Button button_one, button_two;
TextView dialog_title, dialog_description;
customDialog = new Dialog(this);
//Back button will close app
#Override
public void onBackPressed() {
customDialog.setContentView(R.layout.custom_dialog_box);
dialog_title = customDialog.findViewById(R.id.dialog_title);
dialog_title.setText(getString(R.string.leaving_activity_warning_title));
dialog_description = customDialog.findViewById(R.id.dialog_description); dialog_description.setText(getString(R.string.leaving_activity_warning_description));
button_one = customDialog.findViewById(R.id.button_one);
button_one.setText(getString(R.string.cancel));
button_two = customDialog.findViewById(R.id.button_two);
button_two.setText(getString(R.string.leave_anyway));
button_one.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
customDialog.dismiss();
}
});
button_two.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
customDialog.dismiss();
finish();
overridePendingTransition(R.anim.slide_in_left, R.anim.slide_out_right);
}
});
Objects.requireNonNull(customDialog.getWindow()).setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
customDialog.show();
}
UPDATE
Created a Java file called "DialogBoxMessage"
DialogBoxMessage Code:
class DialogBoxMessage {
private Dialog customDialog;
private TextView dialog_title, dialog_description;
private Button button_one, button_two;
//Custom Dialog Box Initialization
DialogBoxMessage(Button myButtonOne, TextView myDialogTitle, TextView myDialogDescription, Dialog myCustomDialog) {
customDialog = myCustomDialog;
button_one = myButtonOne;
button_two = myButtonOne;
dialog_title = myDialogTitle;
dialog_description = myDialogDescription;
}
void leaveActivity() {
customDialog.setContentView(R.layout.custom_dialog_box);
dialog_title = customDialog.findViewById(R.id.dialog_title);
dialog_title.setText(Resources.getSystem().getString(R.string.leaving_activity_warning_title));
dialog_description = customDialog.findViewById(R.id.dialog_description);
dialog_description.setText(Resources.getSystem().getString(R.string.leaving_activity_warning_description));
button_one = customDialog.findViewById(R.id.button_one);
button_one.setText(Resources.getSystem().getString(R.string.cancel));
button_two = customDialog.findViewById(R.id.button_two);
button_two.setText(Resources.getSystem().getString(R.string.leave_anyway));
button_one.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
customDialog.dismiss();
}
});
button_two.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
customDialog.dismiss();
}
});
Objects.requireNonNull(customDialog.getWindow()).setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
customDialog.show();
}
}
I input the following code in another activity
Other activity code:
//Reusable exit dialog message
DialogBoxMessage dialogBoxMessage;
//Back button will close app
#Override
public void onBackPressed() {
dialogBoxMessage.leaveActivity();
finish();
}
But it doesn't seem to work, I think there are a lot of issues... please help :(
I assume customDialog is a seperate class you wrote - therefore i would suggest you put main information like contentview, title, message or type in the constructor when you initialize ur Dialog.
For your onClick Method I suggest you create an Interface to handle Button Clicks in your
customDialog class.
This could be implemented as a static method in a utilities class. The method would require 'this' as a parameter, which contains the activity context. The method should return the result of the button press. The activity can use this response to determine if finish() should be called or not.
UPDATE
I had suggested a simple static method, but you've gone down the object-oriented route. That's fine.
However, your constructor requires passing in several views, which wouldn't appear to achieve the code efficiency you are after.
Your constructor should just require the Activity context; everything else is encapsulated in your new class.
In each Activity's onBackPressed method you will need to create the object with
dialogBoxMessage = new DialogBoxMessage(this);
before you can call any of that object's methods.
Always in my apps I added buttons in void onCreate, but now I'm trying to do app with more buttons (about 10). I would like to all buttons active on start app.
In my opinion it is too much buttons to add in this onCreate and app will be starting to long.
I tried to put this:
myButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
myMethod();
}
})
out of onCreate
but AndroidStudio underlines setOnClickListener and view
I don't have ideas, how and where can i add button out of onCreate.
If you don't want to overcrowd your oncreate method, then create a clicklistener outside onCreate anywhere in activity and in onCreate just set it.
onCreate :
edit_a_member = (Button) findViewById(R.id.edit_member);
delete_a_member = (Button) findViewById(R.id.delete_member);
edit_a_member.setOnClickListener(handleClick);
delete_a_member.setOnClickListener(handleClick);
clickListener:
private View.OnClickListener handleClick = new View.OnClickListener() {
#Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.edit_member:
member_selected = EDIT_MEMBER_SELECTED;
callDialog();
break;
case R.id.delete_member:
callDeleteAlert();
break;
}
}
};
You can simply add a separate method for your buttons in the same class, e.g.:
public void onCreate(...){
//Standard setup of views or whatever you want to do here
this.addButtons();
}
private void addButtons(){
Button b1 = new Button("Hi");
b1.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
myMethod();
}
});
Button b2 = new Button("Hi to you too");
b2.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
myMethod();
}
});
}
This is an example. You can do this in soooo many ways. I feel like you should thoroughly learn Java's fundamental Object Oriented programming, because that's really what your question suggests you don't understand. Go follow a youtube tutorial. I always like "The New Boston"'s Java tutorial series on youtube.
PS: You can make code like this beautiful under the 'Words of wisdom': Don't repeat yourself
If you have to do a lot of work in your onCreate but you are worried that the UI will take too long to load you can always post a delayed runnable to a handler so in the onCreate method put :
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
//add your code here
}
},10);
what this will do is your UI will load then the code in your Runnable will be executed 10 milliseconds after your UI loads thus your app will not take too long to load the UI, even though in your case I doubt it would be necessary.
If you are declaring the buttons in xml file :
Add these properties in each button Declaration in your Xml :
android:clickable="true"
android:onClick="onClick"
And now in Activity Class create a method like this :
public void onClick(View v){
switch(v.getId){
case R.id.{buttons_id_in_xml}
(Your Code)
break;
(Like for others)
}
}
If you want to add buttons dynamically :
Create a method to add the button like this:
void addButton(String buttonName, int button id){
Button button = new Button(this);
button.setText("Push Me");
(add it to parent Layout of xml)
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
switch(id){
case id1:
(handle )
break;
(like for others)
}
}
});
}
The best way to do this is:
add implements View.OnClickListener to
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
// declare variables
private Button mBtn1;
private Button mBtn2;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_start);
// make an instance to the btns
mBtn1 = findViewById(R.id.btn1);
mBtn2 = findViewById(R.id.btn2);
// set onClickListener
mBtn1.setOnClickListener(this); // with "this" you are passing the view
mBtn2.setOnClickListener(this);
}
// implement onClick
#Override
public void onClick(View view) {
// check which btn was clicked by id
switch (view.getId()) {
case R.id.btn1:
btn1Clicked();
break;
case R.id.btn2:
btn2Clicked();
break;
}
}
private void btn1Clicked() {
// your code btn1 clicked
}
private void btn2Clicked() {
// your code btn2 clicked
}
Hope this helped. Cheers!
I have spent almost the day trying to figure it out and yet could not manage to achieve it. I basically have two activities, MainActivity.java and GameActivity.java. The music stops but after going back to MainActivity.java and coming back to GameActivity.java using ImageView several times.
MainActivity.java
public class MainActivity extends AppCompatActivity {
ImageView iv;
public static final String BG_SOUND_CHECK = "background playing!";
// public static MediaPlayer backgroundSound;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final Handler handler = new Handler();
final MediaPlayer backgroundSound = MediaPlayer.create(this, R.raw.background_music);
handler.postDelayed(new Runnable() {
#Override
public void run() {
backgroundSound.setLooping(true);
backgroundSound.start();
Log.v(BG_SOUND_CHECK, "After loop Started!");
}
}, 3000);
getSupportActionBar().hide();
iv = (ImageView)findViewById(R.id.playImage);
iv.setOnClickListener(new View.OnClickListener(){
public void onClick(View view1){
// backgroundSound.setLooping(false);
backgroundSound.pause();
// Log.v(BG_SOUND_CHECK, "Playing After Play Button Click");
Intent myIntent = new Intent(MainActivity.this, GameActivity.class);
// myIntent.putExtra("backgroundSoundObj",backgroundSound);
startActivity(myIntent);
// Log.v(BG_SOUND_CHECK, "After Game Scene");
}
});
}
}
GameActivity.java
public class GameActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_game);
// MainActivity.backgroundSound.pause();
// Rest of the code
}
}
I tried putting the music onPause(); in
1) ImageView onClick();
2) As soon as the GameActivity.java is loaded
but both ways end up pausing it only after I try coming back to MainActivity.java and going to GameActivity.java several times.
Do you see how you put your backgroundSound.start() inside the postDelayed-3000 ?
backgroundSound.pause() anytime before that 3000ms is not going to do anything.
It has nothing to do with going back and forth between your two activities, it just so happens that doing that takes up more than 3000ms, so when you do click for pause(), 3000ms has passed.
What you can do, to fit your current code, is to separate that into a Runnable.
Runnable bgSound = new Runnable() {
#Override
public void run() {
backgroundSound.setLooping(true);
backgroundSound.start();
Log.v(BG_SOUND_CHECK, "After loop Started!");
}
}
Use it with handler.postDelayed(bgSound, 3000)
In your onClick, if you want to stop it from playing before it starts, can use handler.removeCallbacks(bgSound), to stop it after it plays, your pause(). If you don't care to know if it has or hasn't started, you can do both alongside each other, should work fine too.
(if you don't want the music to play after you've left your main activity, you should also do the same actions in your onDestroy and/or onPause)
Here in my MainActivity.java I have an object MediaPlayer, which plays a sound when you click playB button and pause by pressing pauseB. Everything is working fine. But if you re-open the app and click pauseB, the sound continues to play. How to fix it? How to catch the current playing MediaPlayer?
public class MainActivity extends ActionBarActivity {
Button playB;
Button pauseB;
Context c;
MediaPlayer mp;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final Button playB = (Button) findViewById(R.id.playB);
Button pauseB = (Button) findViewById(R.id.pauseB);
mp = mp.create(this, R.raw.fawaid_1);
playB.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
mp.start();
}
});
pauseB.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
mp.pause();
}
});
}
}
when you re-open the app, onCreate is called again, hence you have a new MediaPlayer object, and from that moment, play and pause buttons will control that new player object instead of a previous one. That's why your pause button will have no effect on the sound that started BEFORE you minimized the app. And if you press play button now, you will have two sounds playing at the same time
one way to overcome this, is to check if media player has already been initialized:
if(mp==null)
mp = MediaPlayer.create(this, R.raw.fawaid_1);
It is advisable to use Service with AIDL in developing music player.
Reasons.
You can retain the control again once you go back in your activity.
It is easy to perform an inter process communication.
Here is a simple music Player that runs on the Background, Music Player
The song I used in this music player is Owned by SnowFlakes