Using the Google Glass GDK, I'm trying to put together a simple app that displays / updates a live card. In my Service, I have the following method:
private void publishCard(Context context) {
Card updatedCard = new Card(context);
updatedCard.setText("Foo");
updatedCard.setInfo("Bar");
RemoteViews cardViews = updatedCard.toRemoteViews();
if (cardViews == null)
Log.e(TAG, "Appears to happen every time!")
// Then do some other stuff that fails because of a null RemoteViews
}
As you can see above, the null check seems to fail every time. Any idea why that might be?
My thought is that I'm calling this and passing in a Service as the context rather than an Activity, and maybe you're not supposed to do that? If that were the case, though, how would you be able to update a Live Card? I am capable of constructing a RemoteViews from an XML, but being able to use a Card would simplify things a lot.
That method is not currently implemented; you can follow issue 268 on our issue tracker if you want to keep track of the progress.
For now, you will have to create your own layout XML and use that to create the RemoteViews.
Related
I am using androidx.wear.compose.material.TimeText (link) in my wear app to show the time on top of the screen. I am trying to write a screenshot test where I set a fake time for the screen.
TimeText has timeSource (link) parameter that I can manually set in order to give time. For this, I created real and fake implementations of TimeSource to use in production and tests, respectively using Hilt.
However, I have one condition. Inside my test class, I need to do something like:
private val fakeTimeSource = FakeTimeSource()
fakeTimeSource.setCurrentTime("10:10")
And I should not pass fakeTimeSource to any class that uses real TimeSource but it should update the time. Is it possible? If yes, how can I achieve this?
Note: Or any other approach is fine to fake it. It doesn't have to use TimeSource.
Things were going well until I switched off the screen lock on my device, then things started going wrong intermittently.
I've managed to track the issue down and have some workarounds in mind BUT I would like to know if there is 'best practice' for avoiding or removing the issue.
The issue:
I have an application which changes images based on the application status.
The images are not huge but quite large (231k~) and are stored as resources.
After several screen rotations (I counted 27 with a project using a single ImageView), loading the images fails with Exception of type 'Java.Lang.OutOfMemoryError'
Stripped down to the barest project, the following demonstrates the problem:
protected override void OnCreate (Bundle bundle)
{
base.OnCreate (bundle);
// Set our view from the "main" layout resource
SetContentView (Resource.Layout.Main);
//get a reference to the ImageView
var imageView = FindViewById<ImageView>(Resource.Id.imageView1);
imageView.SetImageBitmap( Android.Graphics.BitmapFactory.DecodeResource( this.Resources, Resource.Drawable.Ready) );
}
The above code is the only method I used to reproduce the issue.
Whilst attempting to resolve, I extended the example so that imageView was released in OnDestry:
protected override void OnDestroy ()
{
base.OnDestroy ();
imageView.SetImageBitmap( null );
imageView.DestroyDrawingCache();
imageView.Dispose();
}
This made no difference unless I added GC.Collect() which I don't want to do.
The best workaround I've currently thought of so far would be to modify the code as follows:
static Bitmap _ready = null;
private Bitmap GetReadyImage {
get {
if (_ready == null) {
_ready = Android.Graphics.BitmapFactory.DecodeResource (this.Resources, Resource.Drawable.Ready);
}
return _ready;
}
}
protected override void OnCreate (Bundle bundle)
{
base.OnCreate (bundle);
// Set our view from the "main" layout resource
SetContentView (Resource.Layout.Main);
//get a reference to the ImageView
imageView = FindViewById<ImageView>(Resource.Id.imageView1);
imageView.SetImageBitmap( GetReadyImage );
}
This relies upon a static reference to each Bitmap and a property accessor for each.
I could even write a method which stores the images in a static List to save writing property accessors for each different property/variable.
I could perhaps add the flags ConfigurationChanges = ConfigChanges.Orientation | ConfigChanges.ScreenSize |ConfigChanges.KeyboardHidden) but this would break the normal Activity lifecycle which I've read isn't best practice?
I find it strange that having scoured the web, I've not yest encountered similar issues or examples. I'm left wondering how most others deal with this?
Any thoughts or comments are much appreciated.
I can only approach this problem from a truly native perspective, as I have not worked directly with the Mono framework.
The described symptoms are 100% indicative of a memory leak in the Activity, but the code shows no real evidence. If you can truly produce the issue with a project containing only one Activity and those four lines of code, it sounds to me like it is perhaps a framework bug that ought to be filed with Xamarin. Have you attempted to create the same simple project in pure Java to see how the results fare on the same device/emulator you are using? It would also be interesting to know if the issue is localized to a specific version of Android. I have never seen this particular behavior before in a native application project.
The awkward part is your statement that forcing a garbage collection makes the problem go away. You're right, you shouldn't have to do that, but a true memory leak (i.e. an unreleased reference) would still persist even if you hit the GC several times. The Android paradigm of destroying and re-creating the Activity on each rotation is such that even if the old Activity lived for awhile, when memory was tight it (and all its references) would quickly be collected to make room for a new instance. If this is not happening, and each Activity is living on past even the system triggered GC passes, perhaps there is a stuck reference in the native code generated by Mono.
Interestingly enough, technically your workaround actually does introduce a true leak, by attaching the Bitmap to a static field that is never cleared. However, I agree that in comparison it seems like a more efficient move. A simpler workaround might also be to code your Activity to manually handle configuration changes (I don't know if Mono is different, but this is accomplished by adding android:configChanges="orientation" to the manifest file). This will keep your Activity from being recreated on each rotation, but it may also require you to reload your view hierarchy if you have different layouts for landscape and portrait. However, even if you have to do this the Acitivity instance will be the same you can safely save the Bitmap without resorting to a static field.
However, if you cannot reproduce the problem with the same project in a native Java project, I would report a Mono bug.
Hard to see without the entire code but it obviously sounds like you have a memory leak. Screen rotation (due to the destroying/creation of the activity) is known to cause these. You might want to have a read at this article by Romain Guy as well as this talk from last year's IO.
I've been working on developing a library for my company for the past couple months and have been annoyed by the fact that filestreams seem to need a context whenever I store or load data to the internal storage.
I have designed the library to work like this :
A singleton class is made for providing and handling a keychain(containing app key and device id) and authinfo(user and password)
Whenever a request to call to a web service is made the calling class will attempt to get an instance of the singleton class and get the keychain and auth info through it like such :
SingletonClass.getInstance().getCredentials(Context ctx);
The result of this is that I need to constantly provide the context of the calling activity as most of my library revolves around calling an API with credentials and device id as parameters.
I am specifically referring to these lines :
....
FileOutputStream fos = ctx.openFileOutput(filename,
Context.MODE_PRIVATE);
fos.write(buf);
fos.close();
....
I am confused as to why the specific context of the activity calling is needed. Any help is greatly appreciated. Is there another way of solving this design issue ?
The application context should work for this - you could consider using this method: Using Application context everywhere? so you can easily get the application context without having to pass it around.
The file storage API is provided by the Context class.
So you need it.
I am trying to write a small application in Android. My application is on Widgets. I have a basic doubt on using RemoteViews. I found that whenever , I update some button or some UI layout a new object of the remoteviews is created . Will that be a problem with the performance? an example code is this:
http://android-developers.blogspot.com/2009/04/introducing-home-screen-widgets-and.html
updateViews = new RemoteViews(context.getPackageName(), R.layout.widget_message);
even for updating the views everytime, new remoteview object is created. Please help me in understanding this.
No it isn't a problem. I'm working with StackViewsWidget example to build a honeycomb widget that has a RemoteViews for each card in the deck of views that shuffle buy, and each card is recycled and rebuilt from what I can tell in the debugger, and it's smooth as butter flipping through the views on my Xoom.
You might consider creating only one object using singleton pattern. This can be done by implementing a singleton for your RemoteViews class and then using this singleton to create an object of RemoteViews. Actually the problem lies with the memory of the machine on which you are running the android app. If you are able to scale that up by doing some profiling and performance settings then you can very well create new objects using the above code. But if you have a limitation then I would suggest the singleton pattern. This solution assumes that the machine you are working on has enough processing power.
I am new to Android development.
I want to know how you all manage objects.
For eg we make object as A a = new A(); and then manage that object.
But, here, we call A.class;
My concern is that i dont want to call onCreate(),nor do i want to push UI screen.
I just want to make 1 static object for 1 screen;and want to manage it throughout my application
that is, instead of calling A.class; can i call A a = new A(),and manage that object without pushing,and whenever i need i push that screen. Is there someway ?
Thanks...
I just want to make 1 static object for 1 screen;and want to manage it throughout my application that is
That somehow describe what an Activity is for. Your complete question suggest that you have no idea how Android works and why it is meant to be. You should start at least with the fundamentals and than work through tutorials to get a feeling. Fundamentals can be found here: http://developer.android.com/guide/topics/fundamentals.html