I successfully implemented the code from the google developers guide's, but i got two issues on my app, first, when i show the dialog to the user to be sure to close the app, and he closes it, the ad shows, second how can i set up the ad for don't close after my app load completly
this is the guide:
https://developers.google.com/admob/android/app-open-ads
and this is my code:
MyApplication.java
public class MyApplication extends Application {
private static AppOpenManager appOpenManager;
#Override
public void onCreate() {
super.onCreate();
MobileAds.initialize(
this,
new OnInitializationCompleteListener() {
#Override
public void onInitializationComplete(InitializationStatus initializationStatus) {
}
});
appOpenManager = new AppOpenManager(this);
}
OpenAppOpenManager.java
public class AppOpenManager implements LifecycleObserver, Application.ActivityLifecycleCallbacks {
private static final String LOG_TAG = "AppOpenManager";
private static final String AD_UNIT_ID = "ca-app-pub-3940256099942544/3419835294";
private static boolean isShowingAd = false;
private final MyApplication myApplication;
private AppOpenAd appOpenAd = null;
private AppOpenAd.AppOpenAdLoadCallback loadCallback;
private Activity currentActivity;
private long loadTime = 0;
/**
* Constructor
*/
public AppOpenManager(MyApplication myApplication) {
this.myApplication = myApplication;
this.myApplication.registerActivityLifecycleCallbacks(this);
ProcessLifecycleOwner.get().getLifecycle().addObserver(this);
}
/**
* Shows the ad if one isn't already showing.
*/
public void showAdIfAvailable() {
// Only show ad if there is not already an app open ad currently showing
// and an ad is available.
if (!isShowingAd && isAdAvailable()) {
Log.d(LOG_TAG, "Will show ad.");
FullScreenContentCallback fullScreenContentCallback =
new FullScreenContentCallback() {
#Override
public void onAdDismissedFullScreenContent() {
// Set the reference to null so isAdAvailable() returns false.
AppOpenManager.this.appOpenAd = null;
isShowingAd = false;
fetchAd();
}
#Override
public void onAdFailedToShowFullScreenContent(AdError adError) {
}
#Override
public void onAdShowedFullScreenContent() {
isShowingAd = true;
}
};
appOpenAd.setFullScreenContentCallback(fullScreenContentCallback);
appOpenAd.show(currentActivity);
} else {
Log.d(LOG_TAG, "Can not show ad.");
fetchAd();
}
}
/**
* LifecycleObserver methods
*/
#OnLifecycleEvent(ON_START)
public void onStart() {
showAdIfAvailable();
Log.d(LOG_TAG, "onStart");
}
/**
* Request an ad
*/
public void fetchAd() {
// Have unused ad, no need to fetch another.
if (isAdAvailable()) {
return;
}
loadCallback =
new AppOpenAd.AppOpenAdLoadCallback() {
#Override
public void onAdLoaded(#NonNull AppOpenAd appOpenAd) {
super.onAdLoaded(appOpenAd);
AppOpenManager.this.appOpenAd = appOpenAd;
AppOpenManager.this.loadTime = (new Date()).getTime();
}
#Override
public void onAdFailedToLoad(#NonNull LoadAdError loadAdError) {
super.onAdFailedToLoad(loadAdError);
Log.d(LOG_TAG, "failed to load");
}
};
AdRequest request = getAdRequest();
AppOpenAd.load(
myApplication, AD_UNIT_ID, request,
AppOpenAd.APP_OPEN_AD_ORIENTATION_PORTRAIT, loadCallback);
}
/**
* Creates and returns ad request.
*/
private AdRequest getAdRequest() {
return new AdRequest.Builder().build();
}
/**
* Utility method to check if ad was loaded more than n hours ago.
*/
private boolean wasLoadTimeLessThanNHoursAgo(long numHours) {
long dateDifference = (new Date()).getTime() - this.loadTime;
long numMilliSecondsPerHour = 3600000;
return (dateDifference < (numMilliSecondsPerHour * numHours));
}
/**
* Utility method that checks if ad exists and can be shown.
*/
public boolean isAdAvailable() {
return appOpenAd != null && wasLoadTimeLessThanNHoursAgo(4);
}
#Override
public void onActivityCreated(#NonNull Activity activity, #Nullable Bundle savedInstanceState) {
}
#Override
public void onActivityStarted(Activity activity) {
currentActivity = activity;
}
#Override
public void onActivityResumed(Activity activity) {
currentActivity = activity;
}
#Override
public void onActivityPaused(#NonNull Activity activity) {
}
#Override
public void onActivityStopped(#NonNull Activity activity) {
}
#Override
public void onActivitySaveInstanceState(#NonNull Activity activity, #NonNull Bundle outState) {
}
#Override
public void onActivityDestroyed(Activity activity) {
currentActivity = null;
}
Related
I placed an ad of the type: "app-open" admob.
This advertisement is not accepted by the App Store except in one case:
That there is a splash for the application, and that the advertisement appears above the splash and ends with the end of the splash.
For example: Here I set the time to run the ad after the splash
appears
/** LifecycleObserver methods */
#OnLifecycleEvent(ON_START)
public void onStart() {
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
showAdIfAvailable();
}
}, 1000);
Log.d(LOG_TAG, "onStart");
}
Here is the total splash timing:
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
if (go) {
startActivity(new Intent(Splash_Activity.this, Home_main.class));
finish();
//If you delete the finish also the splash appears after exiting the application, how can this process be transferred to the advertisement
}
}
}, 4000);
}
So if you are asking where is the problem:
The problem is: If you do not close the ad, it will close automatically at the end of the time of the splash, but when you exit the application you find the ad and you need to close it.
What I need:
It is an automatic closure and a finish for the advertisement when the splash timer ends.
AppOpenManager.clss
/** Prefetches App Open Ads. */
public class AppOpenManager implements LifecycleObserver, Application.ActivityLifecycleCallbacks {
private static final String LOG_TAG = "AppOpenManager";
private static final String AD_UNIT_ID = "MY APP AD UNIT ID";
private AppOpenAd appOpenAd = null;
private long loadTime = 0;
private AppOpenAd.AppOpenAdLoadCallback loadCallback;
private Activity currentActivity;
private static boolean isShowingAd = false;
private final GlobalVar home_main;
/**
* Constructor
*/
public AppOpenManager(GlobalVar home_main) {
this.home_main = home_main;
this.home_main.registerActivityLifecycleCallbacks(this);
ProcessLifecycleOwner.get().getLifecycle().addObserver(this);
}
public static void showAdIfAvailable(FullScreenContentCallback fullScreenContentCallback) {
}
/** LifecycleObserver methods */
#OnLifecycleEvent(ON_START)
public void onStart() {
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
showAdIfAvailable();
}
}, 1000);
Log.d(LOG_TAG, "onStart");
}
/** Shows the ad if one isn't already showing. */
public void showAdIfAvailable() {
// Only show ad if there is not already an app open ad currently showing
// and an ad is available.
if (!isShowingAd && isAdAvailable()) {
Log.d(LOG_TAG, "Will show ad.");
FullScreenContentCallback fullScreenContentCallback =
new FullScreenContentCallback() {
#Override
public void onAdDismissedFullScreenContent() {
// Set the reference to null so isAdAvailable() returns false.
AppOpenManager.this.appOpenAd = null;
isShowingAd = false;
fetchAd();
}
#Override
public void onAdFailedToShowFullScreenContent(AdError adError) {}
#Override
public void onAdShowedFullScreenContent() {
isShowingAd = true;
}
};
appOpenAd.setFullScreenContentCallback(fullScreenContentCallback);
appOpenAd.show(currentActivity);
} else {
Log.d(LOG_TAG, "Can not show ad.");
fetchAd();
}
}
/**
* Request an ad
*/
public void fetchAd() {
// Have unused ad, no need to fetch another.
if (isAdAvailable()) {
return;
}
loadCallback =
new AppOpenAd.AppOpenAdLoadCallback() {
/**
* Called when an app open ad has loaded.
*
* #param ad the loaded app open ad.
*/
#Override
public void onAdLoaded(AppOpenAd ad) {
AppOpenManager.this.appOpenAd = ad;
AppOpenManager.this.loadTime = (new Date()).getTime();
}
/**
* Called when an app open ad has failed to load.
*
* #param loadAdError the error.
*/
#Override
public void onAdFailedToLoad(LoadAdError loadAdError) {
// Handle the error.
}
};
AdRequest request = getAdRequest();
AppOpenAd.load(
home_main, AD_UNIT_ID, request,
AppOpenAd.APP_OPEN_AD_ORIENTATION_PORTRAIT, loadCallback);
}
// We will implement this below.
/**
* Creates and returns ad request.
*/
private AdRequest getAdRequest() {
return new AdRequest.Builder().build();
}
/**
* Utility method that checks if ad exists and can be shown.
*/
public boolean isAdAvailable() {
return appOpenAd != null && wasLoadTimeLessThanNHoursAgo(4);
}
#Override
public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
}
#Override
public void onActivityStarted(Activity activity) {
currentActivity = activity;
}
#Override
public void onActivityResumed(Activity activity) {
currentActivity = activity;
}
#Override
public void onActivityStopped(Activity activity) {
}
#Override
public void onActivityPaused(Activity activity) {
}
#Override
public void onActivitySaveInstanceState(Activity activity, Bundle bundle) {
}
#Override
public void onActivityDestroyed(Activity activity) {
currentActivity = null;
}
/** Utility method to check if ad was loaded more than n hours ago. */
private boolean wasLoadTimeLessThanNHoursAgo(long numHours) {
long dateDifference = (new Date()).getTime() - this.loadTime;
long numMilliSecondsPerHour = 3600000;
return (dateDifference < (numMilliSecondsPerHour * numHours));
}
}
I'm tying to play videos from a Firebase Listadapter. When the user clicks on the list they a video plays, and upon finishing the activity finishes, and they return to the original list.
When the click on the second video it starts the ExoPlayer activity, but won't play the video. If they press back and select the original video it will play fine.
public String mTastingWineID;
public String tastingWineId;
public String mWineVideoID;
public String tastingWineVideoId;
private DataSource.Factory mediaDataSourceFactory;
private boolean isPlaying = false;
public int mVideoResource;
public Uri videoUri;
private static final String TAG = "WineMediaActivity";
private static final DefaultBandwidthMeter BANDWIDTH_METER = new DefaultBandwidthMeter();
private SimpleExoPlayer player;
private SimpleExoPlayerView mVideoView;
private ComponentListener componentListener;
private long playbackPostiion;
private int currentWindow;
private boolean playWhenReady = true;
private BandwidthMeter bandwidthMeter;
public Firebase wineMediaUrl;
public ValueEventListener wineMediaUrlListener;
private MediaControllerCompat mediaControllerCompat;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.analytics_media_wine_information);
Bundle bundle = getIntent().getExtras();
mTastingWineID = bundle.getString(Constants.WINE_ID);
tastingWineId = mTastingWineID.toString();
mWineVideoID = bundle.getString(Constants.WINE_VIDEO_ID);
tastingWineVideoId = mWineVideoID.toString();
if (player != null){
player.release();
}
getCurrentVideo();
}
public void getCurrentVideo(){
wineMediaUrl = new Firebase(Constants.FIREBASE_URL).child(FIREBASE_LOCATION_WINE_DETAILS).child(tastingWineId).child(WINE_MEDIA).child(tastingWineVideoId).child("wineVideoUrl");
wineMediaUrlListener = wineMediaUrl.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
componentListener = new ComponentListener();
mVideoView = findViewById(R.id.videoView1);
mVideoView.requestFocus();
Object tempVideoFiles = dataSnapshot.getValue();
String str = tempVideoFiles.toString();
videoUri = Uri.parse(str);
if (videoUri != null) {
initializePlayer();
} else {
Toast.makeText(WineMediaActivity.this, "No Video Found", Toast.LENGTH_SHORT).show();
}
}
#Override
public void onCancelled(FirebaseError firebaseError) {
}
});
mediaDataSourceFactory = new DefaultDataSourceFactory(this, Util.getUserAgent(this, "mediaPlayerSample"), (TransferListener<? super DataSource>) bandwidthMeter);
}
private class ComponentListener implements ExoPlayer.EventListener, VideoRendererEventListener, AudioRendererEventListener {
#Override
public void onTimelineChanged(Timeline timeline, Object manifest) {
}
#Override
public void onTracksChanged(TrackGroupArray trackGroups, TrackSelectionArray trackSelections) {
}
#Override
public void onLoadingChanged(boolean isLoading) {
}
#Override
public void onPlayerStateChanged(boolean playWhenReady, int playbackState) {
String stateString;
switch (playbackState) {
case ExoPlayer.STATE_IDLE:
stateString = "ExoPlayer.STATE_IDLE";
break;
case ExoPlayer.STATE_BUFFERING:
stateString = "ExoPlayer.STATE_IDLE";
break;
case ExoPlayer.STATE_READY:
stateString = "ExoPlayer.STATE_IDLE";
break;
case ExoPlayer.STATE_ENDED:
stateString = "ExoPlayer.STATE_IDLE";
releasePlayer();
finish();
break;
default:
stateString = "UNKNOWN_STATE";
break;
}
Log.d(TAG, "changed state to: " + stateString + " play when ready: " + playWhenReady);
}
#Override
public void onRepeatModeChanged(int repeatMode) {
}
#Override
public void onShuffleModeEnabledChanged(boolean shuffleModeEnabled) {
}
#Override
public void onPlayerError(ExoPlaybackException error) {
}
#Override
public void onPositionDiscontinuity(int reason) {
}
#Override
public void onPlaybackParametersChanged(PlaybackParameters playbackParameters) {
}
#Override
public void onSeekProcessed() {
}
#Override
public void onAudioEnabled(DecoderCounters counters) {
}
#Override
public void onAudioSessionId(int audioSessionId) {
}
#Override
public void onAudioDecoderInitialized(String decoderName, long initializedTimestampMs, long initializationDurationMs) {
}
#Override
public void onAudioInputFormatChanged(Format format) {
}
#Override
public void onAudioSinkUnderrun(int bufferSize, long bufferSizeMs, long elapsedSinceLastFeedMs) {
}
#Override
public void onAudioDisabled(DecoderCounters counters) {
}
#Override
public void onVideoEnabled(DecoderCounters counters) {
}
#Override
public void onVideoDecoderInitialized(String decoderName, long initializedTimestampMs, long initializationDurationMs) {
}
#Override
public void onVideoInputFormatChanged(Format format) {
}
#Override
public void onDroppedFrames(int count, long elapsedMs) {
}
#Override
public void onVideoSizeChanged(int width, int height, int unappliedRotationDegrees, float pixelWidthHeightRatio) {
}
#Override
public void onRenderedFirstFrame(Surface surface) {
}
#Override
public void onVideoDisabled(DecoderCounters counters) {
}
}
private void initializePlayer() {
if (player == null) {
TrackSelection.Factory adaptiveTrackSelectionFactory = new AdaptiveTrackSelection.Factory(bandwidthMeter);
player = ExoPlayerFactory.newSimpleInstance(new DefaultRenderersFactory(this), new DefaultTrackSelector(adaptiveTrackSelectionFactory), new DefaultLoadControl());
player.addListener(componentListener);
player.setVideoDebugListener(componentListener);
player.setAudioDebugListener(componentListener);
mVideoView.setPlayer(player);
player.setPlayWhenReady(playWhenReady);
player.seekTo(currentWindow, playbackPostiion);
}
MediaSource mediaSource = new ExtractorMediaSource(videoUri, mediaDataSourceFactory, extractorsFactory, null, null);
player.prepare(mediaSource, true, false);
}
#SuppressLint("InlinedApi")
private void hideSystemUi() {
mVideoView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LOW_PROFILE | View.SYSTEM_UI_FLAG_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION);
}
private void releasePlayer() {
if (player != null) {
playbackPostiion = player.getCurrentPosition();
currentWindow = player.getCurrentWindowIndex();
playWhenReady = player.getPlayWhenReady();
player.removeListener(componentListener);
mVideoView.setPlayer(null);
player.setVideoListener(null);
player.setVideoDebugListener(null);
player.setAudioDebugListener(null);
player.release();
player = null;
if (wineMediaUrlListener != null) {
wineMediaUrl.removeEventListener(wineMediaUrlListener);
wineMediaUrlListener = null;
}
}
}
#Override
protected void onPause() {
super.onPause();
releasePlayer();
}
#Override
public void onStop() {
super.onStop();
releasePlayer();
}
#Override
public void onDestroy() {
super.onDestroy();
releasePlayer();
}
Apologies for the code, I'm newish to coding and hoping someone can help me.
Turns out the code is fine - the error was in the upload of videos, they were overwriting the previous video meaning the previous one wouldn't play.
I am trying to make example of Play Billing application described here
In Last step they have described
To clean all the resources and unregister the observer, you just need to call BillingClient.endConnection. So define a method with this call inside BillingManager and then call it from GamePlayActivity.onDestroy:
according to above information I have made function called destroy like this in BillingManagerjava class.
public void destroy() {
mBillingClient.endConnection();
}
My Full BillingManager Class is like below
public class BillingManager implements PurchasesUpdatedListener {
private final BillingClient mBillingClient;
private final Activity mActivity;
private static final String TAG = "BillingManager";
public BillingManager(Activity activity) {
mActivity = activity;
mBillingClient = BillingClient.newBuilder(mActivity).setListener(this).build();
mBillingClient.startConnection(new BillingClientStateListener() {
#Override
public void onBillingSetupFinished(#BillingClient.BillingResponse int billingResponse) {
if (billingResponse == BillingClient.BillingResponse.OK) {
Log.i(TAG, "onBillingSetupFinished() response: " + billingResponse);
} else {
Log.w(TAG, "onBillingSetupFinished() error code: " + billingResponse);
}
}
#Override
public void onBillingServiceDisconnected() {
Log.w(TAG, "onBillingServiceDisconnected()");
}
});
}
public void startPurchaseFlow(final String skuId, final String billingType) {
// Specify a runnable to start when connection to Billing client is established
Runnable executeOnConnectedService = new Runnable() {
#Override
public void run() {
BillingFlowParams billingFlowParams = BillingFlowParams.newBuilder()
.setType(billingType)
.setSku(skuId)
.build();
mBillingClient.launchBillingFlow(mActivity, billingFlowParams);
}
};
// If Billing client was disconnected, we retry 1 time
// and if success, execute the query
startServiceConnectionIfNeeded(executeOnConnectedService);
}
#Override
public void onPurchasesUpdated(#BillingClient.BillingResponse int responseCode,
List<Purchase> purchases) {
Log.d(TAG, "onPurchasesUpdated() response: " + responseCode);
}
private static final HashMap<String, List<String>> SKUS;
static
{
SKUS = new HashMap<>();
SKUS.put(BillingClient.SkuType.INAPP, Arrays.asList("gas", "premium"));
SKUS.put(BillingClient.SkuType.SUBS, Arrays.asList("gold_monthly", "gold_yearly"));
}
public List<String> getSkus(#BillingClient.SkuType String type) {
return SKUS.get(type);
}
public void querySkuDetailsAsync(#BillingClient.SkuType final String itemType,
final List<String> skuList, final SkuDetailsResponseListener listener) {
// Specify a runnable to start when connection to Billing client is established
Runnable executeOnConnectedService = new Runnable() {
#Override
public void run() {
SkuDetailsParams skuDetailsParams = SkuDetailsParams.newBuilder()
.setSkusList(skuList).setType(itemType).build();
mBillingClient.querySkuDetailsAsync(skuDetailsParams,
new SkuDetailsResponseListener() {
#Override
public void onSkuDetailsResponse(int responseCode,
List<SkuDetails> skuDetailsList) {
listener.onSkuDetailsResponse(responseCode, skuDetailsList);
}
});
}
};
// If Billing client was disconnected, we retry 1 time
// and if success, execute the query
startServiceConnectionIfNeeded(executeOnConnectedService);
}
private void startServiceConnectionIfNeeded(final Runnable executeOnSuccess) {
if (mBillingClient.isReady()) {
if (executeOnSuccess != null) {
executeOnSuccess.run();
}
} else {
mBillingClient.startConnection(new BillingClientStateListener() {
#Override
public void onBillingSetupFinished(#BillingClient.BillingResponse int billingResponse) {
if (billingResponse == BillingClient.BillingResponse.OK) {
Log.i(TAG, "onBillingSetupFinished() response: " + billingResponse);
if (executeOnSuccess != null) {
executeOnSuccess.run();
}
} else {
Log.w(TAG, "onBillingSetupFinished() error code: " + billingResponse);
}
}
#Override
public void onBillingServiceDisconnected() {
Log.w(TAG, "onBillingServiceDisconnected()");
}
});
}
}
public void destroy() {
mBillingClient.endConnection();
}
}
And My GamePlayActivity is like below
public class GamePlayActivity extends FragmentActivity implements BillingProvider {
#Override
protected void onDestroy() {
super.onDestroy();
// I want call method here
}
}
Now I want call above function in my game play activity. I have no idea how to call it.
As it mentioned in documentation
call it from GamePlayActivity.onDestroy
but you defined your own method.
Override onDestroy method of GamePlayActivity and put mBillingClient.endConnection(); into it.
#Override
protected void onDestroy() {
mBillingClient.endConnection();
}
I assume your Activity already has an instance of the BillingManager
public class GamePlayActivity extends FragmentActivity implements BillingProvider {
BillingManager bm; // assign this in onCreate
#Override
protected void onDestroy() {
super.onDestroy();
bm.destroy();
}
}
I am working on a project in Android Studio where I am supposed to connect two devices using Wifi-Direct.
I have managed to connect to another device with Wifi-direct. My problem is that when I close the app manually on my phone, the devices do not disconnect. How can I achieve this? I am quite new with Android Studio and java.
Here is my WifiDirectActivity class:
public class WiFiDirectActivity extends Activity implements WifiP2pManager.ChannelListener, DeviceListFragment.DeviceActionListener {
public static final String TAG = "wifidirectdemo";
private WifiP2pManager manager;
private boolean isWifiP2pEnabled = false;
private boolean retryChannel = false;
private final IntentFilter intentFilter = new IntentFilter();
private WifiP2pManager.Channel channel;
private BroadcastReceiver receiver = null;
/**
* #param isWifiP2pEnabled the isWifiP2pEnabled to set
*/
public void setIsWifiP2pEnabled(boolean isWifiP2pEnabled) {
this.isWifiP2pEnabled = isWifiP2pEnabled;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_peers);
// add necessary intent values to be matched.
intentFilter.addAction(WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION);
intentFilter.addAction(WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION);
intentFilter.addAction(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION);
intentFilter.addAction(WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION);
manager = (WifiP2pManager) getSystemService(Context.WIFI_P2P_SERVICE);
channel = manager.initialize(this, getMainLooper(), null);
}
/** register the BroadcastReceiver with the intent values to be matched */
#Override
public void onResume() {
super.onResume();
receiver = new WiFiDirectBroadcastReceiver(manager, channel, this);
registerReceiver(receiver, intentFilter);
if (!amConnected) {
performSearch();
}
}
#Override
public void onPause() {
super.onPause();
unregisterReceiver(receiver);
}
/**
* Remove all peers and clear all fields. This is called on
* BroadcastReceiver receiving a state change event.
*/
public void resetData() {
DeviceListFragment fragmentList = (DeviceListFragment) getFragmentManager()
.findFragmentById(R.id.frag_list);
DeviceDetailFragment fragmentDetails = (DeviceDetailFragment) getFragmentManager()
.findFragmentById(R.id.frag_detail);
if (fragmentList != null) {
fragmentList.clearPeers();
}
if (fragmentDetails != null) {
fragmentDetails.resetViews();
}
}
#Override
public void showDetails(WifiP2pDevice device) {
DeviceDetailFragment fragment = (DeviceDetailFragment) getFragmentManager()
.findFragmentById(R.id.frag_detail);
fragment.showDetails(device);
}
#Override
public void connect(WifiP2pConfig config) {
manager.connect(channel, config, new WifiP2pManager.ActionListener() {
#Override
public void onSuccess() {
// WiFiDirectBroadcastReceiver will notify us. Ignore for now.
}
#Override
public void onFailure(int reason) {
Toast.makeText(WiFiDirectActivity.this, "Connect failed. Retry.",
Toast.LENGTH_SHORT).show();
}
});
}
#Override
public void disconnect() {
final DeviceDetailFragment fragment = (DeviceDetailFragment) getFragmentManager()
.findFragmentById(R.id.frag_detail);
fragment.resetViews();
manager.removeGroup(channel, new WifiP2pManager.ActionListener() {
#Override
public void onFailure(int reasonCode) {
Log.d(TAG, "Disconnect failed. Reason :" + reasonCode);
}
#Override
public void onSuccess() {
fragment.getView().setVisibility(View.GONE);
}
});
}
#Override
public void onChannelDisconnected() {
// we will try once more
if (manager != null && !retryChannel) {
Toast.makeText(this, "Channel lost. Trying again", Toast.LENGTH_LONG).show();
resetData();
retryChannel = true;
manager.initialize(this, getMainLooper(), this);
} else {
Toast.makeText(this,
"Severe! Channel is probably lost premanently. Try Disable/Re-Enable P2P.",
Toast.LENGTH_LONG).show();
}
}
#Override
public void cancelDisconnect() {
/*
* A cancel abort request by user. Disconnect i.e. removeGroup if
* already connected. Else, request WifiP2pManager to abort the ongoing
* request
*/
if (manager != null) {
final DeviceListFragment fragment = (DeviceListFragment) getFragmentManager()
.findFragmentById(R.id.frag_list);
if (fragment.getDevice() == null
|| fragment.getDevice().status == WifiP2pDevice.CONNECTED) {
disconnect();
} else if (fragment.getDevice().status == WifiP2pDevice.AVAILABLE
|| fragment.getDevice().status == WifiP2pDevice.INVITED) {
manager.cancelConnect(channel, new WifiP2pManager.ActionListener() {
#Override
public void onSuccess() {
Toast.makeText(WiFiDirectActivity.this, "Aborting connection",
Toast.LENGTH_SHORT).show();
}
#Override
public void onFailure(int reasonCode) {
Toast.makeText(WiFiDirectActivity.this,
"Connect abort request failed. Reason Code: " + reasonCode,
Toast.LENGTH_SHORT).show();
}
});
}
}
}
private void performSearch() {
final DeviceListFragment fragment = (DeviceListFragment) getFragmentManager()
.findFragmentById(R.id.frag_list);
fragment.onInitiateDiscovery();
manager.discoverPeers(channel, new WifiP2pManager.ActionListener() {
#Override
public void onSuccess() {
Toast.makeText(WiFiDirectActivity.this, "Discovery Initiated",
Toast.LENGTH_SHORT).show();
}
#Override
public void onFailure(int reasonCode) {
Toast.makeText(WiFiDirectActivity.this, "Discovery Failed : " + reasonCode,
Toast.LENGTH_SHORT).show();
}
});
}
}
When you close the app the execution will run through onPause() callback, there you should call the disconnect() method. However, take 5 minutes of your time to understand Android's life cycle principle: https://developer.android.com/guide/components/activities/activity-lifecycle.html. It's one of the first things to learn before developing an Android app.
I need to execute some tasks when my application is closed.
I have made a service for do this and tried many things, but i don't have the good result.
If someone have a tutorial or some path to follow, it would be great
This is my service:
public class TrackersImporter extends Service {
private static TrackersImporter instance;
private static long refreshDelay = 1; // Minutes
private Looper mServiceLooper;
private ServiceHandler mServiceHandler;
private boolean isInit = false;
public ArrayList<Tracker> trackers = new ArrayList<>();
public static TrackersImporter getInstance(){
if (instance == null)
instance = new TrackersImporter();
return instance;
}
#Override
public void onCreate() {
HandlerThread thread = new HandlerThread("TrackersImporter",
Process.THREAD_PRIORITY_BACKGROUND);
thread.start();
mServiceLooper = thread.getLooper();
mServiceHandler = new ServiceHandler(mServiceLooper);
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
try {
Toast.makeText(this, "onStartCommand", Toast.LENGTH_SHORT).show();
Message message = mServiceHandler.obtainMessage();
message.arg1 = startId;
mServiceHandler.sendMessage(message);
} catch (Exception e) {
Log.w("TrackersImporter", e.getMessage());
}
return START_STICKY;
}
public void addTracker(Tracker tracker) {
trackers.add(tracker);
}
protected void showToast(final String msg){
Handler handler = new Handler(Looper.getMainLooper());
handler.post(new Runnable() {
#Override
public void run() {
Toast.makeText(getApplicationContext(), msg, Toast.LENGTH_SHORT).show();
}
});
}
// Object responsible for
private final class ServiceHandler extends Handler {
public ServiceHandler(Looper looper) {
super(looper);
}
#Override
public void handleMessage(Message msg) {
addTracker(Runkeeper.getInstance(MainActivity.getActivity()));
addTracker(Strava.getInstance(MainActivity.getActivity()));
startImport(MainActivity.getActivity().getBaseContext(), MainActivity.getActivity().getAppUser(), trackers);
stopSelf(msg.arg1);
}
/**
* Perform data imports.
* Imports are performed only 1 time.
* Additional calls to this method are equivalent to no-op.
* Call init() then performImport() for each TrackerImportable
* #param user user receiving the datas
*/
public void startImport(Context context, User user, ArrayList<Tracker> trackers) {
Context ctx = MainActivity.getActivity().getApplicationContext();
LocalDateTime now = new LocalDateTime();
if (Preferences.getPref(ctx, "tracker_import_date") == "")
Preferences.setPref(ctx, "tracker_import_date", now.toString());
LocalDateTime past = LocalDateTime.parse(Preferences.getPref(ctx, "tracker_import_date"));
long duration = new Duration(past.toDateTime(), now.toDateTime()).getStandardMinutes();
if (isInit)
return;
if (duration > refreshDelay) {
Preferences.setPref(ctx, "tracker_import_date", now.toString());
for (Tracker tracker : trackers) {
if (tracker.isEnabled() && Tracker.isUserEnabled(context, tracker.getName())) {
tracker.init();
tracker.performImport(user);
}
}
}
isInit = true;
}
}
}
This is my mainActivity
public class MainActivity extends BaseActivity {
...
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
...
if (ConnectivityUtil.isConnected(this.getApplicationContext())) {
initGoogleFit();
initTrackers(appUser);
}
}
private void initTrackers(User user) {
Intent trackersIntentService = new Intent(this, TrackersImporter.class);
trackersIntentService.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
this.startService(trackersIntentService);
}
#Override
protected void onResume() {
...
if (ConnectivityUtil.isConnected(this.getApplicationContext())) {
initTrackers(appUser);
}
}
}
First Create one launcher Activity which is like your Main Activity.
In Activity "onCreate" Method you need to start Service and Do Some thing if you wont in Service "onStartCommand" Method.
public class MainActivity extends Activity {
ArrayList<Integer> list;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
startService(new Intent(MainActivity.this,TrackersImporter.class);
}
public class TrackersImporter extends Service {
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
// do something
Log.v(TAG ,"Service is started");
}
}
And also Register this Service at manifest.xml like this.
<service android:name=".TrackersImporter"></service>
if you like stop service
stopService(new Intent(MainActivity.this,TrackersImporter.class);