I programmed an app named "Trumple Run" for android. Like the name says it is a Jump & Run game and I want to release it soon. Before that I would like to implement Interstitial Ads from AdMob. I followed the official guide for the implementation of Ads but the app always crashes when I tried to show the add. Here is some code from my MainActivity (info: I cut out code which is not relevant for the issue; the method addzeigen() is called from another class)
public class Main_activity extends Activity {
private InterstitialAd mInterstitial;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); //Fullscreen
DisplayMetrics metrics = getResources().getDisplayMetrics(); //Display größe herausfinden
V.Bildbreite = metrics.widthPixels;
V.Bildhöhe = metrics.heightPixels;
addladen();
V.v = new View(this);
setContentView(V.v);
}
public void addladen(){
mInterstitial = new InterstitialAd(this);
mInterstitial.setAdUnitId("ca-app-pub-3940256099942544/1033173712");
AdRequest request = new AdRequest.Builder().build();
mInterstitial.loadAd(request);
}
public void addzeigen(){
if(mInterstitial.isLoaded()){
mInterstitial.show();
addladen();
}
}
I looked at the StackTrace to find the reason for the issue and this two lines indicated that the interstitial is not yet instantiated (returning a null value).
java.lang.NullPointerException: Attempt to invoke virtual method 'boolean com.google.android.gms.ads.InterstitialAd.isLoaded()' on a null object reference
Because of that I added a null checker in my addladen() method to prevent a crash.
public void addzeigen(){
if(mInterstitial != null && mInterstitial.isLoaded()){
mInterstitial.show();
addladen();
}
}
But why is my Interstitial object null? Did I not instantiate it in the right way in my addladen() method? I already searched for a long time in the internet but found no solution and asked the AdMob support but they said I should ask here because it is an implementation problem. How do I have to modify my code to make sure that my Interstitial is not null? I would be really happy if you could help me.
create application to when open app, add immidiate load
public class MyApplication extends Application {
public InterstitialAd mInterstitialAd;
private AppOpenManager appOpenAdManager;
private Activity currentActivity;
private int check = 0;
public AdLoader adLoader;
#Override
public void onCreate() {
super.onCreate();
MobileAds.initialize(
this,
new OnInitializationCompleteListener() {
#Override
public void onInitializationComplete(
#NonNull InitializationStatus initializationStatus) {
}
});
appOpenAdManager = new AppOpenManager();
loadInterstitial(AD_UNIT_ID_INTERSTITIAL_ADS);
}
public void loadInterstitial(String id) {
AdRequest adRequest = new AdRequest.Builder().build();
InterstitialAd.load(
this,
id,
adRequest,
new InterstitialAdLoadCallback() {
#Override
public void onAdLoaded(#NonNull InterstitialAd interstitialAd) {
mInterstitialAd = interstitialAd;
interstitialAd.setFullScreenContentCallback(
new FullScreenContentCallback() {
#Override
public void onAdDismissedFullScreenContent() {
mInterstitialAd = null;
}
#Override
public void onAdFailedToShowFullScreenContent(AdError adError) {
// Called when fullscreen content failed to show.
// Make sure to set your reference to null so you don't
// show it a second time.
mInterstitialAd = null;
}
#Override
public void onAdShowedFullScreenContent() {
}
});
}
#Override
public void onAdFailedToLoad(#NonNull LoadAdError loadAdError) {
mInterstitialAd = null;
}
});
}
}
then you create class check exception happen when load and open app
public class LoadInterstitialAds {
private static LoadInterstitialAds instance;
private InterstitialAd mInterstitialAd;
public static LoadInterstitialAds getInstance() {
if (instance == null) {
return new LoadInterstitialAds();
}
return instance;
}
public void openAdsThenOpenActivity(Activity activity, InterstitialAdsListener listener) {
Application application = activity.getApplication();
if (application instanceof MyApplication) {
LoadInterstitialAds.this.mInterstitialAd = ((MyApplication) application).mInterstitialAd;
if (LoadInterstitialAds.this.mInterstitialAd != null) {
LoadInterstitialAds.this.mInterstitialAd.show(activity);
LoadInterstitialAds.this.mInterstitialAd.setFullScreenContentCallback(new FullScreenContentCallback() {
#Override
public void onAdDismissedFullScreenContent() {
listener.onStartActivity();
((MyApplication) application).loadInterstitial(AD_UNIT_ID_INTERSTITIAL_ADS);
}
#Override
public void onAdFailedToShowFullScreenContent(#NonNull AdError adError) {
((MyApplication) application).loadInterstitial(AD_UNIT_ID_INTERSTITIAL_ADS);
listener.onStartActivity();
}
});
} else {
((MyApplication) application).loadInterstitial(AD_UNIT_ID_INTERSTITIAL_ADS);
listener.onStartActivity();
}
}
}
}
create interface listener tothe convenience of calling
public interface InterstitialAdsListener {
void onStartActivity();
}
and finally, run this code at any where you want to show
LoadInterstitialAds loadInterstitialAds = LoadInterstitialAds.getInstance();
loadInterstitialAds.openAdsThenOpenActivity(getActivity(), ()->{
// your process
});
Related
So i recently updated my code with the latest admob SDK and dependencies.
it is supposed to show an interstitial ad before going to the next page.
upon running it the StartActivity is stuck on process dialog and wont go to the next page.
here is the code
//Start Here
AdRequest adRequest = new AdRequest.Builder().build();
InterstitialAd.load(StartActivity.this,StartActivity.this.getString(R.string.main_inter), adRequest,
new InterstitialAdLoadCallback() {
#Override
public void onAdLoaded(#NonNull InterstitialAd interstitialAd) {
// The mInterstitialAd reference will be null until
// an ad is loaded.
pd.dismiss();
mInterstitialAd = interstitialAd;
mInterstitialAd.show(StartActivity.this);
mInterstitialAd.setFullScreenContentCallback(new FullScreenContentCallback(){
#Override
public void onAdClicked() {
// Called when a click is recorded for an ad.
}
#Override
public void onAdDismissedFullScreenContent() {
// Called when ad is dismissed.
// Set the ad reference to null so you don't show the ad a second time.
pd.dismiss();
mInterstitialAd = null;
startActivity(new Intent(StartActivity.this, MainActivity.class));
StartActivity.this.finish();
}
#Override
public void onAdFailedToShowFullScreenContent(AdError adError) {
// Called when ad fails to show.
mInterstitialAd = null;
}
#Override
public void onAdImpression() {
// Called when an impression is recorded for an ad.
}
#Override
public void onAdShowedFullScreenContent() {
// Called when ad is shown.
}
});
}
#Override
public void onAdFailedToLoad(#NonNull LoadAdError loadAdError) {
// Handle the error
mInterstitialAd = null;
}
});
}
});
}
}
You are not dismissing your progress dialog upon onAdDismissedFullScreenContent
#Override
public void onAdDismissedFullScreenContent() {
// Called when ad is dismissed.
// Set the ad reference to null so you don't show the ad a second time.
pd.dismiss()
mInterstitialAd = null;
StartActivity.this.finish();
}
Always remember to handle dialog states, or it can cause window leaks.
Start Activity before finish() is called
#Override
public void onAdDismissedFullScreenContent() {
// Called when ad is dismissed.
// Set the ad reference to null so you don't show the ad a second time.
pd.dismiss()
mInterstitialAd = null;
startActivity(new Intent(StartActivity.this, NextActivity.class));
StartActivity.this.finish();
}
You should dismiss the dialog if the interstitial fails to load or show.
private void openNextPage(ProgressDialog pd){
pd.dismiss();
mInterstitialAd = null;
startActivity(new Intent(StartActivity.this, MainActivity.class));
StartActivity.this.finish();
}
AdRequest adRequest = new AdRequest.Builder().build();
InterstitialAd.load(StartActivity.this,
StartActivity.this.getString(R.string.main_inter),
adRequest, new InterstitialAdLoadCallback() {
#Override
public void onAdLoaded(#NonNull InterstitialAd interstitialAd) {
// The mInterstitialAd reference will be null until
// an ad is loaded.
// Don't dismiss dialog here as we are going to show interstitials now
mInterstitialAd = interstitialAd;
mInterstitialAd.setFullScreenContentCallback(new FullScreenContentCallback() {
#Override
public void onAdClicked() {
// Called when a click is recorded for an ad.
}
#Override
public void onAdDismissedFullScreenContent() {
// Called when ad is dismissed.
openNextPage(pd);
}
#Override
public void onAdFailedToShowFullScreenContent(AdError adError) {
// Called when ad fails to show.
openNextPage(pd);
}
#Override
public void onAdImpression() {
// Called when an impression is recorded for an ad.
}
#Override
public void onAdShowedFullScreenContent() {
// Called when ad is shown.
}
});
mInterstitialAd.show(StartActivity.this);
}
#Override
public void onAdFailedToLoad(#NonNull LoadAdError loadAdError) {
// Handle the error
openNextPage(pd);
}
});
I have an admob ad of the "open ad" type.
Which works when the application is started, and unfortunately the application is often rejected because the advertisement is seen before the content of the application ....
So I put Splash_Activity to appear a little and then the ad appears, the method is effective and the application is accepted.
Problem: When the time I set for Splash_Activity expires, the ad disappears with it without the need to press continue for the application, and in this case the ad remains in the background of the application.
Required: The Splash_Activity screen stops when the ad appears and does not disappear unless you close the ad.
AppOpenManager:
public class AppOpenManager implements LifecycleObserver, Application.ActivityLifecycleCallbacks {
private static final String LOG_TAG = "AppOpenManager";
private static final String AD_UNIT_ID = "ca-app-pub-****/****";
private AppOpenAd appOpenAd = null;
private long loadTime = 0;
private AppOpenAd.AppOpenAdLoadCallback loadCallback;
private Activity currentActivity;
private static boolean isShowingAd = false;
private final GlobalVar Splash_Activity;
/**
* Constructor
*/
public AppOpenManager(GlobalVar splash_Activity) {
this.Splash_Activity = splash_Activity;
this.Splash_Activity.registerActivityLifecycleCallbacks(this);
ProcessLifecycleOwner.get().getLifecycle().addObserver(this);
}
/** LifecycleObserver methods */
#OnLifecycleEvent(ON_START)
public void onStart() {
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
showAdIfAvailable();
}
}, 1500);
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(
Splash_Activity, 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));
}
}
Splash_Activity
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
if (go) {
startActivity(new Intent(Splash_Activity.this, home_main.class));
finish();
}
}
}, 4200);
}
First, you need to create a callback listener to know when the ad has been dismissed, and stop further code execution until then.
public interface AdListener {
void onCompleted();
}
Change the code of showAdIfAvailable like below with a parameter of listener.
public void showAdIfAvailable(#NonNull AdListener listener) {
// 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.");
appOpenAd.setFullScreenContentCallback(new FullScreenContentCallback() {
#Override
public void onAdDismissedFullScreenContent() {
// Set the reference to null so isAdAvailable()
this.appOpenAd = null;
isShowingAd = false;
fetchAd();
// Inform caller that we have done
listener.onCompleted();
}
#Override
public void onAdFailedToShowFullScreenContent(#NonNull AdError adError) {
appOpenAd = null;
// Inform caller that we have done
listener.onCompleted();
}
#Override
public void onAdShowedFullScreenContent() {
isShowingAd = true;
}
});
appOpenAd.show(currentActivity);
} else {
Log.d(LOG_TAG, "Can not show ad.");
// Inform caller that we have done
listener.onCompleted();
// Load new ad
fetchAd();
}
}
Call to show app onen ad like below from SplashActivity:
showAdIfAvailable(SplashActivity.this, new AdListener() {
#Override
public void onCompleted() {
// Start your activity from here
}
});
However, this is a demonstration of the process. Change it as you want to use it.
Hope it will help.
my app crashes while loading Google Admob ad. It worked fine for a long time but now I get following error:
java.lang.NullPointerException: Attempt to invoke virtual method 'void com.google.android.gms.ads.interstitial.InterstitialAd.setFullScreenContentCallback(com.google.android.gms.ads.FullScreenContentCallback)' on a null object reference
I've changed nothing in code, my app is in Play Store and I have the App on my Galaxy S10 & it worked all the time but now if the Ad has to be loaded I get this error. Can somebody help?
Thanks
Edit: Here's my code
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
MobileAds.initialize(this, new OnInitializationCompleteListener() {
#Override
public void onInitializationComplete(InitializationStatus initializationStatus) {
}
});
AdRequest adRequest = new AdRequest.Builder().build();
InterstitialAd.load(this,"ca-app-pub-93706071examplenumber/4141725063", adRequest, new InterstitialAdLoadCallback() {
#Override
public void onAdLoaded(#NonNull InterstitialAd interstitialAd) {
mInterstitialAd = interstitialAd;
Log.i("TAG", "onAdLoaded");
}
#Override
public void onAdFailedToLoad(#NonNull LoadAdError loadAdError) {
Log.i("TAG", "onAdLoaded");
mInterstitialAd = null;
}
});
private void showInterstitial(){
if (callbackActive == false){
setCallback();
}
if (mInterstitialAd != null ) {
mInterstitialAd.show(MainActivity.this);
} else {
Log.d("TAG", "The interstitial ad wasn't ready yet.");
}
}
private void setCallback(){
callbackActive = true;
mInterstitialAd.setFullScreenContentCallback(new FullScreenContentCallback(){
#Override
public void onAdDismissedFullScreenContent() {
Log.d("TAG", "The ad was dismissed.");
}
#Override
public void onAdFailedToShowFullScreenContent(AdError adError) {
Log.d("TAG", "The ad failed to show.");
}
#Override
public void onAdShowedFullScreenContent() {
mInterstitialAd = null;
Log.d("TAG", "The ad was shown.");
}
});
}
Put setFullScreenContentCallback in onAdLoaded
here is a code snippet (see code below) and check the full code from AdMob official sample on GitHub
public void loadAd() {
AdRequest adRequest = new AdRequest.Builder().build();
InterstitialAd.load(
this,
AD_UNIT_ID,
adRequest,
new InterstitialAdLoadCallback() {
#Override
public void onAdLoaded(#NonNull InterstitialAd interstitialAd) {
// The mInterstitialAd reference will be null until
// an ad is loaded.
MyActivity.this.interstitialAd = interstitialAd;
Log.i(TAG, "onAdLoaded");
Toast.makeText(MyActivity.this, "onAdLoaded()", Toast.LENGTH_SHORT).show();
interstitialAd.setFullScreenContentCallback(
new FullScreenContentCallback() {
#Override
public void onAdDismissedFullScreenContent() {
// Called when fullscreen content is dismissed.
// Make sure to set your reference to null so you don't
// show it a second time.
MyActivity.this.interstitialAd = null;
Log.d("TAG", "The ad was dismissed.");
}
#Override
public void onAdFailedToShowFullScreenContent(AdError adError) {
// Called when fullscreen content failed to show.
// Make sure to set your reference to null so you don't
// show it a second time.
MyActivity.this.interstitialAd = null;
Log.d("TAG", "The ad failed to show.");
}
#Override
public void onAdShowedFullScreenContent() {
// Called when fullscreen content is shown.
Log.d("TAG", "The ad was shown.");
}
});
}
So I am trying to add Interstitial ads to my project.
This is my what my code looks like for the current JHAActivity.java:
Note: In my project I am using my own Ad unit ID from apps.admob.com insted of ca-app-pub-1111111111111111/2222222222.
import com.google.android.gms.ads.AdListener;
import com.google.android.gms.ads.AdRequest;
import com.google.android.gms.ads.InterstitialAd;
import com.google.android.gms.ads.LoadAdError;
import com.google.android.gms.ads.MobileAds;
import com.google.android.gms.ads.RequestConfiguration;
import com.google.android.gms.ads.initialization.InitializationStatus;
import com.google.android.gms.ads.initialization.OnInitializationCompleteListener;
public class JHAActivity extends AppCompatActivity {
private Button jhaButton;
// private static final String AD_UNIT_ID = "ca-app-pub-3940256099942544/1033173712"; Test AD
private static final String AD_UNIT_ID = "ca-app-pub-1111111111111111/2222222222";
private InterstitialAd mInterstitialAd;
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// R.menu.mymenu is a reference to an xml file named mymenu.xml which should be inside your res/menu directory.
// If you don't have res/menu, just create a directory named "menu" inside res
getMenuInflater().inflate(R.menu.mymenu, menu);
return super.onCreateOptionsMenu(menu);
}
// handle button activities
#Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.mybutton) {
// do something here
if (Locale.getDefault().getLanguage().equals("en")) { // If English
new AlertDialog.Builder(this)
.setTitle(R.string.rules)
.setMessage(rulesENG)
// A null listener allows the button to dismiss the dialog and take no further action.
.setNegativeButton(android.R.string.ok, null)
.setIcon(android.R.drawable.ic_dialog_alert)
.show();
} else { // Else if not English
new AlertDialog.Builder(this)
.setTitle(R.string.rules)
.setMessage(rules)
// A null listener allows the button to dismiss the dialog and take no further action.
.setNegativeButton(android.R.string.ok, null)
.setIcon(android.R.drawable.ic_dialog_alert)
.show();
}
}
return super.onOptionsItemSelected(item);
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_jha);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
// Initialize the Mobile Ads SDK.
MobileAds.initialize(this, new OnInitializationCompleteListener() {
#Override
public void onInitializationComplete(InitializationStatus initializationStatus) {}
});
mInterstitialAd = new InterstitialAd(this);
mInterstitialAd.setAdUnitId(AD_UNIT_ID);
mInterstitialAd.loadAd(new AdRequest.Builder().build());
mInterstitialAd.setAdListener(new AdListener() {
#Override
public void onAdClosed() {
// Load the next interstitial.
mInterstitialAd.loadAd(new AdRequest.Builder().build());
}
#Override
public void onAdLoaded() {
// Code to be executed when an ad finishes loading.
}
#Override
public void onAdFailedToLoad(LoadAdError adError) {
// Code to be executed when an ad request fails.
}
#Override
public void onAdOpened() {
// Code to be executed when the ad is displayed.
}
#Override
public void onAdClicked() {
// Code to be executed when the user clicks on an ad.
}
#Override
public void onAdLeftApplication() {
// Code to be executed when the user has left the app.
}
});
jhaButton = (Button) findViewById(R.id.button);
jhaButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
openJHA();
}
});
}
private void showInterstitial() {
// Show the ad if it's ready. Otherwise toast and restart the game.
if (mInterstitialAd != null && mInterstitialAd.isLoaded()) {
mInterstitialAd.show();
} else {
// Toast.makeText(this, "Ad did not load", Toast.LENGTH_SHORT).show();
Log.d("TAG", "The interstitial wasn't loaded yet.");
}
}
int counter = 0;
private void openJHA() {
counter++;
if (counter == 5) {
showInterstitial(); // Display AdMob AD
counter = 0;
}
}
}
So basically when using ca-app-pub-3940256099942544/1033173712 as Ad unit ID, it displays the test ad each time I have pressed the jhaButton 5 times, but when using my own Ad unit ID, the ad does not show up at all. In the run log it just says: D/TAG: The interstitial wasn't loaded yet.. What am I doing wrong here?
#Override
public void onAdLoaded() {
// Code to be executed when an ad finishes loading.
}
#Override
public void onAdFailedToLoad(LoadAdError adError) {
// Code to be executed when an ad request fails.
}
your mInterstitialAd.loadAd(xxx) tried to load once but it is often that onAdFailedToLoad(LoadAdError adError) returned and if you didn't do sth like mInterstitialAd.loadAd again to get a try, it will stop and never jump to onAdLoaded(). Hence your mInterstitialAd.isLoaded() will almost return false.
Every time you want to use mInterstitialAd.showAd(), please check first if (!mInterstitialAd.isLoaded()){mInterstitialAd.showAd() } first
The big problem is that recent Admob used SDK v19.7.0 . codes related to InterestitialAd need to be modified again...And I don't know why the callback lose the function about onAdClicked.
I'm trying to call a method from another class which then calls an AlertDialog method, and I've tried many things but it always causes a null pointer exception. The calling class is running a web server, and I have a RecyclerView list on the activity class containing the method being called. here's some code from the activity class with AlertDialog:
public class ListClass extends AppCompatActivity {
private WebSvr server;
private static final int PORT = 8080;
private androidx.appcompat.widget.Toolbar toolbar;
private ListView lv;
private CustomAdapter customAdapter;
public ArrayList<EditModel> editModelArrayList;
public static String[] newList = new String[20];
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_server_screen);
toolbar = (androidx.appcompat.widget.Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
startWebServer();
customAdapter = new CustomAdapter(this, editModelArrayList);
lv.setAdapter(customAdapter);
}
public static boolean listUpdated;
public void updateList() {
listUpdated = false;
Runnable r = new Runnable() {
#Override
public void run() {
for (int i = 0; i < 20; i++) {
if (CustomAdapter.editModelArrayList.get(i).getEditTextValue() != "") {
newList[i] = CustomAdapter.editModelArrayList.get(i).getEditTextValue();
} else {
if (!showNotification) {
runOnUiThread(new Runnable() {
#Override
public void run() {
showNullFieldNotification(); // <------------- CALLING THIS
}
});
showNotification = true;
}
}
}
listUpdated = true;
}
};
Thread thread = new Thread(r);
thread.start();
}
boolean showNotification = false;
public void showNullFieldNotification() {
new AlertDialog.Builder(ListClass.this)
.setTitle("Warning, some fields are empty")
.setNegativeButton("OK", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
dialogInterface.cancel();
showNotification = false;
}
}).show();
}
public static boolean returnListUpdated() {
return listUpdated;
}
...
}
And here's the code from my web server class:
public class WebSvr extends NanoHTTPD {
public ListClass ListClass = new ListClass();
public WebSvr(int port){
super(port);
}
#Override
public Response serve(String uri, Method method,
Map<String, String> header,
Map<String, String> parameters,
Map<String, String> files) {
ListClass.updateList(); // <--------------- THE METHOD CALLED
while (!ListClass.returnListUpdated()) {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
String strResponse = Arrays.toString(ListClass.returnString());
return newFixedLengthResponse(strResponse);
}
}
It always causes null pointer exception on this line:
new AlertDialog.Builder(ListClass.this)
and where the method is called in ListClass:
showNullFieldNotification();
Error message:
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.espressif.iot_esptouch_demo, PID: 18217
java.lang.NullPointerException: Attempt to invoke virtual method 'android.content.pm.ApplicationInfo android.content.Context.getApplicationInfo()' on a null object reference
at android.content.ContextWrapper.getApplicationInfo(ContextWrapper.java:152)
at android.view.ContextThemeWrapper.getTheme(ContextThemeWrapper.java:157)
at android.app.AlertDialog.resolveDialogTheme(AlertDialog.java:224)
at android.app.AlertDialog$Builder.<init>(AlertDialog.java:454)
at com.myProject.ListClass.showNullFieldNotification(ListClass.java:177)
at com.myProject.ListClass$4.run(ListClass.java:193)
at android.os.Handler.handleCallback(Handler.java:789)
at android.os.Handler.dispatchMessage(Handler.java:98)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6665)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:772)
If I call showNullFieldNotification() in ListClass onCreate() or from the options menu it works no problem, but when called from the WebSvr class it always causes the exception.
For context on the AlertDialog I've tried ListClass.this, getApplicationContext(), getBaseContext()... I've tried to save a context in onCreate as getApplicationContext() and use that.
I've tried to use the solution from this question to get context but that didn't work either. Would really appreciate any help.
EDIT: Forgot to mention that I had also tried to build the alert in this way:
public void showNullFieldNotification2() {
AlertDialog.Builder alert = new AlertDialog.Builder(ListClass.this);
alert.setTitle("Warning, some fields detected as being empty or having \"0\" as value");
alert.setNegativeButton("OK", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
dialogInterface.cancel();
showNotification = false;
}
});
AlertDialog dialog = alert.create();
dialog.show();
}
you forgot create Alert Dialog so it null, not the context
Android simple alert dialog
Got the solution from here in answer from Dan Bray. Needed to use a static context.
Since you are calling from outside of an activity, you'll need to save the context in activity class:
public static Context context;
And inside onCreate:
context = this;
To show notification:
new Handler(Looper.getMainLooper()).post(new Runnable(){
#Override
public void run(){
new AlertDialog.Builder(context)
.setTitle("Warning, some fields are empty")
.setNegativeButton("OK",new DialogInterface.OnClickListener(){
#Override
public void onClick(DialogInterface dialogInterface,int i){
dialogInterface.cancel();
showNotification=false;
}
}).show();
}
});
The methods called in the activity class must also be public static.