I'm making a Java ME application for Symbian S60 5th edition and I have problem with the memory. After some time of running the app I recieve the out of memory exception.
I'm getting images from Google Maps (by the integrated GPS in Nokia 5800) and showing them.
I have this implemented like this:
class MIDlet with method setForm()
class Data which has a thread that collects info about the coordinates, gets image from Google maps, creates new form, appends the image, and calls the method setForm(f) from the Midlet.
Probable the Display.setCurrent(Form f) keeps references on the forms and like this the memory gets fast full.
I tried with Canvas but it has some stupid UI (some circle and some 4 buttons) that I don't like.
How can I solve this problem?
PS: the code...
In class MIDlet
public void setInfo(Form f)
{
getDisplay().setCurrent(f);
}
in class TouristData which collects information about location and gets map image
private attributes:
private Form f=null;
private ImageItem imageItem=null;
private Image img = null;
method locationUpdated which is called when recieve new location:
public void locationUpdated(LocationProvider provider,final Location location)
{
if (!firstLocationUpdate)
{
firstLocationUpdate = true;
statusListener.firstLocationUpdateEvent();
}
if(touristUI != null)
{
new Thread()
{
public void run()
{
if(location != null && location.isValid())
{
//lokacija je, prikaži!
try
{
QualifiedCoordinates coord =location.getQualifiedCoordinates();
if(imageItem == null)
{
imageItem = new ImageItem(null,null,0,null);
imageItem.setAltText("ni povezave");
f.append(imageItem);
}
else
{
img = googleConnector.retrieveStaticImage2(360,470, coord.getLatitude(), coord.getLongitude(), 16, "png32"); //z markerje
imageItem.setImage(img);
}
}catch(Exception e)
{}
}
else
{
}
}
}.start();
}
}
Are you keeping references to the forms or the images? These will keep them from being garbage collected and will cause out of memory errors.
It is hard to tell without some source code. Anyway, it will be better to re-architect your Midlet not to create new forms, but to reuse the same one.
Related
i have integrate AutocompleteSupportFragment on map fagment .when im click on place search .app is crashed.its giving error.java.lang.NullPointerException: Place Fields must be set.
AutocompleteSupportFragment autocompleteFragment = (AutocompleteSupportFragment)
getChildFragmentManager().findFragmentById(R.id.autocomplete_frag);
if (autocompleteFragment != null) {
autocompleteFragment.setPlaceFields(Arrays.asList(Place.Field.ID, Place.Field.NAME));
}
if (autocompleteFragment != null) {
autocompleteFragment.setOnPlaceSelectedListener(new PlaceSelectionListener() {
#Override
public void onPlaceSelected(#NonNull Place place) {
// TODO: Get info about the selected place.
Toast.makeText(getContext(),place.getName(),Toast.LENGTH_SHORT).show();
}
#Override
public void onError(#NonNull Status status) {
// TODO: Handle the error.
Toast.makeText(getContext(),"Error",Toast.LENGTH_SHORT).show();
}
});
}
I had the same issue, and the Google developer Doc on this doesnt tell you the step you need to initialize Places (why would they include that...), but all you need to do is add the following snippet where you initialize the autoCompleteFragmentvariable.
if (!Places.isInitialized()) {
Places.initialize(getApplicationContext(), "YOUR_API_KEY);
}
Cheers
I'm trying to request a permission at runtime for my app. I use a service provider to talk between the portable class and Android.
I start by calling this code on button press in the PCL:
using (new Busy(this))
{
var locationHelper = scope.Resolve<ILocationHelper>();
locationHelper.GetLocation(this);
}
This calls my Android level service:
public class AndroidLocationHelper : ILocationHelper, ILocationListener
{
readonly string[] PermissionsLocation =
{
Manifest.Permission.AccessCoarseLocation
};
const int RequestLocationId = 0;
public void GetLocation(SearchViewModel viewModel)
{
try
{
const string permission = Manifest.Permission.AccessCoarseLocation;
if (((int)Build.VERSION.SdkInt < 23) || (CheckSelfPermission(permission) == Permission.Granted))
{
}
else
RequestPermissions(PermissionsLocation, RequestLocationId);
}
catch (Exception ex)
{
Debug.WriteLine("Error while getting Location service");
Debug.WriteLine(ex.Message);
Messaging.AlertUser("There was an error with determining your location");
}
}
However, I get two errors on CheckSelfPermission and RequestPermissions. These two methods are only available to activities. The code works fine in MainActivity; however, I want to ask for permissions when the user hits a button, not in OnCreate or OnResume, etc.
Thanks for any help.
In your Android project, You can use this and use the Dependency Service to call it in Xamarin.Forms PCL project later:
var thisActivity = Forms.Context as Activity;
ActivityCompat.RequestPermissions(thisActivity, new string[] {
Manifest.Permission.AccessFineLocation }, 1);
ActivityCompat.RequestPermissions(thisActivity,
new String[] { Manifest.Permission.AccessFineLocation },
1);
You can try with ContextCompat.CheckSelfPermission, passing the application context, like this:
ContextCompat.CheckSelfPermission(Android.App.Application.Context, permission)
Update
In case of ActivityCompat.RequestPermissions, which requires an activity reference, you can keep track of the current activity. There is a very handy lib for that, called "CurrentActivityPlugin". You can find at https://github.com/jamesmontemagno/CurrentActivityPlugin
Rafael came up with a solution but I found another option that is a lot less effort just using MessagingCenter. In the MainActivity's OnCreate add a receiver that runs all the location code, that way you have access to all of the activities methods (and there are a bunch of tutorials on doing location services in MainActivity). Then add the Send inside of your service (the class).
To expound Rafael Steil's answer, I tried the suggested CurrentActivityPlugin and it worked on me. In my case I am trying to execute a voice call which needs CALL_PHONE permission. Here is the code snippet in your case: I used the ContextCompat & ActivityCompat so that I don't need to check the VERSION.SdkInt
using Plugin.CurrentActivity;
public void GetLocation(SearchViewModel viewModel){
var context = CrossCurrentActivity.Current.AppContext;
var activity = CrossCurrentActivity.Current.Activity;
int YOUR_ASSIGNED_REQUEST_CODE = 9;
if (ContextCompat.CheckSelfPermission(context, Manifest.Permission.AccessCoarseLocation) == (int)Android.Content.PM.Permission.Granted)
{
//Permission is granted, execute stuff
}
else
{
ActivityCompat.RequestPermissions(activity, new string[] { Manifest.Permission.AccessCoarseLocation }, YOUR_ASSIGNED_REQUEST_CODE);
}
}
It's dead simple
public bool CheckPermission()
{
const string permission = Manifest.Permission.ReceiveSms;
return ContextCompat.CheckSelfPermission(Forms.Context, permission) == (int) Permission.Granted;
}
I have an application which when starting requests a qr code from the user, and according to the qr scanned, a different fragment is loaded in the activity
I am using ZXing mobile scanner to do this
unfortunatelly the scanner returns a reply way before it shuts down and returns to the calling activity
this means that when I call the transaction code to replace the current fragment with the new one, the activity is not yet in the foreground so nothing happens
To solve this I created a ManualResetEvent (I'm using Xamarin, but I will use a Semaphore when I have to convert this to Android Studio) that I set before starting the scan , and then reset in the OnResume part of the activity
this seems to solve the problem, but it feels like there is a much better solution
Is there something I am missing?
thanks in advance for any help you can provide
Edit: the code I am currently using
public class MyActivity : Activity {
ManualResetEvent _has_resumed = new ManualResetEvent(false);
.....
protected override void OnResume() {
base.OnResume();
_has_resumed.Set();
}
......
void scan_qr(Action<string> finished_callback) {
#region initialize the scanner
MobileBarcodeScanner scanner = new MobileBarcodeScanner();
MobileBarcodeScanningOptions options = new MobileBarcodeScanningOptions();
options.UseNativeScanning = true; //use native scan
options.AutoRotate = false;//do not rotate the screen
options.PossibleFormats = new List<BarcodeFormat> { BarcodeFormat.QR_CODE }; // only allow qr_codes;
#endregion
#region perform the actual scan, when it finishes return to the main thread and execute the callback
_has_resumed.Reset();
scanner.Scan(this, options) //do scan
.ContinueWith(result => {
_has_resumed.WaitOne();
return result.Result;
})//wait until the activity has resumed
.ContinueWith((task_result) => { //then return the result
Result result = task_result.Result;
if (result == null) {
show_toast( Resource.String.questions_select_error_no_qr_scanned );
} else {
finished_callback(result.Text);
}
}, System.Threading.Tasks.TaskScheduler.FromCurrentSynchronizationContext());
#endregion
}
}
I've an application in Windows forms that connects to 16 serialports. The structure I used for each one is:
private void Serial_CodeNip_15_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
{
string S = Serial_CodeNip_15.ReadExisting();
myProcess(S);
}
public delegate void del_myProcess(string stringa);
private void myProcess(string stringa)
{
if (this.InvokeRequired)
{
del_myProcess tmp = new del_myProcess(myProcess);
try
{
this.Invoke(tmp, stringa);
}
catch (Exception)
{
}
}
else
{
// my code here
}
}
Receiving data from barcode readers, works fine until more Readers (up 6 or 7) start reading at the same time. In this cases my application tends to hang and all readers denotes a difficult to catch data from serial input buffers. Is this the correct way to read async data from serialports or there’s another simple way to do that. I noticed that working with few serialports there’s no problem.
Thank you in advance for helping
Guys Im using the following custom code to load 20 images from resources and present in a viewpager
public class CustomPagerAdapter extends PagerAdapter {
int[] mResources = {
R.drawable.slide1,
R.drawable.slide2,
R.drawable.slide3,
R.drawable.slide4,
R.drawable.slide5,
R.drawable.slide6,
R.drawable.slide7,
R.drawable.slide8,
R.drawable.slide9,
R.drawable.slide10,
R.drawable.slide11,
R.drawable.slide12,
R.drawable.slide13,
R.drawable.slide14,
R.drawable.slide15,
R.drawable.slide16,
R.drawable.slide17,
R.drawable.slide18,
R.drawable.slide19,
R.drawable.slide20,
};
Context mContext;
LayoutInflater mLayoutInflater;
public CustomPagerAdapter(Context context) {
mContext = context;
mLayoutInflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
#Override
public int getCount() {
return mResources.length;
}
#Override
public boolean isViewFromObject(View view, Object object) {
return view == ((LinearLayout) object);
}
#Override
public Object instantiateItem(ViewGroup container, int position) {
View itemView = mLayoutInflater.inflate(R.layout.pager_item, container, false);
ImageView imageView = (ImageView) itemView.findViewById(R.id.imageView);
imageView.setImageResource(mResources[position]);
container.addView(itemView);
return itemView;
}
#Override
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView((LinearLayout) object);
}
}
This works fine but I want to put the jpgs in a directory on the device so that they can be changed without recompiling the app
I think I need to get the images into the mResource array. I can get the path but not sure what format the code should be instead of using the draw-able lines
i have read articles on here but none make sense to me I am really new to this and the code looks nothing like the code I am using
can anyone point me in the right direction?
Any help is greatly appreciated
Mark
Yes, you can certainly do so. I will try to explain you the process step-by-step,
Step 1
Have a File object pointing to the path, like,
File directory = new File("path-to-directory");
Ensure that the path is to the directory with the images,
Step 2
List all the files inside the directory using listFiles() method, like
File[] allImages = directory.listFiles();
Now you have an array of all the files just like int[] mResources. The only difference being, now you have actual file references, while previously you had resource ids.
Step 3
You can just display the images in the ViewPager just like you did previously. But this is a bit tricky and can take you a considerable amount of time and code to get an image properly displayed from File.
You also need to take care of caching, so that when you load a previously loaded image again, it gets it from the cache.
To do all this, I recommend you to use this library (recommended by Google), Glide.
Setting an image is one line of code,
Glide.with(context).from(file).into(imageView);
That's it. Now you have your images displayed in a ViewPager from a directory in the device.