I'm trying to make ads that give "100 coins" and the button just disappear after 0,2 - 1 second.
I've got no clue why this error could appear. Has someone got an idea how to fix that?
My error
06-03 21:42:16.017: V/PTAdHeyzapBridge(27950): PTAdHeyzapBridge -- Start Session: "MyHeyzapID"
06-03 21:42:16.023: E/Heyzap(27950): Heyzap encountered a runtime exception and is now disabled. Error: Attempt to invoke virtual method 'java.lang.String android.content.Context.getPackageName()' on a null object reference
06-03 21:42:16.023: V/PTAdHeyzapBridge(27950): PTAdHeyzapBridge -- Start Session FAILED : Attempt to invoke virtual method 'java.lang.String android.content.Context.getPackageName()' on a null object reference
06-03 21:42:16.023: V/PTAdHeyzapBridge(27950): Heyzap SDK Version : 8.4.1
My PTAdHeyzapBridge.java
package com.secrethq.ads;
import java.lang.ref.WeakReference;
import org.cocos2dx.lib.Cocos2dxActivity;
import com.google.android.gms.ads.AdView;
import com.heyzap.sdk.ads.HeyzapAds;
import com.heyzap.sdk.ads.InterstitialAd;
import com.heyzap.sdk.ads.VideoAd;
import com.heyzap.sdk.ads.IncentivizedAd;
import com.heyzap.sdk.ads.BannerAdView;
import com.heyzap.sdk.ads.HeyzapAds.BannerListener;
import com.heyzap.sdk.ads.HeyzapAds.BannerError;
import com.heyzap.sdk.ads.HeyzapAds.OnStatusListener;
import com.heyzap.sdk.ads.HeyzapAds.OnIncentiveResultListener;
import android.util.Log;
import android.view.View;
import android.widget.FrameLayout;
import android.widget.RelativeLayout;
public class PTAdHeyzapBridge {
private static native String bannerId();
private static native String interstitialId();
private static native void interstitialDidFail();
private static native void bannerDidFail();
private static native void rewardVideoComplete();
private static final String TAG = "PTAdHeyzapBridge";
private static Cocos2dxActivity activity;
private static WeakReference<Cocos2dxActivity> s_activity;
private static BannerAdView bannerAdView;
public static void initBridge(Cocos2dxActivity activity){
Log.v(TAG, "PTAdHeyzapBridge -- INIT");
PTAdHeyzapBridge.s_activity = new WeakReference<Cocos2dxActivity>(activity);
PTAdHeyzapBridge.activity = activity;
PTAdHeyzapBridge.initBanner();
PTAdHeyzapBridge.initInterstitial();
PTAdHeyzapBridge.initVideo();
}
public static void initBanner(){
Log.v(TAG, "PTAdHeyzapBridge -- Init Banner");
PTAdHeyzapBridge.s_activity.get().runOnUiThread( new Runnable() {
public void run() {
PTAdHeyzapBridge.bannerAdView = new BannerAdView(PTAdHeyzapBridge.activity);
FrameLayout frameLayout = (FrameLayout)PTAdHeyzapBridge.activity.findViewById(android.R.id.content);
RelativeLayout layout = new RelativeLayout( PTAdHeyzapBridge.activity );
frameLayout.addView( layout );
RelativeLayout.LayoutParams adViewParams = new RelativeLayout.LayoutParams(
AdView.LayoutParams.WRAP_CONTENT,
AdView.LayoutParams.WRAP_CONTENT);
adViewParams.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
adViewParams.addRule(RelativeLayout.CENTER_IN_PARENT, RelativeLayout.TRUE);
layout.addView(PTAdHeyzapBridge.bannerAdView, adViewParams);
PTAdHeyzapBridge.bannerAdView.setVisibility( View.INVISIBLE );
// Add a listener.
PTAdHeyzapBridge.bannerAdView.setBannerListener(new BannerListener() {
#Override
public void onAdClicked(BannerAdView b) {
// The ad has been clicked by the user.
}
#Override
public void onAdLoaded(BannerAdView b) {
// The ad has been loaded.
}
#Override
public void onAdError(BannerAdView b, BannerError bannerError) {
// There was an error loading the ad.
Log.v(TAG, "PTAdHeyzapBridge -- Banner onAdError : " + bannerError.getErrorMessage());
bannerDidFail();
}
});
}
});
}
public static void initInterstitial(){
Log.v(TAG, "PTAdHeyzapBridge -- Init Interstitial");
InterstitialAd.setOnStatusListener(new OnStatusListener() {
#Override
public void onShow(String tag) {
// Ad is now showing
}
#Override
public void onClick(String tag) {
// Ad was clicked on. You can expect the user to leave your application temporarily.
}
#Override
public void onHide(String tag) {
// Ad was closed. The user has returned to your application.
}
#Override
public void onFailedToShow(String tag) {
// Display was called but there was no ad to show
}
#Override
public void onAvailable(String tag) {
// An ad has been successfully fetched
}
#Override
public void onFailedToFetch(String tag) {
// No ad was able to be fetched
Log.v(TAG, "PTAdHeyzapBridge -- Interstitial onFailedToFetch : " + tag);
interstitialDidFail();
}
#Override
public void onAudioFinished() {
// TODO Auto-generated method stub
}
#Override
public void onAudioStarted() {
// TODO Auto-generated method stub
}
});
}
public static void initVideo() {
IncentivizedAd.setOnIncentiveResultListener(new OnIncentiveResultListener() {
#Override
public void onComplete(String tag) {
Log.v(TAG, "PTAdHeyzapBridge -- IncentivizedAd Complete ");
// Give the player their reward
rewardVideoComplete();
}
#Override
public void onIncomplete(String tag) {
// Don't give the player their reward, and tell them why
Log.v(TAG, "PTAdHeyzapBridge -- IncentivizedAd InComplete ");
}
});
PTAdHeyzapBridge.s_activity.get().runOnUiThread( new Runnable() {
public void run() {
// As early as possible, and after showing a rewarded video, call fetch
IncentivizedAd.fetch();
}
});
}
public static void showRewardedVideo(){
Log.v(TAG, "PTAdHeyzapBridge -- showRewardedVideo");
PTAdHeyzapBridge.s_activity.get().runOnUiThread( new Runnable() {
public void run() {
if (IncentivizedAd.isAvailable()) {
IncentivizedAd.display(PTAdHeyzapBridge.activity);
}
}
});
}
public static void startSession( String sdkKey ){
if(sdkKey != null){
Log.v(TAG, "PTAdHeyzapBridge -- Start Session: " + sdkKey);
try {
HeyzapAds.start(sdkKey, PTAdHeyzapBridge.activity);
} catch (Exception e) {
// TODO: handle exception
Log.v(TAG, "PTAdHeyzapBridge -- Start Session FAILED : " + e.getMessage());
}
Log.v(TAG, "Heyzap SDK Version : " + HeyzapAds.getVersion());
}else{
Log.v(TAG, "Start Session : null ");
}
}
public static void showFullScreen(){
Log.v(TAG, "PTAdHeyzapBridge -- showFullScreen");
PTAdHeyzapBridge.s_activity.get().runOnUiThread( new Runnable() {
public void run() {
// InterstitialAds are automatically fetched from our server
InterstitialAd.display(PTAdHeyzapBridge.activity);
}
});
}
public static void showBannerAd(){
Log.v(TAG, "PTAdHeyzapBridge -- showBannerAd");
PTAdHeyzapBridge.s_activity.get().runOnUiThread( new Runnable() {
public void run() {
if(PTAdHeyzapBridge.bannerAdView != null){
PTAdHeyzapBridge.bannerAdView.setVisibility(View.VISIBLE);
// Load the banner ad.
PTAdHeyzapBridge.bannerAdView.load();
}
}
});
}
public static void hideBannerAd(){
Log.v(TAG, "PTAdHeyzapBridge -- hideBannerAd");
PTAdHeyzapBridge.s_activity.get().runOnUiThread( new Runnable() {
public void run() {
if(PTAdHeyzapBridge.bannerAdView != null){
PTAdHeyzapBridge.bannerAdView.setVisibility(View.INVISIBLE);
}
}
});
}
public static boolean isBannerVisible() {
return (PTAdHeyzapBridge.bannerAdView.getVisibility() == View.VISIBLE);
}
public static boolean isRewardedVideoAvialable(){
return IncentivizedAd.isAvailable();
}
}
My Main activity
package com.lopeostudios.runningpanda;
import org.cocos2dx.lib.Cocos2dxActivity;
import org.cocos2dx.lib.Cocos2dxGLSurfaceView;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.WindowManager;
import android.widget.Toast;
import com.secrethq.store.PTStoreBridge;
import com.google.android.gms.games.GamesActivityResultCodes;
import com.lopeostudios.runningpanda.R;
import com.secrethq.ads.*;
import com.secrethq.utils.*;
import com.onesignal.OneSignal;
public class PTPlayer extends Cocos2dxActivity {
private static native void loadModelController();
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
Log.v("----------","onActivityResult: request: " + requestCode + " result: "+ resultCode);
if(PTStoreBridge.iabHelper().handleActivityResult(requestCode, resultCode, data)){
Log.v("-----------", "handled by IABHelper");
}
else if(requestCode == PTServicesBridge.RC_SIGN_IN){
if(resultCode == RESULT_OK){
PTServicesBridge.instance().onActivityResult(requestCode, resultCode, data);
}
else if(resultCode == GamesActivityResultCodes.RESULT_SIGN_IN_FAILED){
int duration = Toast.LENGTH_SHORT;
Toast toast = Toast.makeText(this, "Google Play Services: Sign in error", duration);
toast.show();
}
else if(resultCode == GamesActivityResultCodes.RESULT_APP_MISCONFIGURED){
int duration = Toast.LENGTH_SHORT;
Toast toast = Toast.makeText(this, "Google Play Services: App misconfigured", duration);
toast.show();
}
}
}
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
OneSignal.startInit(this).init();
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
}
#Override
public void onNativeInit(){
initBridges();
}
private void initBridges(){
PTStoreBridge.initBridge( this );
PTServicesBridge.initBridge(this, getString( R.string.app_id ));
if (PTJniHelper.isAdNetworkActive("kChartboost")) {
PTAdChartboostBridge.initBridge(this);
}
if (PTJniHelper.isAdNetworkActive("kRevMob")) {
PTAdRevMobBridge.initBridge(this);
}
if (PTJniHelper.isAdNetworkActive("kAdMob") || PTJniHelper.isAdNetworkActive("kFacebook")) {
PTAdAdMobBridge.initBridge(this);
}
if (PTJniHelper.isAdNetworkActive("kAppLovin")) {
PTAdAppLovinBridge.initBridge(this);
}
if (PTJniHelper.isAdNetworkActive("kLeadBolt")) {
PTAdLeadBoltBridge.initBridge(this);
}
if (PTJniHelper.isAdNetworkActive("kVungle")) {
PTAdVungleBridge.initBridge(this);
}
if (PTJniHelper.isAdNetworkActive("kPlayhaven")) {
PTAdUpsightBridge.initBridge(this);
}
if (PTJniHelper.isAdNetworkActive("kMoPub")) {
PTAdMoPubBridge.initBridge(this);
}
if (PTJniHelper.isAdNetworkActive("kFacebook")) {
PTAdFacebookBridge.initBridge(this);
}
if (PTJniHelper.isAdNetworkActive("kHeyzap")) {
PTAdHeyzapBridge.initBridge(this);
}
}
#Override
public Cocos2dxGLSurfaceView onCreateView() {
Cocos2dxGLSurfaceView glSurfaceView = new Cocos2dxGLSurfaceView(this);
glSurfaceView.setEGLConfigChooser(8, 8, 8, 0, 0, 0);
return glSurfaceView;
}
static {
System.loadLibrary("player");
}
#Override
protected void onResume() {
super.onResume();
if (PTJniHelper.isAdNetworkActive("kChartboost")) {
PTAdChartboostBridge.onResume( this );
}
}
#Override
protected void onStart() {
super.onStart();
if (PTJniHelper.isAdNetworkActive("kChartboost")) {
PTAdChartboostBridge.onStart( this );
}
}
#Override
protected void onStop() {
super.onStop();
if (PTJniHelper.isAdNetworkActive("kChartboost")) {
PTAdChartboostBridge.onStop( this );
}
}
#Override
protected void onDestroy() {
super.onDestroy();
}
}
I'm an engineer at Heyzap. Our SDK will catch exceptions from third party SDKs, and shut down our SDK if we catch one (this is our last line of defense in preventing exceptions from crashing your game). In this case, we're catching this exception:
06-03 21:42:16.023: E/Heyzap(27950): Heyzap encountered a runtime exception and is now disabled. Error: Attempt to invoke virtual method 'java.lang.String android.content.Context.getPackageName()' on a null object reference
We've previously seen this exception caused by an outdated UnityAds SDK. Are you using that network, and if so, can you try UnityAds 1.5.6? If you're not, can you tell us which networks you're using, or the Android package of your game?
Also, I see in yours logs that you're using Heyzap 8.4.1, which was released in June of last year. Can you update to our latest version?
Related
I want to create an AlertDialog inside an IntentService, but when passing the context inside the AlertDialog.Builder constructor it shows me the following error:
06-30 00:01:31.265 11994-11994/com.alwa7y W/System.err: android.view.WindowManager$BadTokenException: Unable to add window -- token null is not for an application
06-30 00:01:31.267 11994-11994/com.alwa7y W/System.err: at android.view.ViewRootImpl.setView(ViewRootImpl.java:572)
at android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:310)
at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:86)
at android.app.Dialog.show(Dialog.java:319)
at com.go.mushaf.mushafapplication.services.DownloadService$override.showAlert(DownloadService.java:176)
at com.go.mushaf.mushafapplication.services.DownloadService$override.access$dispatch(DownloadService.java)
at com.go.mushaf.mushafapplication.services.DownloadService.showAlert(DownloadService.java:0)
at com.go.mushaf.mushafapplication.services.DownloadService$BackGroundTask.onPostExecute(DownloadService.java:88)
at com.go.mushaf.mushafapplication.services.DownloadService$BackGroundTask.onPostExecute(DownloadService.java:61)
at android.os.AsyncTask.finish(AsyncTask.java:651)
at android.os.AsyncTask.access$500(AsyncTask.java:180)
at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:668)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:148)
06-30 00:01:31.268 11994-11994/com.alwa7y W/System.err: at android.app.ActivityThread.main(ActivityThread.java:5451)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
and this is the method that creates the AlertDialog:
public void showAlert(String message, String header) {
if (header.equals(""))
header = "Alert!";
try {
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(getApplicationContext());
// Log.d(TAG, "show: " + alertDialog.getOwnerActivity());
alertDialogBuilder.setTitle(header);
alertDialogBuilder.setMessage(message);
alertDialogBuilder.setPositiveButton("موافق",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
((Activity) context).finish();
dialog.dismiss();
showEndLoadingNotification(context);
}
});
// alertDialogBuilder.show();
alertDialogBuilder.setOnCancelListener(new DialogInterface.OnCancelListener() {
#Override
public void onCancel(DialogInterface dialog) {
((Activity) context).finish();
}
});
AlertDialog alertDialog = alertDialogBuilder.create();
alertDialog.show();
} catch (Exception ignored) {
ignored.printStackTrace();
}//when app trying to display a dialog using a previously finished activity as a context
}
And this is the IntentService class:
package com.go.mushaf.mushafapplication.services;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.IntentService;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.graphics.drawable.Drawable;
import android.os.AsyncTask;
import android.support.annotation.Nullable;
import android.util.Log;
import android.widget.TextView;
import com.bumptech.glide.Glide;
import com.bumptech.glide.RequestBuilder;
import com.bumptech.glide.load.DataSource;
import com.bumptech.glide.load.engine.GlideException;
import com.bumptech.glide.request.RequestListener;
import com.bumptech.glide.request.target.Target;
import com.go.mushaf.mushafapplication.DownloadActivity;
import com.go.mushaf.mushafapplication.MainActivity;
import java.util.ArrayList;
import static com.go.mushaf.mushafapplication.DownloadActivity.BUNDLE;
import static com.go.mushaf.mushafapplication.DownloadActivity.CONTEXT;
import static com.go.mushaf.mushafapplication.DownloadActivity.TEXT_ID;
import static com.go.mushaf.mushafapplication.DownloadActivity.getLoadingText;
import static com.go.mushaf.mushafapplication.DownloadActivity.mTxtProgress;
import static com.go.mushaf.mushafapplication.DownloadActivity.showEndLoadingNotification;
import static com.go.mushaf.mushafapplication.Utility.getPages;
public class DownloadService extends IntentService {
public int viewId;
Context context;
public static final String TAG = "servicee";
public DownloadService() {
super("DownloadService");
}
#Override
protected void onHandleIntent(Intent intent) {
if (intent.hasExtra(BUNDLE)) {
viewId = intent.getBundleExtra(BUNDLE).getInt(TEXT_ID);
Log.d(TAG, "onHandleIntent: ");
}
new BackGroundTask().execute();
}
#Override
public int onStartCommand(#Nullable Intent intent, int flags, int startId) {
context = getApplicationContext();
return super.onStartCommand(intent, flags, startId);
}
public class BackGroundTask extends AsyncTask<Void, Integer, Void> {
private final String ASYNC_ERROR = this.getClass().getName();
private RequestBuilder<Drawable> x;
private ArrayList<String> pagesList = getPages();
#Override
protected Void doInBackground(Void... arg0) {
// FIXME: 6/27/2018
doAllCache(mTxtProgress);
return null;
}
#Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
}
#Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);
// if(x!=null) {
// x.preload();
//// if (!cancelFlag || count < MainActivity.mushafTotal)
//// new BackGroundTask().execute(++count);
// }
showAlert("تم اكتمال التحميل بنجاح", "تم التحميل");
// getApplicationContext(), unable to add window
// DownladService.this, unable to add window
// getBaseContext(), unable to add window
}
private void doAllCache(final TextView mTxtProgress) {
Log.d(TAG, "doAllCache: " + mTxtProgress.getText().toString());
Log.d(TAG, "doAllCache: " + pagesList.size());
for (int i=0; i<pagesList.size(); i++) {
String pageNumber = pagesList.get(i); //get string for page number
Log.d(TAG, "doAllCache: " + pageNumber);
String url = MainActivity.mainUril + pageNumber + ".gif"; // get page url
final int finalI = i;
x = Glide.with(DownloadService.this)
.load(url)
.listener(new RequestListener<Drawable>() {
#Override
public boolean onResourceReady(Drawable resource, Object model, Target<Drawable> target, DataSource dataSource, boolean isFirstResource) {
// Log.i("Image Loading End", String.valueOf(i));
mTxtProgress.setText(getLoadingText(getApplicationContext(), finalI));
Log.d(TAG, "onResourceReady: " + resource +"\n"+model.toString()+"\n"+target+"\n"+dataSource);
//// //check cancel
//// if (cancelFlag) {
//// finish();
//// } else {
//
// if (finalI < MainActivity.mushafTotal) {
// final int ii = finalI + 1;
// new BackGroundTask().execute();
//
//// new Handler().postDelayed(new Runnable() {
//// #Override
//// public void run() {//Use your "bitmap" here
//// doAllCache(ii);
//// }
//// }, 100);
// }
//// else{
//// cancelFlag = true;
//// }
//// }
return true;
}
#Override
public boolean onLoadFailed(#Nullable GlideException e, Object model, Target target, boolean isFirstResource) {
Log.d(ASYNC_ERROR, String.valueOf(finalI));
Log.d(ASYNC_ERROR, "onLoadFailed: " + e);
return false;
}
});
}
}
}
public void showAlert(String message, String header) {
if (header.equals(""))
header = "Alert!";
try {
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(getApplicationContext());
// Log.d(TAG, "show: " + alertDialog.getOwnerActivity());
alertDialogBuilder.setTitle(header);
alertDialogBuilder.setMessage(message);
alertDialogBuilder.setPositiveButton("موافق",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
((Activity) context).finish();
dialog.dismiss();
showEndLoadingNotification(context);
}
});
// alertDialogBuilder.show();
alertDialogBuilder.setOnCancelListener(new DialogInterface.OnCancelListener() {
#Override
public void onCancel(DialogInterface dialog) {
((Activity) context).finish();
}
});
AlertDialog alertDialog = alertDialogBuilder.create();
alertDialog.show();
} catch (Exception ignored) {
ignored.printStackTrace();
}//when app trying to display a dialog using a previously finished activity as a context
}
}
and this is how I start the service:
#Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.download_btn:
startLoadingNotification();
Bundle bundle = new Bundle();
bundle.putInt(TEXT_ID, R.id.txt_load);
// bundle.putSerializable(CONTEXT, (Serializable) DownloadActivity.this);
startService(new Intent(DownloadActivity.this, DownloadService.class).putExtra(BUNDLE, bundle));
mViewDownload.setVisibility(View.GONE);
mViewCancel.setVisibility(View.VISIBLE);
break;
case R.id.cancel_btn:
createLogoutDialog().show();
break;
}
}
I want to show the dialog in the onPostExecute method.
I have tried:
getApplicationContext(), DownloadService.this, this, getBaseContext()
all of the above give the same error.
Thanks in advance.
You cannot show an AlertDialog from a Service. You can only show an AlertDialog from an Activity. In this case, show the dialog from the activity that is starting this service. Or, do not use a dialog, but instead use a Notification.
Beyond that:
Do not do asynchronous things inside of an IntentService, as the service goes away as soon as onHandleIntent() returns. Once the service goes away, your process might terminate, killing your background threads before the work is done. Remove BackGroundTask and move all of its logic to be executed from onHandleIntent(). Also, get rid of Glide or figure out how to have it download images synchronously (which, AFAIK, it cannot do).
IntentService will not work well on Android 8.0+ unless you make it be a foreground service and use startForegroundService(). Consider using JobIntentService or, in 2019 and beyond, WorkManager.
Made a game with Libgdx and eventually got GPGS Leaderboard and Achievements to work. Or so I thought.
They run fine on my phone and tablet when I install the APK directly through Android Studio but it won't allow users to sign in when they have downloaded the game from Google Play Store.
Failed to sign in. Please check your network connection and try again
The SHA-1 matches in console.developers.google.com/apis/credentials/oauthclient/ and gradle.
Leaderboards etc have all been published days ago.
What have I forgotten to do? Is there a new SHA-1 I should add to developer console that I don't know how to find? I'm "certain" I've covered all the basics illustrated in other questions on SO.
I am thinking/hoping it is something in the developer console I've forgotten/missed.
Here's AndroidLauncher though just in case I'm wrong about that, thanks in advance:
package com.weavernap.chuggydodge;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.graphics.Color;
import android.os.Bundle;
import android.support.multidex.MultiDex;
import android.view.View;
import android.widget.RelativeLayout;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.backends.android.AndroidApplication;
import com.badlogic.gdx.backends.android.AndroidApplicationConfiguration;
import com.google.android.gms.ads.AdRequest;
import com.google.android.gms.ads.AdSize;
import com.google.android.gms.ads.AdView;
import com.google.android.gms.ads.InterstitialAd;
import com.google.android.gms.ads.MobileAds;
import com.google.android.gms.games.Games;
import com.google.example.games.basegameutils.GameHelper;
import com.weavernap.cdHelpers.AdsController;
public class AndroidLauncher extends AndroidApplication implements GameHelper.GameHelperListener, AdsController {
protected void attachBaseContext(Context base) {
super.attachBaseContext(base);
MultiDex.install(this);
}
private static final String BANNER_AD_UNIT_ID = "ca-app-pub-3737397260010456/7958274520";
private static final String INTERSTITIAL_AD_UNIT_ID = "ca-app-pub-3737397260010456/3314422124";
protected AdView adView;
private InterstitialAd interstitialAd;
protected View gameView;
private GameHelper gameHelper;
// private AdsController adsController;
// private GoogleApiClient mGoogleApiClient;
private SharedPreferences prefs;
private boolean writeLogs = true;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
MobileAds.initialize(getApplicationContext(), "ca-app-pub-3737397260010456~9090257326");
AndroidApplicationConfiguration config = new AndroidApplicationConfiguration();
RelativeLayout relativeLayout = new RelativeLayout(this);
relativeLayout.setLayoutParams(new RelativeLayout.LayoutParams(-1, -1));
AdView adView = this.createAdView();
relativeLayout.addView(adView);
relativeLayout.addView(this.createGameView(config));
this.setContentView(relativeLayout);
this.startAdvertising(adView);
this.interstitialAd = new InterstitialAd(this);
this.interstitialAd.setAdUnitId(INTERSTITIAL_AD_UNIT_ID);
if (this.gameHelper == null) {
this.gameHelper = new GameHelper(this, 1);
this.gameHelper.enableDebugLog(this.writeLogs);
}
this.gameHelper.setup(this);
//
// // Create a gameView and a bannerAd AdView
// View gameView = initializeForView(new CDGame(this), config);
// setupAds();
// // Define the layout
// RelativeLayout layout = new RelativeLayout(this);
// layout.addView(gameView, ViewGroup.LayoutParams.MATCH_PARENT,
// ViewGroup.LayoutParams.MATCH_PARENT);
// RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(
// ViewGroup.LayoutParams.MATCH_PARENT,
// ViewGroup.LayoutParams.WRAP_CONTENT);
// params.addRule(RelativeLayout.ALIGN_PARENT_TOP);
// layout.addView(bannerAd, params);
//
// setContentView(layout);
}
#Override
public void onStart() {
super.onStart();
gameHelper.onStart(this);
}
#Override
public void onStop() {
super.onStop();
gameHelper.onStop();
}
#Override
public void onActivityResult(int request, int response, Intent data) {
super.onActivityResult(request, response, data);
gameHelper.onActivityResult(request, response, data);
}
#Override
public void showOrLoadInterstitial(final boolean showAd) {
try {
this.runOnUiThread(new Runnable() {
public void run() {
if (AndroidLauncher.this.interstitialAd.isLoaded() && showAd) {
AndroidLauncher.this.interstitialAd.show();
return;
} //else
{
AdRequest adRequest = new AdRequest.Builder().build();
AndroidLauncher.this.interstitialAd.loadAd(adRequest);
}
}
});
return;
} catch (Exception e) {
Gdx.app.log("ChuggerDodge.ERROR", "Exception in showOrLoadInterstitial:" + e.toString());
return;
}
}
#Override
public void submitScoreGPGS(int score) {
if (this.getSignedInGPGS()) {
Games.Leaderboards.submitScore(this.gameHelper.getApiClient(), this.getString(R.string.leaderboard_top_scores), score);
}
}
#Override
public void unlockAchievementGPGS(int score) {
if (this.getSignedInGPGS()) {
if (score == 0) {
Games.Achievements.unlock(this.gameHelper.getApiClient(),
this.getString(R.string.achievement_the_every_loser_wins_trophy));
}
if (score > 3) {
Games.Achievements.unlock(this.gameHelper.getApiClient(),
this.getString(R.string.achievement_not_completely_useless));
}
if (score > 19) {
Games.Achievements.unlock(this.gameHelper.getApiClient(),
this.getString(R.string.achievement_hey_youre_all_right_you_are_));
}
if (score == 42) {
Games.Achievements.unlock(this.gameHelper.getApiClient(),
this.getString(R.string.achievement_the_hyperintelligent_pandimensional_being_prize));
}
if (score > 43) {
Games.Achievements.unlock(this.gameHelper.getApiClient(),
this.getString(R.string.achievement_wowzers__youre_about_as_good_as_me_now_));
}
if (score > 76) {
Games.Achievements.unlock(this.gameHelper.getApiClient(),
this.getString(R.string.achievement_actually_thats_quite_impressive_));
}
}
}
#Override
public void getGPGSLeaderboard() {
if (this.gameHelper.isSignedIn()) {
this.startActivityForResult(Games.Leaderboards.getLeaderboardIntent(this.gameHelper.getApiClient(), this.getString(R.string.leaderboard_top_scores)), 100);
return;
} else {
if (this.gameHelper.isConnecting()) return;
{
this.loginGPGS();
return;
}
}
}
#Override
public boolean getSignedInGPGS() {
if (this.gameHelper != null) {
System.out.println("Superduperdavid");
return this.gameHelper.isSignedIn();
}
System.out.println("Nah");
return false;
}
//
#Override
public void loginGPGS() {
// if (!gameHelper.isSignedIn()) {
try {
runOnUiThread(new Runnable() {
public void run() {
gameHelper.beginUserInitiatedSignIn();
}
});
return;
} catch (final Exception ex) {
Gdx.app.log("MainActivity", "Log in failed: " + ex.getMessage() + ".");
return;
}
//
}
//
#Override
public void getAchievementsGPGS() {
// if (gameHelper.isSignedIn()) {
startActivityForResult(Games.Achievements.getAchievementsIntent(gameHelper.getApiClient()), 101);
// } else if (!gameHelper.isConnecting()) {
// loginGPGS();
// }
}
//Following from toaster code
private AdView createAdView() {
this.adView = new AdView(this);
this.adView.setAdSize(AdSize.SMART_BANNER);
this.adView.setAdUnitId(BANNER_AD_UNIT_ID);
RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(-1, -2);
layoutParams.addRule(12, -1);
layoutParams.addRule(14, -1);
this.adView.setLayoutParams(layoutParams);
this.adView.setBackgroundColor(Color.TRANSPARENT);
return this.adView;
}
private View createGameView(AndroidApplicationConfiguration androidApplicationConfiguration) {
this.gameView = this.initializeForView(new CDGame(this), androidApplicationConfiguration);
RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(-1, -2);
layoutParams.addRule(10, -1);
layoutParams.addRule(14, -1);
layoutParams.addRule(2, this.adView.getId());
this.gameView.setLayoutParams(layoutParams);
return this.gameView;
}
private void startAdvertising(AdView adView) {
adView.loadAd(new AdRequest.Builder().build());
}
#Override
public void onDestroy() {
if (this.adView != null) {
this.adView.destroy();
}
super.onDestroy();
}
#Override
public void onPause() {
if (this.adView != null) {
this.adView.pause();
}
super.onPause();
}
#Override
public void onResume() {
super.onResume();
if (this.adView != null) {
this.adView.resume();
}
}
#Override
public void onSignInFailed() {
gameHelper.getSignInError();
}
#Override
public void onSignInSucceeded() {
}
}
Okay, so at some point I had entered the debug SHA-1 into the developer console to get GPGS working during testing. But did not realise that you had to revert back to the original.
So following this and making the changes in the console did the trick pretty much straight away.
I'm attempting to use the class PurchaseManagerAndroidAmazon to handle purchases for my libdx project. The following are within the interface to access the android methods from within the core project:
public void createPurchaseSystem();
public void getPurchaseUpdates();
public void getUserInformation();
public void purchaseItem(String id);
These are the actual methods within the AndroidApplication:
PurchaseManagerAndroidAmazon pm;
#Override
protected void onResume() {
Log.d(TAG, "onResume");
if(pm != null) {
getUserInformation();
getPurchaseUpdates();
}
super.onResume();
}
#Override
public void purchaseItem(String id) {
Log.d(TAG, "purchaseItem");
pm.purchase(id);
}
#Override
public void getUserInformation() {
Log.d(TAG, "getUserInformation");
if(pm == null)
createPurchaseSystem();
PurchasingService.getUserData();
}
#Override
public void getPurchaseUpdates() {
Log.d(TAG, "getPurchaseUpdates");
if(pm == null)
createPurchaseSystem();
PurchasingService.getPurchaseUpdates(true);
}
#Override
public void createPurchaseSystem() {
Log.d(TAG, "createPurchaseSystem");
if(pm == null)
pm = new PurchaseManagerAndroidAmazon(this, 0);
PurchaseManagerConfig config = new PurchaseManagerConfig();
config.addOffer(new Offer().setType(OfferType.CONSUMABLE).setIdentifier(getString(R.string.min_id)));
config.addOffer(new Offer().setType(OfferType.CONSUMABLE).setIdentifier(getString(R.string.med_id)));
config.addOffer(new Offer().setType(OfferType.CONSUMABLE).setIdentifier(getString(R.string.max_id)));
pm.install(new PurchaseObserver() {
#Override
public void handleInstall() {
Log.d(TAG, "PurchaseSystem installed");
PurchaseSystem.purchaseRestore();
}
#Override
public void handleInstallError(Throwable err) {
Log.e(TAG, "ERROR PurchaseObserver: handleInstallError!: " + err.getMessage());
throw new GdxRuntimeException(err);
}
#Override
public void handlePurchase(Transaction transaction) {
Log.d(TAG, "PurchaseSystem handlePurchase: " + transaction.toString());
pm.purchaseRestore();
}
#Override
public void handlePurchaseCanceled() {
Log.d(TAG, "PurchaseSystem handlePurchaseCanceled");
}
#Override
public void handlePurchaseError(Throwable err) {
Log.d(TAG, "ERROR PurchaseObserver: handlePurchaseError!: " + err.getMessage());
throw new GdxRuntimeException(err);
}
#Override
public void handleRestore(Transaction[] transactions) {
Log.d(TAG, "PurchaseSystem handleRestore: " + transactions.toString());
}
#Override
public void handleRestoreError(Throwable err) {
Log.d(TAG, "ERROR PurchaseObserver: handleRestoreError!: " + err.getMessage());
throw new GdxRuntimeException(err);
}
}, config, true);
}
And this is within the core project:
HighPoint highPoint; // this class extends Game of libgdx
public void createDonationScreen() {
if(!purchaseSytemCreated)
createPurchaseSystem();
TextButton minDonButton = new TextButton(....);
medDonButton.addListener(new ClickListener() {
#Override
public void clicked(InputEvent event, float x, float y) {
highPoint.hpaInterface.getPurchaseUpdates();
highPoint.hpaInterface.purchaseItem(MIN_ID);
}
});
Using the Amazon App Tester gives me the error
failed to call PurchasingService.getPurchaseUpdates()
but as you can tell its being called mulitple times. I feel I've put in too many times actually. The Amazon dialog pops up asking me to confirm the purchase when I click the button so it seems like it should work either way.
Any ideas would be greatly appreciated.
Adding call to PurchasingService.getPurchaseUpdates(false) in activity onResume callback solved the notification issue in my case.
I have been asking questions related to my Libgdx game Google play game services configuration error. Up-till now I have solved sign in errors but Now I am stuck at Unlock Achievements. So I am posting my code may Be some one can help me out then.
Here Is my ActionResolver Interface That I created In Core Libgdx project
package com.------.game;
public interface ActionResolver {
public boolean getSignedInGPGS();
public void loginGPGS();
public void submitScoreGPGS(int score);
public void unlockAchievementGPGS(String achievementId);
public void getLeaderboardGPGS();
public void getAchievementsGPGS();
public void onShowAchievementsRequested() ;
}
My AndroidLauncher class is
package com.------.game.android;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.widget.Toast;
import com.badlogic.gdx.Game;
import com.badlogic.gdx.backends.android.AndroidApplication;
import com.badlogic.gdx.backends.android.AndroidApplicationConfiguration;
import com.google.android.gms.analytics.GoogleAnalytics;
import com.google.android.gms.analytics.HitBuilders;
import com.google.android.gms.analytics.Tracker;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.games.Games;
import com.google.android.gms.plus.Plus;
import com.google.example.games.basegameutils.BaseGameUtils;
import com.google.example.games.basegameutils.GameHelper;
import com.google.example.games.basegameutils.GameHelper.GameHelperListener;
import com.-----.game.ActionResolver;
import com.-----.game.MainGame;
public class AndroidLauncher extends AndroidApplication implements
ActionResolver, GameHelperListener , GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener
{
private GameHelper gameHelper;
private GoogleApiClient client;
private Exception e;
final String TAG = "TanC";
private boolean mResolvingConnectionFailure = false;
// Has the user clicked the sign-in button?
private boolean mSignInClicked = false;
// Automatically start the sign-in flow when the Activity starts
private boolean mAutoStartSignInFlow = true;
// request codes we use when invoking an external activity
// private static final int RC_RESOLVE = 5000;
private static final int RC_UNUSED = 5001;
private static final int RC_SIGN_IN = 9001;
// tag for debug logging
final boolean ENABLE_DEBUG = true;
// playing on hard mode?
boolean mHardMode = false;
private int Score;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Score= 100;
client = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(Plus.API).addScope(Plus.SCOPE_PLUS_LOGIN)
.addApi(Games.API).addScope(Games.SCOPE_GAMES)
.build();
GameHelper.GameHelperListener gameHelperListener = new GameHelper.GameHelperListener() {
#Override
public void onSignInFailed() {
Log.i("Game Helper", "Sign in failed");
}
#Override
public void onSignInSucceeded() {
Log.i("Game Helper", "Sign in succeeded");
}
};
if (gameHelper == null) {
gameHelper = new GameHelper(this, GameHelper.CLIENT_GAMES);
gameHelper.enableDebugLog(true);
}
AndroidApplicationConfiguration config = new AndroidApplicationConfiguration();
initialize(new MainGame(this), config); // or initialize (game,
// config);
// gameHelper.setPlusApiOptions(PlusOptions.builder().build());
// no title is needed
gameHelper.setup(gameHelperListener );
// gameHelper.setup(gameHelperListener );
}
#Override
public void onStart() {
super.onStart();
gameHelper.onStart(this);
client.connect();
}
#Override
public void onStop() {
super.onStop();
// ...
gameHelper.onStop();
if (client.isConnected()) {
client.disconnect();
}
}
#Override
public void loginGPGS() {
try {
runOnUiThread(new Runnable() {
public void run() {
gameHelper.beginUserInitiatedSignIn();
}
});
} catch (final Exception ex) {
e.printStackTrace ();
}
}
#Override
public void unlockAchievementGPGS(String achievementId) {
if ( getSignedInGPGS()) {
if(Score>=100){
unlockAchievementGPGS("ABC-------");
}
Games.Achievements.unlock(client, getString(R.string.achievement_Trekker));
}
}
#Override
public void getLeaderboardGPGS() {
}
#Override
public void getAchievementsGPGS() {
if (gameHelper.isSignedIn()) {
startActivityForResult(
Games.Achievements.getAchievementsIntent(gameHelper
.getApiClient()), 101);
} else if (!gameHelper.isConnecting()) {
loginGPGS();
}
}
#Override
public void submitScoreGPGS( int score) {
submitScoreGPGS(Score);
// game.actionResolver.submitScoreGPGS(world.score);
}
#Override
public void onActivityResult(int request, int response, Intent data) {
super.onActivityResult(request, response, data);
gameHelper.onActivityResult(request, response, data);
}
#Override
public boolean getSignedInGPGS() {
return gameHelper.isSignedIn();
}
private boolean isSignedIn() {
return (client!= null && client.isConnected());
}
#Override
public void onShowAchievementsRequested() {
if (isSignedIn()) {
startActivityForResult(Games.Achievements.getAchievementsIntent(client),
RC_UNUSED);
} else {
BaseGameUtils.makeSimpleDialog(this, getString(R.string.achievement_Trekker)).show();
}
}
#Override
public void onSignInFailed() {
}
#Override
public void onSignInSucceeded() {
}
#Override
public void onConnectionFailed(ConnectionResult arg0) {
Log.d(TAG, "onConnectionFailed(): attempting to resolve");
/* if (mResolvingConnectionFailure) {
Log.d(TAG, "onConnectionFailed(): already resolving");
return;
}
if (mSignInClicked || mAutoStartSignInFlow) {
mAutoStartSignInFlow = false;
mSignInClicked = false;
mResolvingConnectionFailure = true;
if (!BaseGameUtils.resolveConnectionFailure(this, client, connectionResult,
RC_SIGN_IN, getString(R.string.unknown_error))) {
mResolvingConnectionFailure = false;
}*/
}
#Override
public void onConnected(Bundle arg0) {
Log.i("Google API", "onConnected(): connected to Google APIs");
}
#Override
public void onConnectionSuspended(int arg0) {
Log.d(TAG, "onConnectionSuspended(): attempting to connect");
client.connect();
}
}
This score int that has a value of 100 I just tried to test if it helps to unlock achievement.
My MainGame class in Core project is
package com.----------.game;
import com.badlogic.gdx.Application.ApplicationType;
import com.badlogic.gdx.Game;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.-------.helpers.AssetLoader;
import com.------.screens.FirstSplash;
public class MainGame extends Game {
SpriteBatch batch;
Texture img;
public ActionResolver actionResolver;
Game game;
public MainGame(ActionResolver actionresolver) {
this.actionResolver = actionresolver;
}
#Override
public void create() {
Gdx.app.log("Game", "created");
AssetLoader.load();
setScreen(new FirstSplash(this));
}
public void show() {
Gdx.app.log("my Splash Screen", "show called");
if (Gdx.app.getType() == ApplicationType.Android) {
actionResolver.getSignedInGPGS();
actionResolver.submitScoreGPGS(110);
actionResolver.unlockAchievementGPGS("ABC-----");
} else {
actionResolver.loginGPGS();
}
}
#Override
public void dispose() {
super.dispose();
AssetLoader.dispose();
}
}
My Android Manifest File is
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.--------.game.android"
android:versionCode="2"
android:versionName="1.1" >
<uses-sdk android:minSdkVersion="11" android:targetSdkVersion="20" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<application
android:allowBackup="true"
android:icon="#drawable/smallicon"
android:label="#string/app_name"
android:theme="#style/GdxTheme"
android:name="com.---------.game.android.MyApplication">
<meta-data android:name="com.google.android.gms.games.APP_ID" android:value="#string/app_id" />
<meta-data android:name="com.google.android.gms.version"
android:value="#integer/google_play_services_version"/>
<activity
android:name="com.outofboxapps.game.android.AndroidLauncher"
android:label="#string/app_name"
android:screenOrientation="landscape"
android:configChanges="keyboard|keyboardHidden|orientation|screenSize">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
My Strings File in Android/Res folder has this
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">My Game</string>
<string name="app_id">------------</string> // has my app id
</resources>
My Logcat says this when I run my app in Debug Mode(Note: I have already configured Google play game services on Developer console| My game is already published without Game services in First Version so to test Game services I have published my Game services in Alpha. I have successfully added testers. I am able to sign in with test account. I also have Dubug plus release certificates Client ID)
03-11 10:28:49.823: I/my Spash Screen(16750): constructor called
03-11 10:28:49.829: I/my Splash Screen(16750): hide called
03-11 10:28:49.830: I/my Splash Screen(16750): rendered 2 times.
03-11 10:28:49.830: I/my Splash Screen(16750): show called
03-11 10:28:50.030: D/GameHelper(16750): GameHelper: onConnected: connected!
03-11 10:28:50.038: D/GameHelper(16750): GameHelper: succeedSignIn
03-11 10:28:50.044: D/GameHelper(16750): GameHelper: Notifying LISTENER of sign-in SUCCESS
03-11 10:28:52.837: I/my Spash Screen(16750): constructor called
03-11 10:28:52.869: I/my Splash Screen(16750): hide called
03-11 10:28:52.869: I/my Splash Screen(16750): rendered 180 times.
03-11 10:28:57.361: I/GameScreen(16750): show called
03-11 10:28:57.361: I/GameScreen(16750): resizing
Now I dont get it. when I am SUCCESSFULLY CONNECTED why i cant do anything else in game services. I just have achievements that I need to unlock on a particular score.
Using all LIBGDX game tutorials, Google Type a number and trival exmaple and tutorial I feel hopeless now that I cant configure these game services at all.
I was also sending my scores at game over from gamescreen class but removed it now because it simply generate Null pointer exception on Sign in(to google game services). I can post that code as well
if (Gameover ----) {
if ((game.actionResolver.getSignedInGPGS())) { // My app crashes at this point ton check Sign in by giving Null pointer exception
game.actionResolver.submitScoreGPGS(AssetLoader.getScore);
if (AssetLoader.getScore >= 2500) game.actionResolver.unlockAchievementGPGS("-----"); // my id is here
}
}
KINDLY ANYBODY WHO HAS DONE THIS SUCCESSFULLY. hELP ME OUT.
Take a look at your loginGPGS() method in your launcher class...You can successfully connect because loginGPGS is run on the ui thread....Try accessing GPGS on the ui thread because it needs to be run in the context of your Main activity....This is how I access mine:
#Override
public void getLeaderboardGPGS() {
try {
runOnUiThread(new Runnable() {
public void run() {
if (gameHelper.isSignedIn()) {
startActivityForResult(
Games.Leaderboards.getLeaderboardIntent(
gameHelper.getApiClient(),
"XXXXXXXXXX-XXX-XXX"), 100);
} else if (!gameHelper.isConnecting()) {
loginGPGS();
}
}
});
} catch (final Exception ex) {
}
}
#Override
public void sendScoreGPGS() {
try {
runOnUiThread(new Runnable() {
public void run() {
if (gameHelper.isSignedIn()) {
startActivityForResult(
Games.Leaderboards.submitScore(gameHelper.getApiClient(),
"YOUR-GPGS-HASH", score);
} else if (!gameHelper.isConnecting()) {
loginGPGS();
}
}
});
} catch (final Exception ex) {
}
}
I want to cancel running AsyncTask (in AsyncTaskLoader) when the user clicks the home button. Here is what I created so far:
package cz.davidliska.android.loaders;
import java.text.SimpleDateFormat;
import java.util.Date;
import android.content.Context;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.LoaderManager;
import android.support.v4.content.AsyncTaskLoader;
import android.support.v4.content.Loader;
import android.util.Log;
public class MainActivity extends FragmentActivity implements LoaderManager.LoaderCallbacks<Date> {
private static final String TAG = "loader";
private Date date;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
LoaderManager.enableDebugLogging(true);
getSupportLoaderManager().initLoader(0, savedInstanceState, this);
}
private static class DateLoader extends AsyncTaskLoader<Date> {
public static final String STATE_DATE_LOADER = "dateloader.state";
private Date mDate;
public DateLoader(Context context, Bundle savedInstanceState) {
super(context);
if (savedInstanceState != null) {
long timeStamp = savedInstanceState.getLong(STATE_DATE_LOADER);
if (timeStamp != 0L) mDate = new Date(timeStamp);
}
}
#Override
protected void onStartLoading() {
Log.d(TAG, "Loader.onStartLoading()");
if (mDate != null) {
deliverResult(mDate);
} else {
forceLoad();
}
}
#Override
public void deliverResult(Date data) {
super.deliverResult(data);
Log.d(TAG, "Loader.deliverResult()");
mDate = data;
}
#Override
protected void onStopLoading() {
super.onStopLoading();
cancelLoad(); // try to cancel AsyncTask
Log.d(TAG, "Loader.onStopLoading()");
}
#Override
protected void onForceLoad() { // overridden in AsyncTaskLoader
super.onForceLoad();
Log.d(TAG, "Loader.onForceLoad()");
}
#Override
protected void onReset() {
super.onReset();
mDate = null;
Log.d(TAG, "Loader.onForceLoad()");
}
#Override
public void onContentChanged() {
super.onContentChanged();
Log.d(TAG, "Loader.onContentChanged()");
}
#Override
protected void onAbandon() {
super.onAbandon();
Log.d(TAG, "Loader.onContentChanged()");
}
#Override
public Date loadInBackground() { // AsyncTaskLoader only
Log.d(TAG, "Loader.loadInBackground()");
try {
// there will be some HttpClient.execute()
while(true) {
Thread.sleep(100);
Log.d(TAG, "Loader.loadInBackground() still running");
}
} catch (InterruptedException e) {
Log.d(TAG, "Loader.loadInBackground() interupted");
}
Log.d(TAG, "Loader.loadInBackground() finished");
return new Date();
}
#Override
public void onCanceled(Date data) { // AsyncTaskLoader only
super.onCanceled(data);
Log.d(TAG, "Loader.onCanceled()");
}
#Override
protected Date onLoadInBackground() { // AsyncTaskLoader only
Log.d(TAG, "Loader.onContentChanged()");
return super.onLoadInBackground();
}
#Override
public void abandon() {
Log.d(TAG, "Loader.abandon()");
super.abandon();
}
#Override
public boolean cancelLoad() {
Log.d(TAG, "Loader.cancelLoad()");
return super.cancelLoad();
}
#Override
public void forceLoad() {
Log.d(TAG, "Loader.forceLoad()");
super.forceLoad();
}
#Override
public boolean isAbandoned() {
Log.d(TAG, "Loader.isAbandoned()");
return super.isAbandoned();
}
#Override
public boolean isReset() {
Log.d(TAG, "Loader.isReset()");
return super.isReset();
}
#Override
public boolean isStarted() {
Log.d(TAG, "Loader.isStarted()");
return super.isStarted();
}
#Override
public void reset() {
Log.d(TAG, "Loader.reset()");
super.reset();
}
#Override
public void stopLoading() {
Log.d(TAG, "Loader.stopLoading()");
super.stopLoading();
}
#Override
public boolean takeContentChanged() {
Log.d(TAG, "Loader.takeContentChanged()");
return super.takeContentChanged();
}
}
#Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
if (date != null)
outState.putLong(DateLoader.STATE_DATE_LOADER, date.getTime());
}
public Loader<Date> onCreateLoader(int id, Bundle args) {
Log.d(TAG, "LoaderCallback.onCreateLoader()");
if (args != null) Log.d(TAG, "bundle: " + args.getLong(DateLoader.STATE_DATE_LOADER));
return new DateLoader(this, args);
}
public void onLoadFinished(Loader<Date> loader, Date data) {
Log.d(TAG, "LoaderCallback.onLoadFinished(): " + new SimpleDateFormat("dd/MM/yyyy").format(data));
date = data;
}
public void onLoaderReset(Loader<Date> loader) {
Log.d(TAG, "LoaderCallback.onLoaderReset()");
}
}
So in onStopLoading() i am calling cancelLoad(), which i think should cancel current task, but AsyncTask in AsyncTaskLoader is still running (while loop in loadInBackground() is still in progress).
The problem is maybe in cancelLoad() method in "java.android.support.v4.content.AsyncTaskLoader.java", where mTask.cancel(boolean) is called with "false" in arguments:
public boolean cancelLoad() {
...
boolean cancelled = mTask.cancel(false);
Is there any chance to cancel running AsyncTask in AsyncTaskLoader?
If you mean "Is there any chance to cancel running AsyncTask in android.content.AsyncTaskLoader?" the answer is yes: you just need to add some "cancel points" in your loadInBackground method and check whether a cancellation request has been issued (isLoadInBackgroundCanceled() == true), then either return or throw an OperationCanceledException).
The support library version of AsyncTaskLoader you are using though doesn't seem to fully implement cancellation at this time (not in mid-flight at least, and a cursory comparison of the framework and of the support version of Loader seems to suggest that cancellation might not be supported at all...).
http://developer.android.com/reference/android/content/Loader.html
http://developer.android.com/reference/android/support/v4/content/Loader.html
Two ways to alleviate the problem come to my mind:
create two implementations of your Loader (one using the framework for API level 11 and above, and one without the cancel feature for older devices)
create an android.support.v4.content.Loader subclass and handle each AsyncTask and cancellation request yourself
public boolean cancelLoad() {
...
boolean cancelled = mTask.cancel(false);
}
#Override
public Date loadInBackground() { // AsyncTaskLoader only
Log.d(TAG, "Loader.loadInBackground()");
try {
// there will be some HttpClient.execute()
while(true) {
Thread.sleep(100);
Log.d(TAG, "Loader.loadInBackground() still running");
if(cancelled) <---------
return new Date(); <----------
}
} catch (InterruptedException e) {
Log.d(TAG, "Loader.loadInBackground() interupted");
}
Log.d(TAG, "Loader.loadInBackground() finished");
return new Date();
}