android app screen flashing at launch
android, android-4.0-ice-cream-sandwich, launching-application, screen
Solution
FINALLY FOUND THE ERROR AND THE PROPER SOLUTION !!
Actually, The problem occurred only when people first launched the App from a screen on land mode... The App is forced to be portrait in the Manifest, but, nevertheless, I realised that Android still executes the onConfigurationChanged at launch (when passing from Land to Portrait, e.g)
The problem is that the App is in 2 languages and to keep the right language on screen orientation I had increment my own Myapplication (to extend Application) to manage onConfigurationChanged and set the correct Locale default throughout the App!!
Even after forcing the App to Portrait in the Manifest (for some reasons some time ago), the onConfigurationChanged from MyApplication.java was still executed in some circomstances...
THE PROBLEM :
The code in the MyApplication.java was
public void onConfigurationChanged(Configuration newConfig)
{
super.onConfigurationChanged(newConfig);
// Set correct language (default or chosen)
Locale locale = new Locale(getState());
Locale.setDefault(locale);
newConfig.locale = locale;
getBaseContext().getResources().updateConfiguration(newConfig, getBaseContext().getResources().getDisplayMetrics());
}
THE SOLUTION:
Do not use directly newConfig, but make a Modifiable Configuration object, instead, as adviced by Android Developper, and work with it
public void onConfigurationChanged(Configuration newConfig)
{
super.onConfigurationChanged(newConfig);
// Set correct language (default or chosen)
Locale locale = new Locale(getState());
Locale.setDefault(locale);
Configuration config = new Configuration(newConfig); // get Modifiable Config from actual config changed
config.locale = locale;
getBaseContext().getResources().updateConfiguration(config, getBaseContext().getResources().getDisplayMetrics());
}
The former solution to load directly the newConfog objest was working until Android v2.3 but was not accepted any more in the Android Version >= 4.0
EVERYTHING IS OK NOW !!
(Special Thanks to Frédéric Espiau alias Apollidore, as the solution came reading his excellent book "Créez des applications pour Android")
Problem
Hi I have searched everywhere here and on Google, without getting a correct answer. So I post a new question: I have several Android Apps that were working perfectly with 1.6 up to 2.3... BUT now, with Android 4.0 (ICS), I have users reporting that the screen is flashing on the homepage when the application is launched and nothing can be done but "home" and Force Stop the App... (then. you can start the app again, and it eventually works... :O) I have tested the App on the emulator and on several devices including the Galaxy S 3 with Android 4.0.4 and I could never reproduce the issue !! :(( It seems that the issue is mostly on the HTC One... Here is the simple code of the activity ``` public class WelcomePage extends Activity { /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); Eula.show(this); //on lui associe le layout setContentView(R.layout.main); //on récupère tous les éléments Button buttonGuide = (Button)findViewById(R.id.buttonOui); Button buttonHotel = (Button)findViewById(R.id.buttonNon); Button buttonMap = (Button)findViewById(R.id.buttonMapg); Button buttonMaps = (Button)findViewById(R.id.buttonMaps); Button buttonMapb = (Button)findViewById(R.id.buttonMapb); Button buttonTwitt = (Button)findViewById(R.id.buttonTwitt); Button buttonFaceb = (Button)findViewById(R.id.buttonFaceb); Button buttonGoogle = (Button)findViewById(R.id.buttonGoogle); Button buttonGeoloc = (Button)findViewById(R.id.buttonGeoloc); OnClickListener onClickLister = new OnClickListener() { public void onClick(View v){ Intent intent; switch(v.getId()){ //si on a cliqué sur le button Oui case R.id.buttonOui: Bundle objetbunble = new Bundle(); objetbunble.putString("titre", "Phuket"); String lurl; if (getString(R.string.lnguserlook).equals("en")) { lurl = "phuketen"; } else { lurl = "phuket"; } objetbunble.putString("url", lurl); intent = new Intent(WelcomePage.this, AfficheGuide.class); Toast.makeText(WelcomePage.this, getString(R.string.titguid)+" Phuket "+getString(R.string.titguid2), Toast.LENGTH_SHORT).show(); ((MyApplication)getApplicationContext()).setIsPagehelp(false); // pas Help en globale //On affecte à l'Intent le Bundle que l'on a créé intent.putExtras(objetbunble); startActivity(intent); break; case R.id.buttonNon: Toast.makeText(WelcomePage.this, getString(R.string.hotellist), Toast.LENGTH_SHORT).show(); //On créé l'Intent qui va nous permettre d'afficher l'autre Activity intent = new Intent(WelcomePage.this, ListeDestinationAll.class); startActivity(intent); break; case R.id.buttonGeoloc: if (!(Extras.Internet.isOnline())){ AlertDialog.Builder builder = new AlertDialog.Builder(WelcomePage.this); builder.setMessage(getString(R.string.txtoffline)) .setPositiveButton("Ok", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { dialog.cancel(); } }).create().show(); } else { Toast.makeText(WelcomePage.this, "Geolocalisation", Toast.LENGTH_SHORT).show(); intent = new Intent(WelcomePage.this, AfficheGeoloc.class); startActivity(intent); } break; case R.id.buttonMapg: Toast.makeText(getApplicationContext(), getString(R.string.map1), Toast.LENGTH_SHORT).show(); if (!(Extras.Internet.isOnline())){ AlertDialog.Builder builder = new AlertDialog.Builder(WelcomePage.this); builder.setMessage(getString(R.string.txtoffline)) .setPositiveButton("Ok", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { dialog.cancel(); } }).create().show(); } else { Toast.makeText(WelcomePage.this, "Phuket", Toast.LENGTH_SHORT).show(); objetbunble = new Bundle(); //Cela fonctionne plus ou moins comme une HashMap, on entre une clef et sa valeur en face objetbunble.putString("titre", "Phuket"); objetbunble.putString("url", "phuket&titre=Phuket"); intent = new Intent(WelcomePage.this, AfficheMaps.class); //On affecte à l'Intent le Bundle que l'on a créé intent.putExtras(objetbunble); startActivity(intent); } break; case R.id.buttonMaps: Toast.makeText(getApplicationContext(), getString(R.string.map2), Toast.LENGTH_SHORT).show(); Bundle objetbunblemap = new Bundle(); objetbunblemap.putString("titre", getString(R.string.map2)); objetbunblemap.putString("url", "pic"); final Intent intentm; intentm = new Intent(WelcomePage.this, ImageViewerJP.class); intentm.putExtras(objetbunblemap); startActivity(intentm); break; case R.id.buttonMapb: if (!(Extras.Internet.isOnline())){ AlertDialog.Builder builder = new AlertDialog.Builder(WelcomePage.this); builder.setMessage(getString(R.string.txtoffline)) .setPositiveButton("Ok", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { dialog.cancel(); } }).create().show(); } else { //On créé un objet Bundle, c'est ce qui va nous permetre d'envoyer des données à l'autre Activity objetbunble = new Bundle(); objetbunble.putString("titre", getString(R.string.titevent3)+" Phuket"); objetbunble.putString("url", getString(R.string.urlevent2)+"phuket"); intent = new Intent(WelcomePage.this, AfficheEvents.class); Toast.makeText(WelcomePage.this, getString(R.string.titevent3)+" Phuket", Toast.LENGTH_SHORT).show(); //On affecte à l'Intent le Bundle que l'on a créé intent.putExtras(objetbunble); startActivity(intent); } break; case R.id.buttonTwitt: if (!(Extras.Internet.isOnline())){ AlertDialog.Builder builder = new AlertDialog.Builder(WelcomePage.this); builder.setMessage(getString(R.string.txtoffline)) .setPositiveButton("Ok", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { dialog.cancel(); } }).create().show(); } else { Toast.makeText(WelcomePage.this, "Twitter", Toast.LENGTH_SHORT).show(); //On créé l'Intent qui va nous permettre d'afficher l'autre Activity intent = new Intent(Intent.ACTION_VIEW); intent.setData(Uri.parse("http://mobile.twitter.com/#!/ResaHotelThai")); startActivity(intent); } break; case R.id.buttonGoogle: if (!(Extras.Internet.isOnline())){ AlertDialog.Builder builder = new AlertDialog.Builder(WelcomePage.this); builder.setMessage(getString(R.string.txtoffline)) .setPositiveButton("Ok", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { dialog.cancel(); } }).create().show(); } else { Toast.makeText(WelcomePage.this, "Google+", Toast.LENGTH_SHORT).show(); //On créé l'Intent qui va nous permettre d'afficher l'autre Activity intent = new Intent(Intent.ACTION_VIEW); intent.setData(Uri.parse("https://plus.google.com/114371498756127408275/posts")); startActivity(intent); } break; case R.id.buttonFaceb: if (!(Extras.Internet.isOnline())){ AlertDialog.Builder builder = new AlertDialog.Builder(WelcomePage.this); builder.setMessage(getString(R.string.txtoffline)) .setPositiveButton("Ok", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { dialog.cancel(); } }).create().show(); } else { Toast.makeText(WelcomePage.this, "Facebook", Toast.LENGTH_SHORT).show(); //On créé l'Intent qui va nous permettre d'afficher l'autre Activity intent = new Intent(Intent.ACTION_VIEW); intent.setData(Uri.parse("http://m.facebook.com/ResaHotelThai")); startActivity(intent); } break; } } }; //on affecte aux Button l'écouteur d'évènement buttonGuide.setOnClickListener(onClickLister); buttonHotel.setOnClickListener(onClickLister); buttonMap.setOnClickListener(onClickLister); buttonMaps.setOnClickListener(onClickLister); buttonMapb.setOnClickListener(onClickLister); buttonTwitt.setOnClickListener(onClickLister); buttonFaceb.setOnClickListener(onClickLister); buttonGoogle.setOnClickListener(onClickLister); buttonGeoloc.setOnClickListener(onClickLister); } //Méthode qui se déclenchera lorsque vous appuierez sur le bouton menu du téléphone public boolean onCreateOptionsMenu(Menu menu) { //Création d'un MenuInflater qui va permettre d'instancier un Menu XML en un objet Menu MenuInflater inflater = getMenuInflater(); //Instanciation du menu XML spécifier en un objet Menu inflater.inflate(R.layout.menu, menu); //Il n'est pas possible de modifier l'icône d'entête du sous-menu via le fichier XML on le fait donc en JAVA menu.getItem(0).getSubMenu().setHeaderIcon(R.drawable.language); return true; } //Méthode qui se déclenchera au clic sur un item public boolean onOptionsItemSelected(MenuItem item) { Intent intent; //On regarde quel item a été cliqué grâce à son id et on déclenche une action switch (item.getItemId()) { case R.id.option: Toast.makeText(WelcomePage.this, getString(R.string.language), Toast.LENGTH_SHORT).show(); return true; case R.id.french: Locale locale = new Locale("fr"); Locale.setDefault(locale); Configuration config = new Configuration(); config.locale = locale; getBaseContext().getResources().updateConfiguration(config, getBaseContext().getResources().getDisplayMetrics()); ((MyApplication)getApplicationContext()).setState("fr"); // passe langue en globale Toast.makeText(WelcomePage.this, "Français", Toast.LENGTH_SHORT).show(); intent = new Intent(WelcomePage.this, WelcomePage.class); //On redémarre l'Activity startActivity(intent); finish(); return true; case R.id.english: Locale locale2 = new Locale("en"); Locale.setDefault(locale2); Configuration config2 = new Configuration(); config2.locale = locale2; getBaseContext().getResources().updateConfiguration(config2, getBaseContext().getResources().getDisplayMetrics()); ((MyApplication)getApplicationContext()).setState("en"); // passe langue en globale Toast.makeText(WelcomePage.this, "English", Toast.LENGTH_SHORT).show(); intent = new Intent(WelcomePage.this, WelcomePage.class); //On redémarre l'Activity startActivity(intent); finish(); return true; case R.id.about: // Assigne un Layout particulier a la dialogue Box LayoutInflater inflater = (LayoutInflater) WelcomePage.this.getSystemService(LAYOUT_INFLATER_SERVICE); View layout = inflater.inflate(R.layout.afficheabout, (ViewGroup) findViewById(R.id.layout_root)); // Traitement du texte a afficher + linkify pour que le lien soit cliquable TextView text = (TextView) layout.findViewById(R.id.text); final SpannableString s = new SpannableString("Version 1.1.0\n\n\nwww.bloodico.com\n\nCopyright ©2011/2012\nBloodico Co Ltd"); text.setText(s); Linkify.addLinks(text, Linkify.ALL); // Traitement de l'image a afficher a gauche ImageView image = (ImageView) layout.findViewById(R.id.image); image.setImageResource(R.drawable.sawadi); // Construction de la dialogbox AlertDialog.Builder adb = new AlertDialog.Builder(WelcomePage.this); adb.setView(layout); adb.setTitle("GuidePhuket"); adb.setIcon(R.drawable.ic_launcher); //on indique que l'on veut le bouton ok à notre boite de dialogue adb.setPositiveButton("Ok", null); adb.show(); return true; case R.id.help: Toast.makeText(WelcomePage.this, getString(R.string.helptitle), Toast.LENGTH_SHORT).show(); //On créé un objet Bundle, c'est ce qui va nous permetre d'envoyer des données à l'autre Activity Bundle objetbunble = new Bundle(); //Cela fonctionne plus ou moins comme une HashMap, on entre une clef et sa valeur en face objetbunble.putString("titre", getString(R.string.helptitle)); objetbunble.putString("url", getString(R.string.helpurl)); intent = new Intent(WelcomePage.this, AfficheGuide.class); //On affecte à l'Intent le Bundle que l'on a créé intent.putExtras(objetbunble); startActivity(intent); return true; case R.id.morapp: Toast.makeText(WelcomePage.this, getString(R.string.morapp), Toast.LENGTH_SHORT).show(); Intent marketIntent = new Intent(Intent.ACTION_VIEW).setData(Uri.parse("market://search?q=pub:Bloodico+Co+Ltd")); startActivity(marketIntent); return true; } return super.onOptionsItemSelected(item); } ``` } And here is the Layout used ``` <?xml version="1.0" encoding="UTF-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" android:gravity="center" android:background="@drawable/fond" > <ImageView android:id="@+id/imageintro" android:layout_width="fill_parent" android:layout_height="wrap_content" android:src="@drawable/logocompanyfr" android:gravity="center_horizontal" android:contentDescription="@string/app_name" /> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="horizontal" android:layout_marginTop="20dp" > <Button android:id="@+id/buttonOui" android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_marginRight="20dp" android:background="@drawable/titreguidebutton" /> <Button android:id="@+id/buttonNon" android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_marginRight="20dp" android:background="@drawable/titrehotelbutton" /> <Button android:id="@+id/buttonGeoloc" android:layout_width="fill_parent" android:layout_height="fill_parent" android:background="@drawable/titregeolocbutton" /> </LinearLayout> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="horizontal" android:paddingTop="5dp" > <Button android:id="@+id/buttonMapg" android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_marginRight="20dp" android:background="@drawable/titreinfobutton" /> <Button android:id="@+id/buttonMaps" android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_marginRight="20dp" android:background="@drawable/titremapsbutton" /> <Button android:id="@+id/buttonMapb" android:layout_width="fill_parent" android:layout_height="fill_parent" android:background="@drawable/titremapbbutton" /> </LinearLayout> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="100dp" android:orientation="horizontal" > <Button android:id="@+id/buttonFaceb" android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_marginRight="20dp" android:background="@drawable/titrefacebbutton" /> <Button android:id="@+id/buttonTwitt" android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_marginRight="20dp" android:background="@drawable/titretwittbutton" /> <Button android:id="@+id/buttonGoogle" android:layout_width="fill_parent" android:layout_height="fill_parent" android:background="@drawable/titregooglebutton" /> </LinearLayout> </LinearLayout> ``` And here is an excerpt of the manifest file ``` <uses-sdk android:minSdkVersion="4" android:targetSdkVersion="8" /> <uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> <supports-screens android:smallScreens="true" android:normalScreens="true" android:largeScreens="true" android:anyDensity="true" /> <application android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:name=".MyApplication" android:allowBackup="true" android:screenOrientation="portrait"> <activity android:name=".WelcomePage" android:screenOrientation="portrait" android:label="@string/app_name" android:icon="@drawable/ic_launcher" android:theme="@android:style/Theme.NoTitleBar"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> ``` Any help would be grantly appreciated, as i have more and more users concerned and can not find a way where to search.