ArcGIS for Java: Event when layer is completely loaded - arcgis

I'm new to the development of ArcGIS for Java. Currently, I've got an application which creates a JMap and loads 3 layers:
ArcGISTiledMapServiceLayer (World_Imagery)
ArcGISTiledMapServiceLayer (World_Transportation)
GraphicsLayer to display some GPS-Points as Polylines
When all the map content is fully loaded, I want to save the map as an image. At the moment this is done by writing a bufferedImage to a file. Because in future the application should run automatically in backgorund, without showing the JFrame, I need some sort of event, signalizing when all content is loaded.
I searched the API-Reference, but couldn't find anything.
Is there any chance to get the correct moment, when all the work is done? Is there a more elegant way to save the map as an image?
Thanks in advance!

for all people encountering the same problem, there is the ProgressEvent, "which is fired by the map and indicates the draw progress of the Map's layer collection"
Therefore, saving the fully loaded map as an image is possible, when the progress has reached 100 %:
jMap.addProgressEventListener(new ProgressEventListener()
{
#Override
public void progress(ProgressEvent event)
{
System.out.println(event.getProgress());
if(event.getProgress() == 100)
{
SaveMap((JComponent) appWindow.getComponent(0));
}
}
});

Related

Cannot find the exact eror sometimes showing Adapter not attached sometimes cannot find memetrack [duplicate]

I'm running Ubuntu 16.04. And on Android Studio when I try to run my application in the emulator I get the following error:
FATAL EXCEPTION: main
Process: project name here, PID: 2528
java.lang.RuntimeException: Canvas: trying to draw too large(216090000bytes) bitmap.
at android.view.DisplayListCanvas.throwIfCannotDraw(DisplayListCanvas.java:260)
at android.graphics.Canvas.drawBitmap(Canvas.java:1415)
at android.graphics.drawable.BitmapDrawable.draw(BitmapDrawable.java:528)
at android.widget.ImageView.onDraw(ImageView.java:1316)
at android.view.View.draw(View.java:17185)
at android.view.View.updateDisplayListIfDirty(View.java:16167)
at android.view.View.draw(View.java:16951)
at android.view.ViewGroup.drawChild(ViewGroup.java:3727)
at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3513)
at android.view.View.updateDisplayListIfDirty(View.java:16162)
at android.view.View.draw(View.java:16951)
at android.view.ViewGroup.drawChild(ViewGroup.java:3727)
at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3513) at
etc...
I did have to run through some hoops to get my emulator working however, needed to create a sym-link so I can run the emulator on AMD. Not sure if this is part of the problem. And for the life of me I cannot figure why it continues to do this. In my group there are others who emulate the project just fine on the same emulated phone and SDK.
Move your image in the (hi-res) drawable to drawable-xxhdpi. But in app development, you do not need to use large image. It will increase your APK file size.
The solution is to move the image from drawable/ folder to drawable-xxhdpi/ folder, as also others have mentioned.
But it is important to also understand why this somewhat weird suggestion actually helps:
The reason is that the drawable/ folder exists from early versions of android and is equivalent to drawable-mdpi. When an image that is only in drawable/ folder is used on xxhdpi device, the potentially already big image is upscaled by a factor of 3, which can then in some cases cause the image's memory footprint to explode.
This solution worked for me.
Add these lines in your Manifest application tag
android:largeHeap="true"
android:hardwareAccelerated="false"
I had the same problem.
If you try to upload an image that is too large on some low resolution devices, the app will collapse.
You can make several images of different sizes (hdpi, xxdpi and more) or simply use an external library to load images that solve the problem quickly and efficiently.
I used Glide library (you can use another library like Picasso).
panel_IMG_back = (ImageView) findViewById(R.id.panel_IMG_back);
Glide
.with(this)
.load(MyViewUtils.getImage(R.drawable.wallpaper)
.into(panel_IMG_back);
This issue can be resolved by 3 methods as follows:
Method 1:
By adding image into a res/drawable-nodpi folder (By doing this it will not pre-scale your image).
Method 2:
Generate all dpi(hdpi,ldpi,mdpi,xhdpi,xxhdpi,xxxhdpi) of image and add to drawable folder. (This process will increase APK size).
Method 3:
Add image to drawable/drawable-xxhdpi folder.
All these methods are verified.
Turns out the problem was the main image that we used on our app at the time. The actual size of the image was too large, so we compressed it. Then it worked like a charm, no loss in quality and the app ran fine on the emulator.
For this error was like others said a big image(1800px X 900px) which was in drawable directory, I edited the image and reduced the size proportionally using photoshop and it worked...!!
If you don't want your image to be pre-scaled you can move it to the res/drawable-nodpi/ folder.
More info: https://developer.android.com/training/multiscreen/screendensities#DensityConsiderations
if you use Picasso change to Glide like this.
Remove picasso
Picasso.get().load(Uri.parse("url")).into(imageView)
Change Glide
Glide.with(context).load("url").into(imageView)
More efficient Glide than Picasso draw to large bitmap
I also had this issue when i was trying to add a splash screen to the android app through the launch_backgrgound.xml . the issue was the resolution. it was too high so the images memory footprint exploded and caused the app to crash hence the reason for this error. so just resize your image using a site called nativescript image builder so i got the ldpi,mdpi and all the rest and it worked fine for me.
I just created directory drawable-xhdpi(You can change it according to your need) and copy pasted all the images to that directory.
This can be an issue with Glide. Use this while you are trying to load to many images and some of them are very large:
Glide.load("your image path")
.transform(
new MultiTransformation<>(
new CenterCrop(),
new RoundedCorners(
holder.imgCompanyLogo.getResources()
.getDimensionPixelSize(R.dimen._2sdp)
)
)
)
.error(R.drawable.ic_nfs_default)
.into(holder.imgCompanyLogo);
}
Try using an xml or a vector asset instead of a jpg or png.
The reason is quite obvious in the exception name itself i.e. the resolution of the resource is too large to render.
You can png to xml using online tools like https://svg2vector.com/ OR add your image to drawable-xxhdpi folder.
Solution for Picasso is add Transformation for resize image.
class ResizeTransformation(private val maxSize: Int) : Transformation {
override fun transform(source: Bitmap?): Bitmap? {
var result:Bitmap? = null
if (source != null) {
var width = source.width
var height = source.height
val bitmapRatio = width.toFloat() / height.toFloat()
if (bitmapRatio > 1) {
width = maxSize;
height = (width / bitmapRatio).toInt()
} else {
height = maxSize;
width = (height * bitmapRatio).toInt()
}
result = Bitmap.createScaledBitmap(source, width, height, true)
source.recycle()
}
return result
}
override fun key() = "resize()"
}
Use:
Picasso.get()
.load(url)
.transform(ResizeTransformation(2400)) //FHD+ resolution
.into(view)
Convert your all png formats into webs format. You can do it by Android Studio.

Xamarin Xaml force update interface elements

The post has been rewritten to better fit the current problem.
I have a button x:Name="selectVesselButton". On button click, it tries to establish a connection to a server, which takes a sec or two for to do. Originally, I wanted the button to be grayed out while it was downloading and deserializing the json file from the connection.
My old code (before async, and trying to update the button):
// disabling the button to prevent spam clicking.
string buttonText = selectVesselButton.Text;
selectVesselButton.IsEnabled = false;
selectVesselButton.Text = "loading...";
// retrieve data for speed page.
RetrieveData();
// redirect to next info block if build was successfull.
FocusSpeedblock();
// enabling the button again.
selectVesselButton.Text = buttonText;
selectVesselButton.IsEnabled = true;
The issue with this code was that the button visuals did not update until the RetrieveData() was finished, defeating the purpose of doing that at all. This was because the code for updating the interface and the code for downloading and deserializing the object were both on the same thread.
However, following Ivan's advice, I made the downloading and deserializing Async, which fixed this issue (more like moved it).
This works fairly well, but I am still having some trouble updating the interface automatically. I have some labels that need to be updated based on the json file output. The value of the labels update on the background, but only update visually once I interact with the labels (I.E. scrolling the scrollview they are on). Check edit 3 for more detail on that.
EDIT 3:
When the second thread is finished, it should call the UpdateSpeedLabels() and update some labels. However, they update in codebehind, without instantly updating the interface. They only update if I interact with those labels.
The preferred way of doing this on Xamarin is with data binding. As you opted out of this it is still possible.
What you need is to ensure that your long task is not running in the UI thread as it blocks it and prevent its updates. You do this by using Task.Run(() => { your task code }); . However you can't update your user interface inside the Task.Run as it is not running on the UI thread and it would crash the app, so you need to use Device.BeginInvokeOnMainThread(() => { your UI code }); inside Task.Run for that part.

Cannot read image file in appcelerator titanium

I have an image stored at /assets in my project folder and I am trying to read it using Ti.Filesystem.getFile(). The code prints the blob data in android but it prints undefined in iOS.
Following function is called on Button click event https://pastebin.com/QgqLQPyz
function readImg(e) {
var localPath = '/butterfly.jpg';
var cachedFilename = Ti.Utils.sha1(localPath) + localPath.substr(localPath.lastIndexOf('.'));
console.log("cachedFilename:---"+cachedFilename);
var cachedFile = Ti.Filesystem.getFile(Ti.Filesystem.applicationCacheDirectory, cachedFilename);
if(!cachedFile.exists()){
var blob = Ti.Filesystem.getFile(Ti.Filesystem.resourcesDirectory, localPath).read();
console.log("-----------blob in not exists:"+JSON.stringify(blob));
}
}
When the same image path is set in ImageView it gets displayed so the issue is not with path . What am I missing here ? pls help. Thank you.
The best option so you don't have to do anything specific to the images at all (keep in mind, image manipulation is pretty heavy to do on runtime), is to use a module that was made for this purpose, av.imageview. This allows you to configure all kinds of content modes.
An option to get your code to work is to get the blob using the the getAsset method.
var blob = Ti.Filesystem.getAsset('/images/butterfly.jpg');
and then resize where you see fit. But I would advise you, if you do need to do this every time the app runs, then just resize once and store that resized image to be used after that. That way there will only be a single time the image needs resizing.

IBDesignables and traitCollection in live rendering

I am building my custom UIControl, a custom button built as an IBDesignable, which needs to change based on the size class in which it is being displayed. I have a method -setupForTraitCollection, which looks like this:
func setupForTraitCollection() {
switch(traitCollection.horizontalSizeClass, traitCollection.verticalSizeClass) {
case (.Regular, _):
// iPad - not compressed design
compressed = false
default:
// iPhone - compressed design
compressed = true
}
}
This code works great when compiled, but in live rendering, and when debugging the view, it never hits the "iPad" switch case. I am starting to give up here and simply accept that traitCollections aren't available in live rendering, but I'd like to have this confirmed. Better still, if someone could point me in the direction of finding a solution.
So the to-the-point question is - Can I use traitCollections in an IBDesignable and if so, how?
I'd really like to be able to change size class in IB and see the result on my custom control.
Interface Builder does not yet set the trait collection for designable views when we are rendering in Xcode. We are tracking this with radar://17278773. Filing a report at http://bugreport.apple.com and mentioning that bug ID will help us track demand and prioritize appropriately.

How can I trigger the loading animation of a WinJS ListView

is there a way to trigger the loading animation of a ListView manually?
I load some data on start up from a web service and would like to display a busy indecator.
function searchData(url) {
var promise = DataService.getData(query);
promise.done(function (result) {
console.dir(result);
var bindingList = new WinJS.Binding.List(result);
sectionListView.winControl.itemDataSource = bindingList.dataSource;
});
}
this is what I do in app.onactivated
promise = WinJS.UI.processAll();
promise.done(function () {
searchData(query);
});
args.setPromise(promise);
I read something that ListView should display busy animation while waiting for a promise...
Is this true?
Or is this something I have to do manually... display and hide a div whenever needed?
Thanks for any help...
According to this thread, the progress ring will only appear if the ListView is hooked up to an asynchronous data source, while the WinJS.Binding.List is synchronous. I don't think there are any asynchronous data sources available by default, so you would have to set up a custom data source to be able to get that default progress ring. I would recommend just setting a progress ring to run when your app starts and removing it in the done block of your data promise.
You need to create your own custom List Data Source. WinJS provides the utilities to do this pretty easily. This is a good sample against the Bing web service. If you need more samples of how to write your own Data Source / Data Adapter let me know, I've written a few.