I successfully implemented AdMob interstitial ads into my application but the only problem is that they are not clickable.
Here is my AdMob.java class:
import android.app.Activity;
import com.google.android.gms.ads.AdListener;
import com.google.android.gms.ads.AdRequest;
import com.google.android.gms.ads.InterstitialAd;
public class Admob extends AdListener{
private Activity ctx;
//Admob
private InterstitialAd interstitial;
private AdRequest adRequest;
private String unitId;
public static boolean fromAdmob = false;
public Admob(Activity ctx, String unitId)
{
this.ctx = ctx;
this.unitId = unitId;
try{
this.interstitial = new InterstitialAd(this.ctx);
interstitial.setAdUnitId(unitId);
interstitial.setAdListener(this);
adRequest = new AdRequest.Builder().build();
}
catch (Exception e){
e.printStackTrace();
}
}
public void loadAd()
{
try{
interstitial.loadAd(adRequest);
}
catch (Exception e){
e.printStackTrace();
}
}
#Override
public void onAdLoaded() {
try{
fromAdmob = true;
interstitial.show();
}
catch (Exception e){
e.printStackTrace();
}
}
#Override
public void onAdFailedToLoad(int errorCode)
{
}
#Override
public void onAdClosed() {
fromAdmob = false;
}
}
And the MainPageActivity.java file:
public class MainPageActivity extends Activity implements IGameListener, IEventDelegate{
//Tags
private static final String TAG = "bubblesMainPage";
//Context
public static Activity instance;
//Media
private MediaPlayer mp;
//Ads
private Admob admob;
//TapSDK
private Tap tap;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_page_activity);
overridePendingTransition(R.anim.fade_in, R.anim.fade_out);
tr
Tap.establish(this);
tap = new Tap(this, "xxxx");
}
catch (Exception e){
e.printStackTrace();
}
//Admob
this.admob = new Admob(this, "ADMOB_ID");
//Context
instance = this;
//Media
mp = MediaPlayer.create(getApplicationContext(), R.raw.background_music);
mp.setLooping(true);
//Set activity properties
try {
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON, WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
} catch (Exception e) {
e.printStackTrace();
}
//Intents & Listeners
final Intent gamePlayActivity = new Intent(this, BubbleShooterActivity.class);
BubbleShooterActivity.listener = this;
//Animations
Animation scaleUpAnim = AnimationUtils.loadAnimation(getApplicationContext(), R.anim.scale_up);
findViewById(R.id.play_button).startAnimation(scaleUpAnim);
//UI Events
findViewById(R.id.play_button).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
new Thread(new Runnable() {
#Override
public void run() {
try {
startActivity(gamePlayActivity);
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
}
});
findViewById(R.id.more_games_button).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
tap.showMoreGamesWithViewControllerAndAppID((IEventDelegate)instance);
}
});
}
/*
Game methods - start
*/
#Override
public void onGameStart() {
Log.i(TAG, "onGameStart");
}
#Override
public void onLevelFailed() {
//Level failed window
try{
Intent i = new Intent(this, LostActivity.class);
startActivity(i);
}
catch (Exception e){
e.printStackTrace();
}
Log.i(TAG, "onLevelFailed");
}
#Override
public void onLevelUp() {
Log.i(TAG, "onLevelUp");
if(admob != null){
runOnUiThread(new Runnable() {
#Override
public void run() {
try{
admob.loadAd();
}
catch (Exception e){
e.printStackTrace();
}
try{
Intent i = new Intent(instance, WonActivity.class);
startActivity(i);
}
catch (Exception e){
e.printStackTrace();
}
}
});
}
}
#Override
public void onGameEnd() {
Log.i(TAG, "onGameEnd");
}
/*
TapSDK methods - start
*/
#Override
public void viewDidAppear() {
Log.i(TAG, "TapSDK: viewDidAppear");
}
#Override
public void viewDidDisappear() {
Log.i(TAG, "TapSDK: viewDidDisappear");
}
#Override
public void viewConnectFail(String s) {
Log.i(TAG, "TapSDK: viewConnectFail " + s);
}
#Override
public void conversion() {
Log.i(TAG, "TapSDK: conversion");
}
#Override
public void onOfferComplete(int score) {
Log.i(TAG, "TapSDK: onOfferComplete " + score);
}
/*
Activity methods start
*/
#Override
public void onBackPressed() {
Log.i(TAG, "onBackPressed");
try{
Intent exitScreen = new Intent(this, ExitActivity.class);
startActivity(exitScreen);
}
catch (Exception e){
e.printStackTrace();
Log.e(TAG, "onBackPressed: " + e.getMessage());
}
}
#Override
protected void onStart() {
super.onStart();
// Monitor launch times and interval from installation
RateThisApp.onStart(this);
// If the criteria is satisfied, "Rate this app" dialog will be shown
RateThisApp.showRateDialogIfNeeded(this);
}
#Override
protected void onResume()
{
super.onResume();
if(tap != null)
tap.onResume();
mp.seekTo(0);
mp.start();
}
#Override
protected void onPause()
{
if(tap != null)
tap.onPause();
mp.pause();
super.onPause();
}
#Override
protected void onDestroy()
{
mp.stop();
mp = null;
if(tap != null)
tap.onDestroy();
super.onDestroy();
}
}
I couldn't figure out how to show the interstitial ad when the user levels up and presses the play button (which will lead him to the next level). The interstitial ad show up when he presses the home button which will take him to the MainActivity screen.
Can someone help me to make the ads clickable? Also, any suggestions on how to add the interstitial ad after each completed level? When someone has finished a level and presses the play button, an interstitial ad should appear and when that is closed he should be able to play the next level.
I really appreciate your help!
A number of issues:
Don't call interstitial.show() from onAdLoaded. Call show() when the user presses the play button for your next level (but only if an ad is available).
Get rid of public static Activity instance; Never hold a static reference to an Activity. You will just leak context everywhere.
Instead of calling admob.loadAd() from onLevelUp() call it as soon as you create your Activity (it takes times to load an ad from the network). NB you don't need to call it from runOnUIThread()
Call admob.loadAd() again after each time you show the ad to the user.
Related
I am not sure where I have missed something, I expect the playPauseButton to respond when I click it but nothing happens when I do. I have noticed some errors in my debug console log, which are mostly related to mediaPlayer, but I don't exactly know what they mean, since an quite new to android programming! Below is my debug console log, and a bit of related code:
// Removed Logcat!!
Some code related from a class Player.java:
import android.media.MediaPlayer;
import android.media.AudioManager;
import android.util.Log;
import java.io.IOException;
public class Player {
// Creating new MediaPlayer
MediaPlayer mediaPlayer = new MediaPlayer();
// Creating a public static player as reference to this Player class
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) {
}
// Releasing everything from the mediaPlayer
mediaPlayer = null;
}
// Creating new Media Player
mediaPlayer = new MediaPlayer();
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
// Try & Catch errors
try {
mediaPlayer.setDataSource(url);
mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mp) {
mediaPlayer.start();
}
});
mediaPlayer.prepareAsync();
} catch (IOException e) {
e.printStackTrace();
}
}
public void pausePlayer () {
try {
mediaPlayer.pause();
} catch (Exception e) {
Log.d("EXCEPTION", "Failed to pause Media Player");
}
}
public void playPlayer () {
try {
mediaPlayer.start();
} catch (Exception e) {
Log.d("EXCEPTION", "Failed to start Media Player");
}
}
public void togglePlayer () {
try {
if (mediaPlayer.isPlaying())
pausePlayer();
else
playPlayer();
} catch (Exception e) {
Log.d("Exception", "Failed to toggle Media Player");
}
}
}
the other related code from MainActivity.java
public class MainActivity extends AppCompatActivity {
static FloatingActionButton playPauseButton;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
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) {
}
});
// Songs location on our server
String url = // "*My website/file.mp3";
// Passing above url to our MediaPlayer
if (Player.player == null)
new Player();
Player.player.playStream(url);
}
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);
}
}
Try for example:
playPauseButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if(video.isplaying()){pause function()}
else{play function()}
}
});
Okay, I'd like to thank MohammadMoeinGolchin, who has helped me figure this out. It so happen's that I did not complete my function inside of my public void onClik(View view) function. But you will see that is is written somewhere in a separate Player.java class. So to resolve this, what I did instead, is to call the togglePlayer() function inside my onClick(View view) like this:
#Override
public void onClick (View view) {
Player.player.togglePlayer();
}
So basically, i got a list view that shows a list of bands.
When i press on one of the bands in the list, it creates a band profile page via an adapter.
In this layout, i got a play button, which starts a MediaPlayer service and play a song.
So far, so good.
The problem is, im trying to update the seekBar, located in the band profile page (created by the adapter mentioned above), from the MediaPlayer service Java file, but i'm unable to reach it.
i'm trying to use :
LayoutInflater inflater = (LayoutInflater)getSystemService(LAYOUT_INFLATER_SERVICE);
View layout = inflater.inflate(R.layout.activity_singleband, null, false);
seekBar = (SeekBar) layout.findViewById(R.id.seekBarBand);
but it seems that it uses another "instance" of the view, and not the one i'm currently viewing.
Here is the full MusicService Java file:
public class MusicService extends Service {
SeekBar seekBar;
Handler handler;
Runnable runnable;
NotificationManager nMN;
TextView BandName;
String songLink;
String songName;
String bandName;
String SongPlaying="";
String BandPlaying="";
public static MediaPlayer mp;
public static Boolean mpState = true;
public static Boolean mpPause = false;
public static Boolean isPlaying = false;
#Override
public void onCreate() {
super.onCreate();
}
// Play Cycle for seekBar
public void PlayCycle(){
seekBar.setProgress(mp.getCurrentPosition());
if (mp.isPlaying()){
runnable = new Runnable() {
#Override
public void run() {
PlayCycle();
}
};
handler.postDelayed(runnable, 1000);
}
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
songLink = intent.getStringExtra("SongLink");
songName = intent.getStringExtra("SongName");
bandName = intent.getStringExtra("BandName");
LayoutInflater inflater = (LayoutInflater)getSystemService(LAYOUT_INFLATER_SERVICE);
View layout = inflater.inflate(R.layout.activity_singleband, null, false);
seekBar = (SeekBar) layout.findViewById(R.id.seekBarBand);
BandName = (TextView) layout.findViewById(R.id.singleBandNameView);
BandName.setText("Bla Bla");
System.out.print("Band Name : "+ BandName.getText() );
handler = new Handler();
seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
#Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean input) {
if (input){
mp.seekTo(progress);
}
}
#Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
#Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
});
if (isPlaying && !songName.equals(SongPlaying) && !BandPlaying.equals(bandName)) {
Stop();
mp = new MediaPlayer();
mp.setAudioStreamType(AudioManager.STREAM_MUSIC);
try {
Uri songUri = Uri.parse(songLink);
mp.setDataSource(getApplicationContext(), songUri);
SongPlaying = songName;
Toast.makeText(getApplicationContext(), "Please wait", Toast.LENGTH_SHORT).show();
isPlaying=true;
new prepare().execute();
}
catch (IOException e) {
e.printStackTrace();
}
}
else if (!isPlaying && !songName.equals(SongPlaying) && !BandPlaying.equals(bandName) ) {
mp = new MediaPlayer();
mp.setAudioStreamType(AudioManager.STREAM_MUSIC);
try {
Uri songUri = Uri.parse(songLink);
mp.setDataSource(getApplicationContext(), songUri);
SongPlaying = songName;
Toast.makeText(getApplicationContext(), "Please wait", Toast.LENGTH_SHORT).show();
new prepare().execute();
isPlaying=true;
}
catch (IOException e) {
e.printStackTrace();
}
}
else {
Toast.makeText(getApplicationContext(), "Song is Already Playing", Toast.LENGTH_SHORT).show();
}
return super.onStartCommand(intent, flags, startId);
}
#Override
public void onDestroy() {
super.onDestroy();
mp.release();
handler.removeCallbacks(runnable);
}
/// Permanent Notification
private void showNotification() {
nMN = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
Notification n = new Notification.Builder(this)
.setContentTitle(songName)
.setContentText(bandName)
.setSmallIcon(R.drawable.ic_bandcamp)
//.addAction(R.drawable.ic_play_arrow_black_24dp, "button1", new pause())
.setOngoing(true)
.build();
nMN.notify(1, n);
}
/// PREPARE SONG TO PLAY //
public class prepare extends AsyncTask {
#Override
protected Object doInBackground(Object[] objects) {
try {
mp.prepare();
PlayCycle();
seekBar.setMax(mp.getDuration());
mp.start();
SongPlaying = songName;
isPlaying=true;
showNotification(); // show notification
mp.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mp) {
Toast.makeText(getApplicationContext(),"Song Finished", Toast.LENGTH_LONG).show();
new stop().execute();
}
});
} catch (IOException io){ io.printStackTrace(); }
return null; }}
/// STOP PLAYING SONG //
public static void Stop()
{
mp.reset();
mp.release();
isPlaying=false;
}
public static class stop extends AsyncTask {
#Override
protected Object doInBackground(Object[] objects) {
try {
mp.reset();
mp.release();
isPlaying=false;
} catch (Exception io){ io.printStackTrace(); }
return null; }}
/// PAUSE PLAYING SONG//
public static class pause extends AsyncTask {
#Override
protected Object doInBackground(Object[] objects) {
try {
mp.pause(); }
catch (Exception io){ io.printStackTrace(); }
return null; }}
public static class start extends AsyncTask {
#Override
protected Object doInBackground(Object[] objects) {
try {
mp.start(); }
catch (Exception io){ io.printStackTrace(); }
return null; }}
#Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
throw new UnsupportedOperationException("Not yet implemented");
}
}
Would love to have some suggestions.
Thanks in advance.
Okey Firstly I suggest you to read more about Android Service classes. Secondly Do NOT place you visual components like a SeekBar or TextView in the Service because it doesn't make any sense. Service is just a background task and do not know about the UI. Since it's executed in the background you don't even need AsyncTask inside this so thirdly remove ALL AsyncTasks in your service and run their task like they don't need to be executed in the background.
So all what you have to do is create a Fragment/Activity for the UI, then bind your Fragment/Acitivity with your Service to communicate and update UI components.
The easiest way is make the Service a Singleton like it's done here:
public class MusicService extends Service {
private static MusicService instance = null;
public static MusicService getInstance() {
return instance;
}
Handler handler;
Runnable runnable;
NotificationManager nMN;
String songLink;
String songName;
String bandName;
String SongPlaying="";
String BandPlaying="";
public static MediaPlayer mp;
public static Boolean mpState = true;
public static Boolean mpPause = false;
public static Boolean isPlaying = false;
#Override
public void onCreate() {
instance = this;
super.onCreate();
}
// Play Cycle for seekBar
public void PlayCycle(){
seekBar.setProgress(mp.getCurrentPosition());
if (mp.isPlaying()){
runnable = new Runnable() {
#Override
public void run() {
PlayCycle();
}
};
handler.postDelayed(runnable, 1000);
}
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
songLink = intent.getStringExtra("SongLink");
songName = intent.getStringExtra("SongName");
bandName = intent.getStringExtra("BandName");
handler = new Handler();
if (isPlaying && !songName.equals(SongPlaying) && !BandPlaying.equals(bandName)) {
Stop();
mp = new MediaPlayer();
mp.setAudioStreamType(AudioManager.STREAM_MUSIC);
try {
Uri songUri = Uri.parse(songLink);
mp.setDataSource(getApplicationContext(), songUri);
SongPlaying = songName;
Toast.makeText(getApplicationContext(), "Please wait", Toast.LENGTH_SHORT).show();
isPlaying=true;
new prepare().execute();
}
catch (IOException e) {
e.printStackTrace();
}
}
else if (!isPlaying && !songName.equals(SongPlaying) && !BandPlaying.equals(bandName) ) {
mp = new MediaPlayer();
mp.setAudioStreamType(AudioManager.STREAM_MUSIC);
try {
Uri songUri = Uri.parse(songLink);
mp.setDataSource(getApplicationContext(), songUri);
SongPlaying = songName;
Toast.makeText(getApplicationContext(), "Please wait", Toast.LENGTH_SHORT).show();
new prepare().execute();
isPlaying=true;
}
catch (IOException e) {
e.printStackTrace();
}
}
else {
Toast.makeText(getApplicationContext(), "Song is Already Playing", Toast.LENGTH_SHORT).show();
}
return super.onStartCommand(intent, flags, startId);
}
#Override
public void onDestroy() {
super.onDestroy();
mp.release();
handler.removeCallbacks(runnable);
}
/// Permanent Notification
private void showNotification() {
nMN = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
Notification n = new Notification.Builder(this)
.setContentTitle(songName)
.setContentText(bandName)
.setSmallIcon(R.drawable.ic_bandcamp)
//.addAction(R.drawable.ic_play_arrow_black_24dp, "button1", new pause())
.setOngoing(true)
.build();
nMN.notify(1, n);
}
/// PREPARE SONG TO PLAY //
public class prepare extends AsyncTask {
#Override
protected Object doInBackground(Object[] objects) {
try {
mp.prepare();
PlayCycle();
seekBar.setMax(mp.getDuration());
mp.start();
SongPlaying = songName;
isPlaying=true;
showNotification(); // show notification
mp.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mp) {
Toast.makeText(getApplicationContext(),"Song Finished", Toast.LENGTH_LONG).show();
new stop().execute();
}
});
} catch (IOException io){ io.printStackTrace(); }
return null; }}
/// STOP PLAYING SONG //
public static void Stop()
{
mp.reset();
mp.release();
isPlaying=false;
}
public static class stop extends AsyncTask {
#Override
protected Object doInBackground(Object[] objects) {
try {
mp.reset();
mp.release();
isPlaying=false;
} catch (Exception io){ io.printStackTrace(); }
return null; }}
/// PAUSE PLAYING SONG//
public static class pause extends AsyncTask {
#Override
protected Object doInBackground(Object[] objects) {
try {
mp.pause(); }
catch (Exception io){ io.printStackTrace(); }
return null; }}
public static class start extends AsyncTask {
#Override
protected Object doInBackground(Object[] objects) {
try {
mp.start(); }
catch (Exception io){ io.printStackTrace(); }
return null; }}
#Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
// throw new UnsupportedOperationException("Not yet implemented");
return null;
}
i'm trying to play stream radio using Mediaplayer with MP1 as variable of Mediaplayer i want to play it in all Fragments app,expect one activity (ActivityOne) which is contains another Mediaplayer MP2 to play,so i want to stop MP1 when i'm in (ActivityOne) activity, and play MP2 , and when i return from (ActivityOne) i want to resume MP1, my big problem is the (ActivityOne) called when i click button which is exist in fragment
my code below works only in one direction :
when i return from (ActivityOne) activity, the music stops.
structure of the app : MainAcitivty > Fragment > ActivityOne
MainActivity.java
MediaPlayer MP1;
boolean prepared = false;
boolean started = false;
PlayerTask playerTask;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mediaPlayer = new MediaPlayer();
playerTask = new PlayerTask();
playerTask.execute(stream);
/**/
MusicButton = findViewById(R.id.toggleButton);
MusicButton.setVisibility(View.INVISIBLE);
MusicButton.setOnCheckedChangeListener(new OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (started && MusicButton.isChecked()) {
started = false;
MP1.pause();
MusicButton.setChecked(true);
} else {
started = true;
MP1.start();
MusicButton.setChecked(false);
}
}
});
}
#SuppressLint("StaticFieldLeak")
public class PlayerTask extends AsyncTask<String, Void, Boolean> {
ProgressBar loadingRL = findViewById(R.id.progressBar);
#Override
protected void onPreExecute() {
super.onPreExecute();
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
AudioAttributes attribs = new AudioAttributes.Builder().setUsage(AudioAttributes.USAGE_MEDIA).setContentType(AudioAttributes.CONTENT_TYPE_MUSIC).build();
MP1.setAudioAttributes(attribs);
} else {
MP1.setAudioStreamType(AudioManager.STREAM_MUSIC);
}
loadingRL.setVisibility(View.VISIBLE);
}
#Override
protected Boolean doInBackground(String... strings) {
try {
MP1.setDataSource(strings[0]);
MP1.prepare();
prepared = true;
} catch (IOException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalStateException e) {
e.printStackTrace();
}
MP1.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer MP1) {
MP1.start();
}
});
return prepared;
}
#Override
protected void onPostExecute(Boolean aBoolean) {
super.onPostExecute(aBoolean);
MusicButton.setVisibility(View.VISIBLE);
MusicButton.setChecked(true);
loadingRL.setVisibility(View.VISIBLE);
}
ActivityOne.java
MediaPlayer MP2;
boolean prepared = false;
boolean started = false;
ToggleButton music;
PlayerTask playerTask = null;
CoordinatorLayout coordinatorLayout;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_pop_for_ringtone);
coordinatorLayout = findViewById(R.id.coord);
MP2 = new MediaPlayer();
playerTask = new PlayerTask();
playerTask.execute(url);
}
#SuppressLint("StaticFieldLeak")
public class PlayerTask extends AsyncTask<String, Void, Boolean> {
ProgressBar pb = findViewById(R.id.progress);
#Override
protected void onPreExecute() {
super.onPreExecute();
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
AudioAttributes attribs = new AudioAttributes.Builder().setUsage(AudioAttributes.USAGE_MEDIA).setContentType(AudioAttributes.CONTENT_TYPE_MUSIC).build();
MP2.setAudioAttributes(attribs);
} else {
MP2.setAudioStreamType(AudioManager.STREAM_MUSIC);
}
}
#Override
protected Boolean doInBackground(String... strings) {
if (!isCancelled()) {
try {
MP2.setDataSource(strings[0]);
MP2.prepare();
prepared = true;
} catch (IOException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalStateException e) {
e.printStackTrace();
}
MP2.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer MP2) {
MP2.start();
}
});
}
return prepared;
}
#Override
protected void onPostExecute(Boolean aBoolean) {
super.onPostExecute(aBoolean);
music.setEnabled(true);
music.setVisibility(View.VISIBLE);
music.setChecked(true);
all.setVisibility(View.VISIBLE);
}
#Override
protected void onCancelled(Boolean aBoolean) {
if (isCancelled() && MP2.isPlaying()) {
MP2.stop();
}
}
}
#Override
public void onBackPressed() {
if (playerTask != null && playerTask.getStatus() == AsyncTask.Status.FINISHED) {
if (MP2.isPlaying()) {
MP2.stop();
}
} else if (playerTask != null && playerTask.getStatus() != AsyncTask.Status.FINISHED) {
playerTask.cancel(true);
}
super.onBackPressed();
}
i spent 2 days to resolve this problem without any result ,please someone help me i will be thankful to him
You could solve this by using Otto library. First create a new Java class but choose enum instead and inside enum you can add: PLAY and PAUSE for example:
public enum PlaybackEvent {
PLAY, PAUSE
}
Then if you are not using custom Application class create one and extend Application and override inside onCreate method. Inside your app gradle add compile 'com.squareup:otto:1.3.8' then create an instance of Bus inside Application class and register. For example this would look like this:
public class MApplication extends Application {
public static Bus sBus = new Bus(ThreadEnforcer.MAIN);
#Override
public void onCreate() {
super.onCreate();
sBus.register(this);
}
Don't forget to replace in manifest default application class with your new one
<application
android:name="com.packagename.MApplication"
After that in your MainActivity class override and register/unregister your event bus in onResume and in onPause.
#Override
protected void onResume() {
super.onResume();
try {
MApplication.sBus.register(this);
}
catch(Exception e){
e.printStackTrace();
}
}
#Override
protected void onDestroy() {
super.onDestroy();
try {
MApplication.sBus.unregister(this);
}
catch(Exception e){
e.printStackTrace();
}
}
After that in MainActivity create a public void method passing as parameter PlayBackEvent and Subscribe so you can listen a message which will be send from your fragment class. For example:
#Subscribe
public void handlePlaybackEvent(PlaybackEvent event) {
switch (event) {
case PLAY:
if(MP1.isPlaying())
MP1.pause();
break;
case PAUSE:
if(!MP1.isPlaying())
MP1.play();
break;
}
}
And last thing you have to do is to send the message from your fragment when starting second activity and that will go:
MApplication.sBus.post(PlaybackEvent.PAUSE);
and of course you can also send a message to play again MP1 from second activity overriding onBackPressed putting inside line of code:
MApplication.sBus.post(PlaybackEvent.PLAY);
Hope this will help you to resolve the problem.
Have you tried using startActivityForResult()?
Key Point: My application should be capable of running in background.
A rough structure of my application calls is:
HomeActivity(AppCompatActivity) -> MainActivity(AppCompatActivity) -> CameraRecorderService(IntentService) AND SensorService(Service)
Brief Explanation: On a button press in HomeActivity, MainActivity is triggered using Intent. As soon as MainActivity is called, in its onCreate() method, I call the two services i.e. CameraRecorderService and SensorService.
The CameraRecorderService records the video in an infinite loop unless it receives an event from SensorService.
The current application is working completely fine unless the app goes in background, i.e. I press the home button. It gives D/Camera﹕ app passed NULL surface , E/MediaRecorderJNI﹕ Application lost the surface.
The relevant code for MainActivity and CameraRecorderService are:
"MainActivity.java"
public class MainActivity extends AppCompatActivity implements SurfaceHolder.Callback{
public static SurfaceView mSurfaceView; //declared static so that it can be accessed by Services
public static SurfaceHolder mSurfaceHolder;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mSurfaceView = (SurfaceView) findViewById(R.id.surfaceView1);
mSurfaceHolder = mSurfaceView.getHolder();
mSurfaceHolder.addCallback(this);
mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
Intent intent2 = new Intent(MainActivity.this, SensorService.class);
intent2.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startService(intent2);
Intent intent = new Intent(MainActivity.this, CameraRecorderService.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startService(intent);
ImageButton btnStop = (ImageButton) findViewById(R.id.stop);
btnStop.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
stopService(new Intent(MainActivity.this, CameraRecorderService.class));
stopService(new Intent(MainActivity.this, SensorService.class));
System.exit(0);
}
});
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
}
"CameraRecorderService.java"
public class CameraRecorderService extends IntentService {
public CameraRecorderService(){
super("CameraRecorderService");
}
private SurfaceView mSurfaceView;
private SurfaceHolder mSurfaceHolder;
private static Camera mServiceCamera;
private boolean mRecordingStatus;
private MediaRecorder mMediaRecorder;
static boolean accidentStatus = false;
boolean manualStopStatus = false;
int accidentOnVideoIndex = 0;
#Override
public void onCreate() {
super.onCreate();
mSurfaceView = MainActivity.mSurfaceView; //Getting the surface from Activity
mSurfaceHolder = MainActivity.mSurfaceHolder;
}
#Override
public void onDestroy() {
super.onDestroy();
manualStopStatus = true;
if(mRecordingStatus){
stopRecording();
}
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
protected void onHandleIntent(Intent intent) {
while(!accidentStatus){
int i =1;
while(i < 3) {
if (!accidentStatus && !manualStopStatus) {
accidentOnVideoIndex = i;
startRecording("someName" + i);
try {
Thread.sleep(5000);
if(mRecordingStatus)
stopRecording();
} catch (InterruptedException e) {
e.printStackTrace();
}
i++;
}else{
break;
}
}
}
if(!manualStopStatus) {
startRecording("someName3");
try {
Thread.sleep(5000);
stopRecording();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public boolean startRecording(String fileName){
try {
mRecordingStatus = true;
mServiceCamera = Camera.open();
Camera.Parameters p = mServiceCamera.getParameters();
final List<Camera.Size> listSize = p.getSupportedPreviewSizes();
Camera.Size mPreviewSize = listSize.get(2);
Log.v(TAG, "use: width = " + mPreviewSize.width
+ " height = " + mPreviewSize.height);
p.setPreviewSize(mPreviewSize.width, mPreviewSize.height);
p.setPreviewFormat(PixelFormat.YCbCr_420_SP);
mServiceCamera.setParameters(p);
mServiceCamera.setDisplayOrientation(90);
try {
mServiceCamera.setPreviewDisplay(mSurfaceHolder);
mServiceCamera.startPreview();
}
catch (IOException e) {
Log.e(TAG, e.getMessage());
e.printStackTrace();
}
mServiceCamera.unlock();
mMediaRecorder = new MediaRecorder();
mMediaRecorder.setCamera(mServiceCamera);
mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER);
mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
mMediaRecorder.setProfile(CamcorderProfile.get(CamcorderProfile.QUALITY_480P));
mMediaRecorder.setOutputFile("/somePath/" + fileName + ".mp4");
mMediaRecorder.setPreviewDisplay(mSurfaceHolder.getSurface());
mMediaRecorder.prepare();
mMediaRecorder.start();
return true;
} catch (IllegalStateException e) {
Log.d(TAG, e.getMessage());
e.printStackTrace();
return false;
} catch (IOException e) {
Log.d(TAG, e.getMessage());
e.printStackTrace();
return false;
}
}
public void stopRecording() {
mRecordingStatus = false;
try {
mServiceCamera.reconnect();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
mMediaRecorder.stop();
mMediaRecorder.reset();
mServiceCamera.stopPreview();
mMediaRecorder.release();
mServiceCamera.release();
mServiceCamera = null;
}
public static class MyBroadcastReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
System.out.println("Accident!!");
accidentStatus = true;
}
}
I think the problem is that the SurfaceView is destroyed when Activity goes in onPause() state and as I have used a static SurfaceView it is nullified. And so the CameraRecorderService(IntentService) does not get the value from Activity because it runs on a separate thread.
But how do I solve this problem? As I said, the application works fine in foreground but the main purpose of my application is to run in background. Any suggestions are welcome!
The basic idea is if no face detected,it should return to Main(reset Activity) but after returning back to main ,getCameraInstance(0) returns null.
If i want to back to Main ,it will call the onPause() and release the cam and after main re-created the backCamera is already relased and it should problem-free create a new instance of back camera.Am i wrong ?
Thanks
ps :i get java.lang.RuntimeException: Fail to connect to camera service and that means i didnt release the camera correctly but i cant find my error.
Here is my code
public class MainActivity extends Activity{
....
private Camera mCameraBack=null;
private CameraPreviewBack mPreviewBack;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if(mCameraBack==null){
mCameraBack=getCameraInstance(0);
}
try{
mPreviewBack=new CameraPreviewBack(this,mCameraBack );
previewBack=(FrameLayout)findViewById(R.id.camera_preview_back);
previewBack.addView(mPreviewBack);
}catch(Exception ex){
Log.d(TAG,"surfaceCreate");
ex.printStackTrace();
}
public void capture(View view){
mPreviewBack.takePicture();
...
}
#Override
protected void onPause() {
Log.d(TAG, "onPause");
super.onPause();
if (mCameraBack != null) {
mCameraBack.stopPreview();
mCameraBack.release();
mCameraBack = null;
}
if (mPreviewBack != null) {
previewBack.removeView(mPreviewBack);
mPreviewBack = null;
}
}
#Override
public void onResume() {
Log.d(TAG, "onResume");
super.onResume();
if (mCameraBack == null) {
mCameraBack = getCameraInstance(0);
}
if (mPreviewBack == null) {
mPreviewBack=new CameraPreviewBack(this,mCameraBack );
previewBack.addView(mPreviewBack);
}
}
public static Camera getCameraInstance(int cameraId){
Camera c = null;
try {
c = Camera.open(cameraId);
}
catch (Exception e){
}
return c; // returns null if camera is unavailable
}
}
and
public class CameraPreviewBack extends SurfaceView implements SurfaceHolder.Callback {
...
public CameraPreviewBack(Context context,Camera camera) {
super(context);
mCamera=camera;
this.context=context;
mHolder=getHolder();
mHolder.addCallback(this);
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
Log.d(TAG, "Surface created");
try {
if(mCamera!=null){
mCamera.setPreviewDisplay(holder);
mCamera.startPreview();
}
} catch (IOException e) {
Log.d(TAG, "mHolder failure");
e.printStackTrace();
}
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
Log.d(TAG, "Surface changed");
configureCamRotation();
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
}
public void takePicture(){
..
task.execute();
try {
task.get();
} catch (InterruptedException e) {
} catch (ExecutionException e) {
}
task.cancel(isFinished);
}
private PictureCallback getPictureCallback() {
PictureCallback mPicture = new PictureCallback() {
#Override
public void onPictureTaken(byte[] data, Camera camera){
....
if(!detected){
Intent intentMain=new Intent(context, MainActivity.class);
intentMain.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
context.startActivity(intentMain);
}
...
}
private class TakePictureTask extends AsyncTask<Void, Void, Void> {
#Override
protected Void doInBackground(Void... params) {
mCamera.takePicture(null, null, getPictureCallback());
try {
Thread.sleep(2000); // 3 second preview
} catch (InterruptedException e) {
}
return null;
}
}
newer swallow exceptions
like here:
catch (Exception e){
}
Print this exception Log.d(TAG, "Error when init camera", e); and maybe you will get:
Runtime Exception http://developer.android.com/reference/android/hardware/Camera.html#open(int)
releasing camera onDestroy and changing Intents in onPostExecute method of Asynctask solved my problem