Hi everyone I have an Activity which is loading after I click on an Item inside my Listview.
This activity shows the location inside a MapView like this:
<FrameLayout
android:id="#+id/mapContainer"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_toEndOf="#+id/imageView"
android:layout_above="#+id/button"
android:layout_below="#+id/imageView"
android:layout_alignParentStart="true"
android:layout_marginTop="10dp" >
<TextView
android:id="#+id/loading"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="Loading Map..." />
</FrameLayout>
The Problem is, that I want to show the Map to the User later on if he/she clicks on a button.
But the Activity is loading very slow and even has a black blank screen before showing anything. This looks very unprofessional, and seems wrong.
I tried making the MapView invisible first and show it when user hits the button, but it is loading when the activity starts.
I'am trying following code:
protected void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_single_event);
mapView = new MapView(SingleEvent.this);
mapView.onCreate(savedInstanceState);
com.google.android.gms.maps.MapView.LayoutParams mapParams = new com.google.android.gms.maps.MapView.LayoutParams(com.google.android.gms.maps.MapView.LayoutParams.MATCH_PARENT,220);
mapContainer = (FrameLayout) findViewById(R.id.mapContainer);
mapContainer.addView(mapView, mapParams);
This one is working it is showing the map, but the activity is loading to long with a black blank screen, until my activity is loaded.
Is there any way to first load the activity and after that load the MapView on a button click?
I'am trying to do something like this:
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
mapView = new MapView(SingleEvent.this);
mapView.onCreate(savedInstanceState);
com.google.android.gms.maps.MapView.LayoutParams mapParams = new com.google.android.gms.maps.MapView.LayoutParams(com.google.android.gms.maps.MapView.LayoutParams.MATCH_PARENT,220);
mapContainer = (FrameLayout) findViewById(R.id.mapContainer);
mapContainer.addView(mapView, mapParams);
}
},1000);
But with that code, the Map isnt loading its only showing the grey blank grid.
I think its because of the savedInstanceState but maybe there is a work around?
I tried to save the Bundle savedInstanceState, loading like above.
You can use a MapFragment. In onCreate(), you can set visibility to invisible. When the map is ready, onMapReady() will be called and you can configure map settings there.
I had the same issue which was occurring due to hardware accelartion and largeheap. I had used these features at application level. But I removed them from the app level and used them in the activity they used. The Activity which contained SupportMapFragment didn't need these features. So I moved this code from Application tag to Activity in Manifest.
Issue was in Manifest.
<application
android:label="#string/app_name"
android:theme="#style/AppTheme"
android:hardwareAccelerated="false"
android:largeHeap="true">
Remove from Manifest and Use in the Activity
<activity
android:name="com.mycompayname.activities.SignUpActivity"
android:hardwareAccelerated="false"
android:largeHeap="true"/>
Related
Description
When starting the Google Maps app (using a "get directions" Intent) from within my own app, part or all of the map presented in my app sometimes (~25-50% of the time) turns black during the screen transition. Here are videos from a minimal working example:
Real device
A rectangular piece of the map that is covered by a transparent view turns black during the transition. Note that while the transparent part of the view is unnecessary in this MWE, it is a required part of my actual application.
Emulator
The entire map turns black during the transition.
The Activity shown has the following layout:
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.google.android.gms.maps.MapView
android:id="#+id/map_view"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<FrameLayout
android:id="#+id/bottom_sheet"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="150dp"
android:layout_marginTop="48dp"
android:background="#android:color/white" />
<Button
android:id="#+id/button_action"
android:layout_width="100dp"
android:layout_height="wrap_content"
android:layout_gravity="center" />
</FrameLayout>
</RelativeLayout>
and code:
public class MapsActivity extends AppCompatActivity {
private MapView mapView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_maps);
findViewById(R.id.button_action).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(final View view) {
final Intent intent = new Intent(ACTION_VIEW, Uri.parse("google.navigation:q=42.3314,-83.0458"));
intent.setPackage("com.google.android.apps.maps");
startActivity(intent);
}
});
mapView = (MapView) findViewById(R.id.map_view);
mapView.onCreate(savedInstanceState);
}
// All the other overridden lifecycle methods, forwarded to mapView correctly.
}
The project uses the latest version of Google Play Services (10.0.1). Full code is available on GitHub.
I've read through a bunch of legacy issues with maps turning black, but those seem to relate to a single map being scrolled (e.g. https://code.google.com/p/gmaps-api-issues/issues/detail?id=4659).
I don't have a reliable way to reproduce the issue, even within the MWE, but it happens often enough to be easy to observe and capture.
Device specs seem to make a difference (higher spec devices exhibit the issue less often).
Questions
What's the underlying cause of this issue?
Is there something I should (or should not) be doing to avoid this ugly behavior when launching the Google Maps app?
In My application i am setting orientation of the application on button click, using setRequestedOrientation(), My application has one webview which displays local web page.
I am using solution as mentioned in below link, to stop reloading of page when orientation changes.
http://www.devahead.com/blog/2012/01/preserving-the-state-of-an-android-webview-on-screen-orientation-change/
Only difference is that i am not having onSaveInstanceState and onRestoreInstanceState in my activity.
What happens in my case is that, my web view does not reload when i change the orientation but it just re-renders the UI upon changing the orientation.
It happens like it first displays the UI and then it displays the white blank screen for few seconds and then again it displays UI.
How can i workaround it?
Once upon a time I used their implementation however I after reading up on the Android documentation I realized that much of their code was pointless since registering for config changes (in the manifest) means that your activity won't be destroyed as it normally is.
Long story short, you don't need to use a FrameLayout as a container for your webView, you may not need onConfigurationChanged, etc. If I get some time I will post some code as an example.
For now, make sure you have the following in your manifest file
android:configChanges="keyboard|keyboardHidden|orientation|screenSize"
instead of
android:configChanges="keyboard|keyboardHidden|orientation"
since on orientation change devices may get get a screenSize change
EDIT This is what I have done (skimmed from one of my projects so I may have missed minor details)
in AndroidManifest.xml
<activity android:name=".Activities.WebWrapperActivity"
android:theme="#android:style/Theme.NoTitleBar"
android:configChanges="keyboard|keyboardHidden|orientation|screenSize"/>
web_wrapper_activity_layout.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<WebView android:id="#+id/web_wrapper_activity_web_view"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:scrollbarStyle="outsideOverlay"/>
</LinearLayout>
The Activity (or a portion of it)
public class WebWrapperActivity extends Activity {
private WebView _webView;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.web_wrapper_activity_layout);
init();
}
private void init() {
_webView = (WebView) findViewById(R.id.web_wrapper_activity_web_view);
_webView.setScrollbarFadingEnabled(true);
_webView.getSettings().setLoadsImagesAutomatically(true);
_webView.getSettings().setJavaScriptEnabled(true);
_webView.getSettings().setAllowFileAccess(true);
_webView.getSettings().setSavePassword(false);
_webView.getSettings().setPluginState(WebSettings.PluginState.ON);
_webView.loadUrl(“http://www.google.com”);
}
#Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
_webView.saveState(outState);
}
}
As i mentioned previously, you may not need onConfigurationChanged if your webView is the only view in the Activity.
If you have any issues let me know
This question already has an answer here:
Closed 10 years ago.
Possible Duplicate:
Android Activity Life Cycle
I am able to create a simple Splash Screen for my app using Themes and it works just fine. However, there may be times that the app needs to refresh a large amount of data and I want to display a ProgressBar to the user letting them know what's going on while they wait. So I ditched the Theme and created a layout resource and set that as the ContentView for my Splash Activity, but nothing displays. Not only does none of my content display (completely black screen) but the title bar continues to show up despite trying to hide it every way possible.
Splash.axml
<?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">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="15dp"
android:src="#drawable/logo" />
<LinearLayout
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:gravity="center">
<ProgressBar
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="10dp" />
<TextView
android:id="#+id/progressText"
android:text="Loading..."
android:textSize="20dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="5dp" />
</LinearLayout>
Splash.cs
[Activity(MainLauncher=true, NoHistory = true)]
public class Splash : Activity
{
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
RequestWindowFeature(WindowFeatures.NoTitle);
Window.SetFlags(WindowManagerFlags.Fullscreen, WindowManagerFlags.Fullscreen);
SetContentView(Resource.Layout.Splash);
string lastUpdated = PreferenceManager.GetDefaultSharedPreferences(this).GetString("LastInventoryUpdate", null);
DateTime lastUpdateDate = Convert.ToDateTime(lastUpdated);
TimeSpan span = DateTime.Today - lastUpdateDate;
if (string.IsNullOrEmpty(lastUpdated) || span.Days > 30)
{
TextView progressText = (TextView)FindViewById(Resource.Id.progressText);
progressText.Text = "Updating parts database. May take several minutes...";
InventoryRepository repository = ((MyApp)Application).Inventory;
repository.Execute();
}
StartActivity(typeof(Login));
}
}
Still shows logo and title in the title bar and absolutely nothing for content. Even tried taking all the AsyncTask and StartActivity stuff out and just tried loading the Activity with the splash layout. It does eventually show up, but it shows as the black screen for a long while first. Can't imagine why as this is my main launcher and there is literally nothing going on but setting the content of the activity.
And as far as the TitleBar showing up, I've also tried adding this to my manifest (which I currently have working in another activity just fine)
<activity android:name="app.MyApp.Splash" android:theme="#android:style/Theme.NoTitleBar.Fullscreen"></activity>
If I include a Theme for the activity, the TitleBar goes away, but my layout resource never displays.
Wouldn't you know after struggling all day I figured out a large part of the problem minutes after posting. In short, I put the Theme back on the Splash Activity which now shows while everything is initially loading and usually redirects to Login before the content is ever set, which is perfect. But I changed my OnCreate as follows:
[Activity(MainLauncher=true, NoHistory = true, ScreenOrientation = Android.Content.PM.ScreenOrientation.Landscape, Theme = "#style/Theme.Splash")]
public class Splash : Activity
{
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
RequestWindowFeature(WindowFeatures.NoTitle);
Window.SetFlags(WindowManagerFlags.Fullscreen, WindowManagerFlags.Fullscreen);
SetContentView(Resource.Layout.Splash);
string lastUpdated = PreferenceManager.GetDefaultSharedPreferences(this).GetString("LastInventoryUpdate", null);
DateTime lastUpdateDate = Convert.ToDateTime(lastUpdated);
TimeSpan span = DateTime.Today - lastUpdateDate;
if (string.IsNullOrEmpty(lastUpdated) || span.Days > 30)
{
SetTheme(Resource.Drawable.bg_black);
TextView progressText = (TextView) FindViewById(Resource.Id.progressText);
progressText.Text = "Updating parts database. May take several minutes...";
InventoryRepository repository = ((MyApp) Application).Inventory;
repository.Execute();
}
else
StartActivity(typeof (Login));
}
}
Main difference is that I only call StartActivity if I'm not running my AsyncTask. Otherwise, I call StartActivity from OnPostExecute of my AsyncTask. Also, be sure to set the background property of all your views in the splash layout. Since I left the theme on the activity, if you don't do this, your theme will show up as the background for EVERY view.
Im having some trouble accessing Hello Mapview at the moment, http://developer.android.com/training/tutorials/views/hello-mapview.html, but i think ive done this correctly. I want to show a map in a separate activity.
Map.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<com.google.android.maps.MapView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/mapview"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:clickable="true"
android:apiKey="working key"
/>
</LinearLayout>
Button onclick event that should show my map
public void showMap(View v){
Intent intent = new Intent(getBaseContext(), GoogleMapsActivity.class);
startActivity(intent);
}
GoogleMapsActivity.java
public class GoogleMapsActivity extends MapActivity
{
MapView mapView;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.map);
mapView = (MapView) findViewById(R.id.mapview);
mapView.setBuiltInZoomControls(true);
}
The activity is added to my manifest, Google apis is included etc. Its working if i put the map in my main activity, but not in my GoogleMapsActivity. Please tell me what ive missed here.
Thanks
From https://developers.google.com/maps/documentation/android/reference/:
Only one MapActivity is supported per process. Multiple MapActivities running simultaneously are likely to interfere in unexpected and undesired ways.
Basically, you can only have 1 MapActivity, and MapViews can only be hosted in a MapActivity. What you want basically isn't possible.
EDIT: not sure it would work for you, but you might try marking your second activity with android:process=":remote" and see if that works, but I doubt it.
EDIT: there is evidently some confusion. Look at https://developers.google.com/maps/documentation/android/reference/com/google/android/maps/MapView. This states that:
A MapView can only be constructed (or inflated) by a MapActivity. This is because it depends on threads which access the network and filesystem in the background; these threads must be shepherded by the lifecycle management in MapActivity. Tiles are cached on the filesystem in your application's directory. The cache is auto-managed so you don't need to do anything with it, and can delete it at any time.
I'll re-iterate: You CAN'T display a MapView in any other activity.
The problem was a misspelling in my manifest file,
<activity android:name=".GoogleMapActivity" /> //missing an "s"
I have an app which contains an activity which is a MapviewActivity and is mostly a mapview.
However I have noticed that the start up time of the activity is really slow and causes a lag from the moment the button is pressed to go in to the map activity. I feel this creates a bad user experience and would like to avoid this.
I have already set the background of the map activity to #null as suggested by one of the UI improvement articles on googles developer page, which I feel does not do the trick.
Is there a way to improve this? I would not like the main home screen to get stuck on the launch of the activity, even a transfer to the map activity and then loading the mapview would be better.
Thanks,
Jason
You could try removing the MapView from your layout. Then, in onCreate(), use post() to schedule a Runnable to add in the MapView and do your map-related initialization from Java. By using post() (or, potentially, postDelayed()) to postpone the MapView further, you should be able to render the rest of the activity first.
I haven't tried this, so YMMV. :-)
This has been bugging me for a while and I worked this out by expanding on on CommonsWare's answer:
I am currently using this solution that sped up my Activity loading time greatly and make everything look as smooth as it gets.
My MapActivity:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_map); // See activity_map.xml below.
// Start a runnable that does the entire Map setup.
// A delay does not seem to be necessary.
Handler mapSetupHandler = new Handler();
Runnable mapSetupRunnable = new Runnable() {
public void run() {
FragmentManager fragMan = getSupportFragmentManager();
FragmentTransaction fragTransaction = fragMan.beginTransaction();
final SupportMapFragment mapFragment = new SupportMapFragment();
fragTransaction.add(R.id.container_map, mapFragment, "mapFragment");
fragTransaction.commit();
// At the end, retrieve the GoogleMap object and the View for further setup,
// zoom in on a region, add markers etc.
mapFragment.getMapAsync(new OnMapReadyCallback() {
#Override
public void onMapReady(GoogleMap googleMap) {
mMap = googleMap;
mMapView = mapFragment.getView();
setUpMap();
}
});
}
};
mapSetupHandler.post(mapSetupRunnable);
}
layout/activity_map.xml:
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<!--This FrameLayout will be used by the GoogleMap-->
<!--as a container for the SupportMapFragment.-->
<FrameLayout
android:id="#+id/container_map"
android:layout_width="match_parent"
android:layout_height="fill_parent"
android:layout_above="#id/bar_room_password"
android:layout_below="#id/toolbar">
<!--Initially the container is filled with a placeholder image.-->
<!--A small, heavily blurred image of a map screenshot is used-->
<!--in order to fake a loading map.-->
<ImageView
android:id="#+id/image_map_placeholder"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:alpha="50"
android:contentDescription="#string/map"
android:scaleType="centerCrop"
android:src="#drawable/placeholder_map" />
</FrameLayout>
[... more, unrelated Views...]
</RelativeLayout>
The Activity appears quickly because the setup is handled inside of a Runnable. Also, instead of just showing an empty View while the GoogleMap is doing its setup and downloads, I show a vague fake image of a map.
The Google logo is being placed on top of the ImageView relatively early so it looks pretty convincing with just a 128x128 pixel image:
I tried CommonsWare's answer, but there was a significantly delay launching even a bare MapActivity without a MapView in it.
So, I put another activity in the middle, "MapLoading". My home activity launches MapLoading, which then uses post() to immediately launch the MapActivity. Because of the lag, the app sticks on MapLoading for a few seconds (which is the intended result, as opposed to sticking on my home activity).
The MapLoading activity has noHistory set so when the back button is clicked from the MapActivity it goes right through to the home screen. Future launches of the MapActivity are very fast and the MapLoading activity just flashes on the screen.
Here is the code for MapLoading (the activity with the MapView in it is called Map):
public class MapLoading extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.maploading);
new Handler().post(new Runnable() {
public void run()
{
startActivity(new Intent(MapLoading.this, Map.class));
}
});
}
}
Here is its layout:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<TextView
android:id="#+id/maploading"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:gravity="center"
android:textSize="14pt"
android:text="Loading map..."
/>
</RelativeLayout>
And the corresponding stanza in AndroidManifest.xml:
<activity android:label="#string/app_name"
android:name="MapLoading"
android:noHistory="true" />