During recent development of my app (see my signature) I focused a lot on how to optimize the already working code further in order to make it smoother without loosing quality or using too much memory. Well I came across some mistakes I had made in my early days of developing Android so I figured it might help the beginners and intermediate developers. So here I collected my suggestion of common mistakes and best practices in Android. Let me start by making you familiar with a motto which you might know if you have developed Perl before.
TIMTOWTDI
There's more than one way to do it, in short TIMTOWTDI is a well known aspect of the Perl language, which aims at giving programmers the freedom to choose their way of doing things. It “doesn't try to tell the programmer how to program.” Well it does have various disadvantages such as possibly messy code and barely readable code, but it offers programmers to use their preferred style.
The only reason why I'm bringing this up here is because it helped me a lot to think that way, since TIMTOWTDI sometimes applies to Java as well and a way somebody else is preferring might not be better than your own way. But it is never bad to have a look at how others code the important tasks and sometimes the performance or readability gain is tremendous. So I'm not telling you to exactly use my way, but advice all beginners to perhaps rethink their code .
Tweaking Android Apps
The first step is always to look at what the awesome Android documentation says about performance, so I can more than advise you to read this straightforward article about what to do and not to do on Android. It covers some very important performance issues like the expensive object creation and method invocations. It is crucial to follow those basic rules while trying to develop fast Android apps. I will cover and further explain some of their suggestions here, but will try to also look at them from a developer's perspective who cares about readability and simplicity.
Now onto the code, let's start with some basic Java practices and then move on to some more Android specific styles and improvements.
Looping wisely
Often it doesn't matter if you write slow code and lose 1 or 2 milliseconds but especially in loops and everything that can be called once a frame you suddenly loose a lot of time. Thus it is crucial to especially pay attention to those repeated parts of your code like the onDraw() method in your custom view implementation (see last section) and start optimizing there. Let's take a look at what kinds of loops we have, the slowest first and the fastest ones towards the end:
while
The while loop is probably the first complex programming structure you learned, and just writing
Java:
success = false;
while (!success) {
trySomething();
}
is extremly readable but can potentially run forever or longer than you need it to. One aspect which is often overlooked is that the condition inside the parentheses will be checked on every run of the loop! So even a simple string.length() call can be optimized (if the String won't change) saving its length as an int and then using that in the condition block.
Its unpredictability and lack of possible tweaking done by the JIT makes the while loop a tool that needs caution but is sometimes crucial to complete the task. Just make sure you only use the while loop if there is no way to predict when your condition is false. For almost all other cases, you can do some calculations and use one of the iteration loops:
for (traditional)
This one is widely used like this:
Java:
for (int i=0; i<getSize(); i++) {
doSomethingWithIndex(i);
}
Even though this is more predictable, consider how the program will run: Before every execution of the block, the condition i<getSize() has to be checked, so getSize() is called (and an Android, method calls are expensive!). You could now think, alright, we'll just cache our size upfront like we did with in our while loop, but examine the following fast example of iterating through an array:
Java:
for (int i=getSize()-1; i>=0; i--) {
array[i] = getNewValue(i);
}
The trick is starting at the last value and then iterating backwards until 0 is reached. This may not work at all times, where the order of the blocks may be important or it is redundant due to having a fixed end value, but it saves both method calls and memory usage needed to get the last value before going into the loop.
But that is hardly readable and you often have to rethink because of looping backwards, so we can do better can't we?
for (iterator-based: “foreach”)
Dealing with an array, List or other collection of data you can easily do something for every part in that collection using the foreach loop:
Java:
for (Object item : objects) {
doSomething(item);
}
That is the fastest way you can iterate through any kind of iterable collection because it can be heavily optimized by the compiler and is also simplistic and readable. The only problem here is that you don't have the index of the item you're getting and you can't write data to the collection. To accomplish that one of the slower for loops must be used.
Keywords do matter
This is a minor one that is overlooked often. Beginners in Java mostly don't use keywords and access modifiers like “private”, “public”, or “final”. That is fine since we all love simplistic code don't we? And an honest word, if you don't write a library or work on your code with a big team, you don't have to know much about the access modifiers, but if you want to, there is always the Java documentation. But the “final” identifier is actually pretty important to both the ones reading the code and also the compiler, since it can just insert its value into the references. That means, that whenever you declare an instance variable, think about if it is likely to change or if you can declare it as final. Within methods, making use of the “final” keyword does not really change much for the compiler, but it sometimes helps you make a clearer design so you directly get a compiler warning whenever you're trying to change a final variable's value.
A side note on making “static” variables and fields – I wouldn't recommend that on Android unless you know what you're doing or you're using it together with “final”. A “static final” instance variable is the best way to declare constants in Android because the compiler can replace it fast and ART can replace it during the install of your app!
Strings are special
Let's talk about something that is fundamental to Java – the String object. Well it's not a real object since it is actually immutable. That means a String can only be created or collected by the garbage collector, it can't be changed (which is very important since object creation is god damn expensive in Android so it would make our apps pretty slow)! Wait, then what happens if I call one of the awesome methods in the String class like substring() or replace()? And here comes the downside: These methods have to create new Strings and the old one is collected by the garbage collector. While this might be totally alright if you're just parsing some basic user input, if you need to perform some heavy String operations like many substrings, a whole lot of unused garbage and overhead is created. This doesn't only mean that you are temporarily using a lot of memory, with the garbage collector needed to kick in it also affects your performance.
So how do we get around this problem? Luckily there is a Java class which can do almost the same as the default String implementation, the StringBuilder. This class will hold a char array with all the chars you had in your String. The class can take care of managing that array like initializing it with a default length of 16 and creating a larger array once you have more characters that would fit into it. Take a look at the constructors as well – with new StringBuilder(length) you can directly make that array as long as it needs to be and with new StringBuilder(string) the array is instantly filled with the string. The big advantage the StringBuilder is that it can modify the array instead of having to create new Strings every time. If you're finished with the heavy modifying, just call toString() to get the String back.
If you want to read more about it, here's a nice article.
Android-specific tips
Bundling is better than trundling
Let me explain this with an example: Let's say you are dealing with some data concerning persons so you are saving their name, age and gender. In any object oriented language like Java you would create a wrapper object holding that data:
Java:
public class Person {
private String name;
private int age;
private boolean isMale;
public Person (String name, int age, boolean isMale) {
this.name = name;
this.age = age;
this.isMale = isMale;
}
// additional getters and setters go here.
}
Of course you could do that in Android as well, but you will encounter this problem: What if you need to save your Person array or need to pass a specific Person to another activity? Well, you have a few options available:
You could override the toString() method in Person so it contains all its data and parse your array into a String array manually. Then another constructor will be needed to get the data back from the String using our beloved String operations. But there is still the problem that when you want to add data to the person like height later, you have to reconsider the toString() method and it's constructor counterpart.
Alternatively, wanting to integrate it better into the system, you might want to implement Parcelable in the Person class. That way you can directly put person extras to your Intent or save it to SharedPreferences. But that seems like more work if you want only a simple container for your data. Once you need have a more complex class it might be advisable to make it Parcelable (perhaps using the Android Studio plugin, thanks @nikwen), but let's start with an easier apporach here.
This is how I do it: I use a Bundle instead of a person class to store all the needed data. The Bundle class already implements Parcelable and and simplifies adding data for you. What is more, you are probably already familiar with it since you get one calling getExtras() on the starting Intent of your activity! Now back to the example, this is how it would be done:
To not get confused about all the keys you need, let's create a class containing some static final keys:
Java:
public class Person {
public static final String NAME = “person_name”; // will contain a String
public static final String AGE = “person_age”; // will contain an int
public static final String ISMALE = “person_ismale”; // will contain a boolean
}
While this is only needed for consistent keys, here is how you would create the Person:
Java:
public Bundle getPerson(String name, int age, boolean isMale) {
Bundle person = new Bundle();
person.putString(Person.NAME, name);
person.putInt(Person.AGE, age);
person.putBoolean(Person.ISMALE, isMale);
return person;
}
Similarly, you can get one or more stored values of the Bundle using one of the person.get...() methods. Furthermore, instead of creating an array of Persons you can now create a Bundle of persons using bundle.putBundle()! You just need to find the right key-scheme, here you could either provide an id for each person or just use their names as key (although the key array has to be passed seperately). And what do we get from all this? Well we can now just call intent.putBundleExtra(person) and voilà, we've passed it to another app component.
Resourcing is not outsourcing
One of Android's big advantages is its exceptional resource system. The fact that all your Strings and values are saved in a separate xml file makes your app not only easier to translate, but also keeps your code cleaner and lets you have a complete overview of what amount of constants you use. But you can go further than that. The resources allow for entirely different configurations depending on screen size, resolution, orientation, location and api-level! To learn more about how this can be done, head over to the Android devoper guides.
One thing I wanted to highlight is that it used to be quite hard to make a consistent interface and still support Android 2.1 and above. That is not the case any more since we now the the continuously improving AppCompat library. It is even useful for apps targeting only ICS and above because it contains bugfixes and improvements for those versions as well. Using this library is the best way to get the holo theme and its ActionBar in your app, although if you could also try ActionBarSherlock to accomplish the latter.
Click to expand...
Click to collapse
Think D.I.P
So what's this strange thing they call dip? And why do we even bother using it, we have had pixels (pix) since the beginning of programming. First things first, try to avoid pixels on Android. On almost every other platform using the smallest unit that's available is a great thing in layouts, but not so much on Android where apps can run on devices as small as a smartwatch up to 2k tablets. The problem is that you can't be sure if a single pixel is as small it can barely be seen or as large as a few millimeters. That is why we have the standard-sized density-independent-pixels (dip or dp in short) where 48 dips are roughly equivalent to 9mm, the convenient size of a touchable area (e.g. a Button). Great, then how many dips is my screen wide/high? That is not an easy question since it varies as well. Phones usually have around 320dips (at the smallest width) but larger screens can fit more so on tablets you have 600dips or more. Try to understand this documentation and don't be confused with the abbreviations dp, dip and DPI – dp and dip are the same and DPI is dots per inch (similar to pixels per inch), the screen density!
The reason why I'm bringing this up here is advice you to understand and always think in dips, never in pixels. Even on a Canvas, where there is only methods for pixels, don't think “ok I draw my text 20 pixels from the left edge and 50 from the top so canvas.drawText(“text”, 20, 50, myPaint);”. Start to think in dips: “I have to draw it 16dip from the left edge and 24dip from the top!” But how to convert it to pixels so it can be actually drawn onto the Canvas? It really is a shame there is no method in the Context class to directly convert dip to pixels, so here's the one I use:
Java:
private DisplayMetrics displayMetrics;
/**
* Converts a given dip (density independent pixel) value to its corresponding pixel value.
* @param dips The dip value to convert, as float.
* @return The pixel value, as int.
*/
private int dipToPix(float dips) {
if(displayMetrics == null)
displayMetrics = getResources().getDisplayMetrics();
return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dips, displayMetrics);
}
And a side note on sp, that is the scale-independent text size. Try to use it as far as you can, for instance in layout resources. But just in case of needing the actual size, use the same method because sp is computed almost the same as dip.
Hyperthreading is not that complex
An app's UI (or “main”) thread is its beating heart, and we don't want to slow down what's powering us if there are other options available, right? If you don't follow the rule of not performing any time consuming tasks in the default thread you'll end up with what all developers fear: The “App is Not Responding” dialog – in short ANR. When users see this, they can get really mad, from just force closing your app and uninstalls to 1-star ratings everything is to be expected. Because it is crucial to know about Threads (and Processes), carefully read the guide in the Android docs about it, pay special attention to the two simple rules in Android threading:
1. Do not block the UI thread
2. Do not access the Android UI toolkit from outside the UI thread
Click to expand...
Click to collapse
Let's take a look at the first one, what are you going to do instead if you need to accomplish an expensive task like web requests, complex calculations, Bitmap operations, database queries and I/O management?
Well the answer is not as simple as it may seem since it depends on what and how often you will be doing that task. A task that is performed once per activity launch is almost always wrapped into an AsyncTask, a class which is heavily optimized and integrated into the system. If you know how it works it is a very powerful tool since it does most of the heavy lifting for you, so let me show you how to do it:
You start by extending the AsyncTask class like so:
Java:
private class MyAsyncTask extends AsyncTask<Param, Progress, Result> { //...
Usual stuff, except for the weird <Param, Progress, Result> thing. It is actually not that hard, these are all just type declarations of variables your methods want to use. Thus, the first one is the type of starting parameter you want. Think of it as if you wrote your task in a separate method without access to any instance variables, what data would it need to work (what params would you pass to it in the parentheses). The second one is actually often unused and is needed if you want to return a var indicating progress on the task so it can be published e.g. in a ProgressBar. Lastly, Result is (you may have guessed it) the type of variable you want your task to return, to be published in the UI as well. A typical configuration would be <Uri, Integer, String> for a task reading a file. Note that these have to be objects, so for primitives you'd have to use their respective Java classes like Integer or Double. But that also means that a Bundle can be used as well so we know how to pass multiple parameters now! And there is another way as well, look at the overridden methods:
Java:
protected Long doInBackground(Uri... uris) {
// do your expensive work here, it runs on a separate thread!
}
protected void onProgressUpdate(Integer... progress) {
}
You'll notice the three dots after Uri and Integer. To keep it simple, treat it as an array, so to access your value call uris[0] and progress[0], respectively. The reason for it being an array is that you can start the same AsyncTask with multiple parameters of the same task:
Java:
new MyAsyncTask().execute(uri1, uri2, uri3, uri4);
This is extremely useful in this case to read multiple files at the same time (don't be confused with the configuration in <> above, the param(s) passed to execute() are joined together in the Param array).
A side note on progress here, if you want to publish progress during your doInBackground(), just call publishProgress(Progress) and override onProgressUpdate() to publish the changes in the UI. Similarly with onPostExecute(), you'll probably want to override that method as well to show your awesome result to the user.
What you need to keep in mind is how AsyncTask is handled internally, read the section “The 4 steps” in the AsyncTask documentation carefully. In fact, doInBackground() is method you need to think about the most since it is encapsulated in a separate thread with no access to the UI or methods in your activity.
Because AsyncTask is limited to one operation and should only run up to a few seconds, there are a couple of other ways to do tasks in the background like a second Thread and helpers such as Handlers. The Handlers are needed to access the UI from the worker threads, still following the second rule above. If you want to read more here's an awesome Vogella tutorial about it.
Fragment-tation
This next one is really a good style of development and can save a lot of work if you provide layouts for both phones and tablets (which you definitely should). The basic theme of using Fragments is to follow the divide and conquer technique, which dates back to ancient time in Babylonia. Thus, the idea is to have one large problem (a user interface and its data for both tablets and smartphones) and split it into multiple simpler ones (in this case having one or more Fragments for each screen on phones). Especially in multi-pane layouts, for instance in the settings app, Fragments are a wonderful tool to avoid the use of two different activities, one for phones and one for tablets. The steps to implement them in your app are pretty simple and there are already some neat guides like the one in the documentation and Vogella's one. An additional use-case for Fragments is to retain an AsyncTask when rotating the screen. You would create a Fragment without layout in the UI and call setRetainInstance() on it. Any expensive AsyncTask can then be started inside that Fragment and is not stopped when the activity is recreated during an orientation change.
Memory-zing is unneeded
But it is not only performance, layout and style which can be improved, think about memory usage for a second. It goes hand in hand with performance since an app which consumes unnecessary memory (garbage) will be slowed down by the garbage collector (GC) thrown in from the system, trying heavily to free some RAM. On Android this is extremely important, since a garbage collector running intensely on a single or dual core processor can really slow down the device's performance. That is also why method calls and object creation are so expensive and have to be used with caution – the overhead they produce bumps up the memory usage. And there is one specific case where you can really have a problem with your memory, a so-called memory leak. What this means is that some part of your app is holding on to a very large object like a Resources or database one or even a whole Activity or Fragment. The problem is that the GC can only collect objects which aren't referenced from an active part of your app so this means it can't be collected and ends up blocking all your available memory. Such a leak is something you want to avoid at all times and there are some awesome tools to find out if you have one. All you need to know about that and memory optimizations in general is covered in this amazing I/O talk, so I advice you to watch that!
Most of the time there is no real need for reducing method calls and object creation because the GC is fast enough. But there is one step where it is crucial to avoid it, methods which are called on every redraw like the onDraw() method of a View, which I'll cover in the following.
Optimizing performance? onDraw!
In your custom views the most important method to think about is the onDraw() method since that is where everything that is visible to the user is rendered. A lot can be gained (or lost) in that crucial step, so try to follow the performance guidelines posted earlier as close as possible. Especially, pay attention to the object creation, creating a few objects in onDraw() might not seem expensive, but the memory footprint and the garbage collector usage will be tremendous. When drawing on a Canvas for instance, a common pattern would be to check if the paint instance variable is null before drawing:
Java:
if(paint == null) {
paint = new Paint();
paint.setColor(drawingColor); // ...
}
That code would typically be placed in the surfaceCreated(), but could also be in the onDraw() if you are lazy and want to keep it in one place. . While object creation is not the only thing you can improve performance-wise, just try to apply the aspects I wrote about in the beginning, especially those loops!
One thing I have to point out about performance before moving on to some links that might help you is that before trying to optimize your app in some arbitrary way (and totally destroying readability) measure upfront. That means use the tools mentioned in this great I/O talk covering graphics and performance to get a sense whether your app is really driving close to that 16 millisecond threshold to get the desired 60 frames. Additionally, it might be a good idea to not only test it on the high end devices (#Nexus5) but also those with a high “resolution/processing” value such as the first tablets with 1080p resolution. Thus, only start tweaking performance if you know you take too much time, then try to nail down the time consuming methods. And always try to improve readability and simplicity, not only for us when posting pieces of your code here but also for yourself: it helps getting into the flow if you see that your code is readable and nice .
Additional resources
If you can spare some time and want to know more about how to build awesome apps and UIs, check out the Android sessions at Google I/O 13, especially the Android UI design talk and the Android Protips 3 (but the first and second Protips were great as well as the beginner's talk from 2010). There is also the Android developers blog and the Vogella tutorials. As usual, the Android developers page is always a great resource and Google is still your friend (use “android dev” together with your question to get better results). For more info about general Java performance improvements, I found this nice pdf outlining how you can improve your code even further.
Click to expand...
Click to collapse
</guide>
Anyway, that's about it. It has really become a way too long collection of links and videos so I hope it was useful and perhaps made you rethink your code . If you've got any comments or suggestions feel free to post them here, helps a lot.
This guide was featured on the portal on February 4th (thanks eagleeyetom!)
To be continued...
One Thanks isn't enough!
Great writeup! Thanks!
Wow man such a good information muchly appreciated great job!
Sent from my Nexus 4 using Tapatalk
Wow, great collection of tips and tricks. Much appreciated!!
Handy tips
awesome job dude.was really helpful!!!!!:good:
Great article! Please keep going. :good:
Simply awesome...great work.
Sent from my SAMSUNG-SGH-T989 using Tapatalk
Thanks for this great writeup! The android specific tips are really interesting.
Great guide (again). :good:
Just one thing I want to add: I still prefer wrapper classes which implement Parcelable. In fact, it's not that difficult and you should be able to do it in a few minutes. Have a look at the example code here: http://developer.android.com/reference/android/os/Parcelable.html That's it.
I've also found an IntelliJ plugin for that purpose (but I haven't tried it yet): https://github.com/mcharmas/android-parcelable-intellij-plugin
That wasn't meant to degrade your work though. It's an amazing guide.
nikwen said:
Great guide (again). :good:
Just one thing I want to add: I still prefer wrapper classes which implement Parcelable. In fact, it's not that difficult and you should be able to do it in a few minutes. Have a look at the example code here: http://developer.android.com/reference/android/os/Parcelable.html That's it.
I've also found an IntelliJ plugin for that purpose (but I haven't tried it yet): https://github.com/mcharmas/android-parcelable-intellij-plugin
That wasn't meant to degrade your work though. It's an amazing guide.
Click to expand...
Click to collapse
Good point and thanks!
Having a closer look at it, implementing Parcelable is not that much work and it would definetely be the more advanced way. Bundle is basically just another layer that makes things a bit easier for the start (and no typecasting) and I found that it can really shine with a singleton class holding the keys and the getters and setters (which have an additional param, the Bundle). For a beginner who just wants to save some values (possibly keeping the keys in the activity or even hardcoded) using the Bundle is a lot easier. Yet again, TIMTOWTDI
Thank you!
Hey Simplicity, after few years there is something you would change? Maybe dagger2, kotlin, rxjava changed the game, as really open question what do you think about?
The question might be a bit off topic, i am working on a root app development but i am pretty confused that how should i get the busbox commands to run on button press, i have given the path and everything but how am i supposed to create a busbox file in data/data/package/files.
This part is confusing me I am not able to create that file, should i keep it in res while creating the app ? And also one last question, from where can i get that busbox file with all its command. Please help, I'm sorry if this is the wrong forum I'm new to posting questions and also to app development .
Related
Hi,
I've got a question about an issue to the thread safe execution.
The whole setup was made in order to have a business logic triggered by
struts, that still can retrieve information from its environment -- here Struts -- without
having explicit knowledge of it. In short, the processing is like this:
a) the ActionObject gets the business object
b) calls the business method on the business object including
-the HttpServletRequest just received in the perform call, and
-a reference to itself
c) the business object now uses this reference to retrieve from this object
some information about the business objects environment. Thus, the business object
calls the ActionObject (without knowing, that it is a struts Action) and hands in
the HttpServletRequest (as an java.lang.Object).
d) the ActionObject uses the HttpServletRequest to get the desired information
(like request.getParameter()) and returns the result back to the business object.
Basically, I want to know, if I can use a static method (no static fields) within the ActionObject
for performing the environment lookup thread safe.
Sounds a little complicated, doesn't it? Well, to those who have the time to get involved.
It's actually not that difficult.
The class structure in my struts app is like the following:
-Class MyActionClass: extends ...struts.Action implements myClasses.Environment
-Interface myClasses.Environment has (let's say) just one method:
public boolean isPropertySet(Object helperObject)
-Class DoSomeStuffRq is a class that contains
a)translated form data, and
b) an java.lang.Object reference to store the HttpServletRequest
(which the MyActionObject just has recieved in its perform method).
-Class MyBusinessClass: doSomeBusinessStuff(DoSomeStuffRq stuffInfo, Environment env)
The Environment interface is there in order to decouple Struts from the business logic - giving
the chance to reuse the MyBusinessClass when not using Struts anymore (well, I hope I don't
have to, but still).
So finer grained, the actions are:
1) Let the MyActionClass get the businessObject (of type MyBusinessClass),
2) MyActionClass calls the method businessObject.doSomeBusinessStuff(stuffInfo, this);
["this" is of type Environment]
3) in order to process the business actions, the BusinessObject has to
retrieve a boolean value from it's (unknown) environment. So it calls
the isPropertySet from the Environment interface (which has the MyActionClass implementation):
public StuffResponse doSomeBusinessStuff(DoSomeStuffRq stuffInfo, Environment env)
{
boolean importantProperty = environment.isPropertySet(stuffInfo.getObjectReference());
...
}
where stuffInfo.getObjectReference() gives the above mentioned HttpServletRequest reference
as a java.lang.Object.
4) the rest is quite obvious: myActionObject does a cast of the java.lang.Object to the HttpServletRequest
and gets a request parameter. Then, it returns a boolean value depending on that request parameter.
Well, there's lots to argue about in the whole scenario.
Questions like: does it make sense to do all that stuff to decouple business logic and Struts;
is there
a better way of passing the parameters between the objects, shall the MyActionClass handle
the lookup,
when all I need is a HttpServletRequest and so on.
But the simple question I'm interested in is: Can I have the MyActionClass' method
public boolean isPropertySet(Object helperObject)
being static?
I think, I can, because:
As long as I don't use any class members in the MyActionClass, the thread safety shall be
given -- no matter if the method is static or not. Is that true?
Well it's more a java related question, but I think there are some people here, who are interested
in this issue too.
Thanks in advance for your time,
greetings
was referred to this forum from someone at androidcommunity.com regarding this...
i searched the forum but couldnt find any relevant posts - can anyone point me in the right direction for doing this properly?
specifically how could one set an image resource based on a string variable being used for part of the image's file name
i tried this based on a post i saw elsewhere:
myContext.getResources().getIdentifier(myStringVariable + "_thumbnail", "drawable", myContext.getPackageName()));
but it returnes a string(or an integer?) of numbers (the resource id?) that setImageResource couldnt use unless i just wasnt doing it properly.
is there perhaps a way to get the resource name based on that id number or whatever it is that im getting?
apreesh
33 views
dang
getIdentifier() returns int and yes, it could be used in setImageResource() method.
But why you want to set resources from strings?
because the image being set is based on user selection and is not just one image its several associated images so there is a number sequence to the image file names as well that i did not show in the snippet i posted.
but i went back and plugged some of those returned values (resources ids?) from getIdentifier() into setImageResource() and it does indeed work so thanks for that - i have an idea what i was doing wrong before but for the sake of moving on im using a different solution now - in short i am now defining each group of images as a separate class member int[] and i will probably use a switch case to plug the correct one into the gridview. its ugly, but i currently only have 11 different groups and no more than 16 images per group so it will work for now until i can study the resource object more and figure out a way to get counts of associated image resources based on a part of the resource name, like with a regular expression or something, because thats the next problem i will have to deal with if i am not pre-defining all of these arrays.
if you know of a way to do that that would be awesome but ill will probably look into it more myself once i get this app closed up and can go back and fix stuff. im pressed for time right now.
thanks
It's really bad thing to use getIdentifier() method, we should always use R class. I think your problem resides somewhere before, you try to do something, that you shouldn't
How do you get these strings? You mentioned they are from user, but he doesn't write them by hand, right? If this is some selectable list, etc., they should be ints, enums, or some objects from the beginning. Not strings. Parsing strings is always ugly.
Ahh and if you have group of many small images, it is usually better to concatenate them into one big image - it's more efficient and you don't have to use 200 R constants in your code.
the string comes from the tag associated with a clickable imageView selected from the previous screen - a menu item if you will. the string will serve several purposes, retrieving related data, etc, but the first thing i needed to work out was retrieving the correct images and displaying them. i dont know how i could concatenate the images into one big image because each one needs to be clickable itself and handle certain events associated with itself.
i will go ahead and admit this is my first app so im basically figuring stuff out as i go. and learning most of my oop from flash has probably handicapped me
i appreciate your help dude
Brut.all said:
it's more efficient and you don't have to use 200 R constants in your code.
Click to expand...
Click to collapse
the only other thing i could think of trying was creating an xml doc to group the associated resource names together and figure out how to read from that to know which images to set
i dont see any methods in the R class i could use for sorting, grouping and then retrieving certain resources based on user interaction
switch cant eval string types...!?
kadmos said:
switch cant eval string types...!?
Click to expand...
Click to collapse
Nope
As I said, strings aren't good for identifying things - regardless of the language used. This is why people created int constants and/or enums.
And no, I doubt there are some mechanisms of grouping resources, etc. It must be simple, you are trying to complicate everything
I have a strong feeling that you should change your app architecture and get rid of strings. But here quick general fix (not a good solution! but just works).
Map your strings to R ints:
Code:
Map<String, Integer> map = new HashMap<String, Integer>();
map.put("button_normal", R.drawable.button_normal);
map.put("button_pressed", R.drawable.button_pressed);
// etc
Accessing will be done:
Code:
map.get("button_" + state); // Return int id, use as you need.
This is a bad practice, but it will work. Consider re-archirecturing your app.
@Brut.all: do you have any plans on updating apktool with 2.2 support?
@kadmos
Full example:
Code:
public static enum Planet {
MERCURY(R.string.planet_mercury, R.drawable.planet_mercury),
VENUS(R.string.planet_venus, R.drawable.planet_venus),
EARTH(R.string.planet_earth, R.drawable.planet_earth),
MARS(R.string.planet_mars, R.drawable.planet_mars);
public final int nameResId;
public final int imageResId;
public static Planet findByNameResId(int nameResId) {
for (Planet p : values()) {
if (p.nameResId == nameResId) {
return p;
}
}
return null;
}
private Planet(int nameResId, int imageResId) {
this.nameResId = nameResId;
this.imageResId = imageResId;
}
}
You have enum of planets, each of them has its name and image. Then you could do something like:
Code:
@Override
public boolean onCreateOptionsMenu(Menu menu) {
for (Planet planet : Planet.values()) {
menu.add(0, planet.nameResId, 0, planet.nameResId);
}
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
Planet planet = Planet.findByNameResId(item.getItemId());
doSomethingWithPlanetImage(planet.imageResId);
return true;
}
You identifies planets by ints (nameResId in this example - of course it must be unique), not by strings. Operations on ints are several times faster, than on strings, this is why Google decided to identify all things: resources, menu items, etc. just by ints.
Ahh and no, writing switch-cases to do something depending on given object isn't true OOP. OOP is above: enums know, which drawable is connected to them, there is no need for switches.
AuxLV said:
@Brut.all: do you have any plans on updating apktool with 2.2 support?
Click to expand...
Click to collapse
Yeah, of course, I want to work on apktool this weekend. Unfortunately baksmali doesn't support Froyo yet, so I can't support it fully neither.
@Brut.all:
Ha, I recognise that example It's from the Java Trail/tutorial on enums isn't it? Except they used gravity rather than drawable references.
@kadmos:
Are all the images known from the beginning? In other words, is the user creating them at runtime or are you including them with your app? If they are included with your APK then normally, as Brut said, you should be able to use the identifiers directly.
Concatenating the images all into one isn't hard to do, as you can still draw the specific bitmaps out using the Bitmap.create(bitmapToGetAPartOutOf, ....) method. You can then make those individual bitmaps into ImageViews and only have to remember the 'grid reference' for where they came out of the big image. That said, you'd have to balance the added complexity of creating the big images against the ease of not having loads of R constants. I can't really say anymore because I'm not fully following what you're trying to achieve.
Steven__ said:
@Brut.all:
Ha, I recognise that example It's from the Java Trail/tutorial on enums isn't it? Except they used gravity rather than drawable references.
Click to expand...
Click to collapse
I took planets example, because it's good, but everything was written from scratch
Steven__ said:
Concatenating the images (...)
Click to expand...
Click to collapse
I'm pretty sure I saw this concatenating approach somewhere in official Android's guidelines for performance, but now I can't find it :-/ Also I don't have much experience in Android development, so if no one else suggest this approach, then I think kadmos could forget about it.
Brut.all said:
You identifies planets by ints (nameResId in this example - of course it must be unique), not by strings. Operations on ints are several times faster, than on strings, this is why Google decided to identify all things: resources, menu items, etc. just by ints.
Ahh and no, writing switch-cases to do something depending on given object isn't true OOP. OOP is above: enums know, which drawable is connected to them, there is no need for switches.
Click to expand...
Click to collapse
i know its not true oop i didnt want to have to do that but i have not yet seen a way to pass any value from a selected item into a method that could use that value to retrieve x amount of associated resources (images in this case).
Steven__ said:
Are all the images known from the beginning? In other words, is the user creating them at runtime or are you including them with your app? If they are included with your APK then normally, as Brut said, you should be able to use the identifiers directly.
...I can't really say anymore because I'm not fully following what you're trying to achieve.
Click to expand...
Click to collapse
using the planets example, say i had x (varying) amount of pics of each planet's surface in my drawables and wanted only those planet's pics to display in a grid view when a user selects whichever planet. thats really all this is. being new to this i just dont know the most efficient way to do it. if this was Flash i could just group all the images file names/paths in an external xml doc and use that to load them from whatever folder at runtime - i wouldnt need any of those 200 or so images declared as anything or even as assets in my library (and i would only need the xml because flash cant access a file system on its own to see and filter files that it would or wouldnt need based on, say, a string comparison - though there is third party software like Zinc that gives Flash that capability.)
so i did get this to work by passing a number as a tag (string) in a bundle though an imageView click event and then casting the string as an int to use in the switch - which as of now leads to one of 11 different int arrays of resources names (images) ive got declared in my ImageAdapter class to populate my gridView.
the way i wished i could made this work would have been to use a string (like a planet name) ,passed from whatever planet image/menu item/whatever was clicked, and use that string to compare and determine which and how many images in drawables were associated with that planet and then use that to create my gridView at runtime.
kadmos said:
so i did get this to work by passing a number as a tag (string) in a bundle though an imageView click event and then casting the string as an int to use in the switch - which as of now leads to one of 11 different int arrays of resources names (images) ive got declared in my ImageAdapter class to populate my gridView.
Click to expand...
Click to collapse
I see what you're saying, that makes sense. Just as a quick note though, if you're declaring your ImageViews programmatically, you don't have to use a string object for the tag. You can directly give the integer and then cast it back when you get the tag. Just remember to use (Integer) as the tag is actually just an unspecified object.
kadmos said:
the way i wished i could made this work would have been to use a string (like a planet name) ,passed from whatever planet image/menu item/whatever was clicked, and use that string to compare and determine which and how many images in drawables were associated with that planet and then use that to create my gridView at runtime.
Click to expand...
Click to collapse
Yes, I can see why you'd want to do it this way. Your current problem is that if you add more images, you have to manually update your arrays. Unfortunately I can't think of a better, 'clean' way of doing it.
@kadmos
Now I have problems understanding you ;-) But if you don't want to declare all images in sources, but in XMLs, then you could use XML arrays.
Code:
<resources>
<string-array name="planet_names">
<item>mercury</item>
<item>venus</item>
<item>earth</item>
<item>mars</item>
</string-array>
<integer-array name="planet_images">
<item>@array/mercury_images</item>
<item>@array/venus_images</item>
<item>@array/earth_images</item>
<item>@array/mars_images</item>
</integer-array>
<integer-array name="mercury_images">
<item>@drawable/mercury_0</item>
<item>@drawable/mercury_1</item>
<item>@drawable/mercury_2</item>
</integer-array>
<integer-array name="venus_images">
<item>@drawable/venus_0</item>
<item>@drawable/venus_1</item>
<item>@drawable/venus_2</item>
</integer-array>
<integer-array name="earth_images">
<item>@drawable/earth_0</item>
<item>@drawable/earth_1</item>
<item>@drawable/earth_2</item>
</integer-array>
<integer-array name="mars_images">
<item>@drawable/mars_0</item>
<item>@drawable/mars_1</item>
<item>@drawable/mars_2</item>
</integer-array>
</resources>
When user will open planet selector, you will iterate through contents of R.array.planet_names array, each item (planet) in this selector will have itemId set to array index. When user will click on something, you will get itemId of clicked item, then you will find array of its images as R.array.planet_images[itemId] (not exactly - it's conceptual example).
You will be able to add new images or even planets through XML editing.
Steven__ said:
Yes, I can see why you'd want to do it this way. Your current problem is that if you add more images, you have to manually update your arrays. Unfortunately I can't think of a better, 'clean' way of doing it.
Click to expand...
Click to collapse
Brut.all said:
But if you don't want to declare all images in sources, but in XMLs, then you could use XML arrays...
...You will be able to add new images or even planets through XML editing.
Click to expand...
Click to collapse
as i posted earlier this was the idea that i had - i havent tried it yet because i wanted to get some feedback from you guys just to see if i was completely off base. so right now its coming down to what would make for the more memory efficient final product - declaring all these images as class array constants (which i already have working) or using xml and coding the operations for parsing, counting, filtering, assigning, etc?
again thank you guys for your time and help
kadmos said:
or using xml and coding the operations for parsing, counting, filtering, assigning, etc?
Click to expand...
Click to collapse
Do you mean parsing XMLs? My example above uses standard Android resources. You don't have to parse these XMLs, you will get them as arrays And yes, it's super efficient, because they are compiled to easy-to-read form
ok then im going to go ahead and try it
be back soon
i hope
Hello XDA, I'm trying to write (what I believe to be) a simple app; a calculator with storage buttons. I've gotten the basic layout and initialized the core components. Yet, when I add on-click listeners, there's a force quit when testing. Attached is the Java class and xml. I've tried very hard to figure out what it is; I've even tried simply putting a println statement in the on-click listener. It doesn't even do THAT
Also, if there's anything (AT ALL) that you could criticize me on in terms of code organization, standards, etc. PLEASE let me know. I'm a newbie, and it's better to kick bad coding habits before they grow strong!
Thanks in advance, guys. I know it's annoying to debug others code, especially beginners, but I don't think it'll take much time at all, and I'd like to think I'm a relatively organized beginner
So I found out what it was; EditText doesn't accept ints or doubles as parameters. There's got to be an easier way of doing this, though. Is there any calculator-window-type objects that will store ints and/or (preferrably or) doubles? It's doable, but highly annoying to cast everything to a string and then parse it back to a numerical data type to perform operations on it.
I'm developing an organizer app as my bc. thesis and I don't have any real Android developer to consult, so I made this thread and hope somebody will help me and point me in the right direction.
I just started to work on it and I have roughly 1 month to make something useable out of it.
So... the first thing that comes to my mind right now is synchronization.
1. I don't know if I should implement it or not.
I have a hosting with 1.5 GB space, a relatively fast connection. Would syncing data (text (probably xml) only) with this server slow it down significantly ? How many users could an average server take ?
And another one regarding sync:
2. I'd like my application to exchange data with my server under the google account on which the device is logged in, so no registration will be neccessary (I suppose the majority of devices are loggen in with google). I'll probably need to get the user's google account name on every sync session. Is that possible ?
The app will already have a server-side app to edit your events and stuff, so I'll need the user's login information again to retrieve his data from my database, but I won't have his password, so I can't make a usual login form. I guess Google has some API to figure out if a user is logged in, doesn't it ?
Any advice will be appreciated.
Can I open a menu with a simple button click ? Like a context menu but for short clicks.
// I solved the **** outta this one.
Still waiting for answers on the first post.
"Organizer App" really doesn't tell us what you're trying to do. It's hard to answer questions if one doesn't know that basic plan of the project you're trying to create.
Check this -> Basic info about my bc thesis
Nice web page...ambitious project for a 4 week time frame.
As a programmer, you know to start small and add functionality as your program grows.
I would start by making a simple"To Do" list: Add item, Delete item, Edit item, Mark item done, Save this list, Recall a list, Delete a list.
Post back when that's done
Rootstonian said:
Nice web page...ambitious project for a 4 week time frame.
As a programmer, you know to start small and add functionality as your program grows.
I would start by making a simple"To Do" list: Add item, Delete item, Edit item, Mark item done, Save this list, Recall a list, Delete a list.
Post back when that's done
Click to expand...
Click to collapse
Agreed 100%.
@ OP:
I don't know much about syncing, but it won't have a large cost of the server's resources - syncing an CSV or XML file is pretty trivial. Even if you have a low bandwidth cap, text files are quite small. So you should be fine in terms of that.
Nobody can give you a "set number" - ie. the server can take "X people." It greatly depends on the server type, how much bandwidth is allocated to you, your traffic priority, etc. I mean if it's one server with like a xeon processor then it can probably handled a pretty heavy load (say 50 probably? (and yes, I'm kind of pulling that number out of my ass)). Though most web hosts don't just dedicate one server to each customer. Typically, now-a-days, everything is virtualized. Everything is unified using server farms (ie. multiple servers or computers) virtually, then virtual chunks of resources are distributed to clients. So even if somebody could give you exact numbers (which is impossible), they'd most likely be wrong. That is unless you paid extra to have a particular server or particular number of servers dedicated to you...but even then, there's a high chance that it's just a chunk of a virtual server farm.
He's right, this is pretty ambitious in a 4 week period, especially if you have other activities going on as well. It's even more ambitious if this is your first app. You may want to reconsider your objectives given your time frame.
As for the google login, you'd need to look at the google API, and see if there's a way to verify peoples' usernames and passwords. If you can, then it's just a matter of encrypting them and storing them in a properties file or something.
Hope that helps ya out some.
Rootstonian said:
Nice web page
Click to expand...
Click to collapse
Thank you
I know, I know. I could have started 4 months ago. But I didn't, the lazy bastard I am.
This is the practical part of my bc thesis. The ultimate deadline is 3rd of june, but I have to have my theoretical part (30-50 pages of text, if IIRC) done by then, all printed out and ****. So I plan to work as hard as I can on this till the end of this month and then start to work on both at the same time. I really don't have any other duties in school, since I have a nice reserve of credits so this is my priority #1.
The main objective is geo-tasks, since that's what the name of my thesis says. Everything else is just an addition (i.e. the widget, that was just an idea, I doubt I will have time for that). So I'd rather start with that (I know, It's the hardest part). Or do you still think I should start with the to-do's ?
You can check out my last night's post to see what I've been up to the last 2 days and what I'll be up to next.
What is your level of Android programming experience (None, Basic, Intermediate, Advanced)?
And I'm a little fuzzy on the whole "Geo" thing. Is it like I have a list "Get milk, bread eggs", "Pick-up dry cleaning", "Get oil change" and then your app is going to "sense" when I'm by the grocery, dry cleaner's and oil change place? Which grocery? I use 4 different stores. Same dry cleaner and oil change though usually.
If so, you are going to need to code in lat/long coordinates for these places and then compute your location vs one of the merchants, compare that merchant to an "active" TO DO list item and pop-up an alert of some sort if you're within a mile. Wow
Your project, you know your skill level. Start where you want I guess LOL.
I think it's more of an agenda type thing - that syncs.
@Rootstonian
I'd say basic, but quickly crawling up to intermediate.
It's almost like you said, but there's only one location for every task. Maybe in a later version...
Well, good luck. Keep us posted
Will do. Hope you guys will keep on helping me
I need to use my database object in more than one activity. How do I pass it from one activity to another ?
Should I create a new instance in each activity ? Or should I create a content provider ? (I'd rather not - they're quite complicated for me and I only need to access the DB in this app).
I'm going to assume you are using a database helper type class.
No need to pass data from Activity to Activity; just open, use and close the database in each Activity as required.
I have a problem.
I created a LinearLayout for all the tasks in the database. Now I want to register all of them for a context menu. I can do that, but I can't figure out which one's menu was triggered.
LinearLayout has a setId method, but it only takes integer values, which is no good for me, because I have 3 types of tasks and if I assign them their id from the database, then the same ID will probably be assigned to 3 different views.
I could use some sort of multiplication, like for timed tasks I would multiply the ID by 10 000, but that's not elegant at all, and it would crash after a few months of using the app.
So what do I do now ?
I'll paste some code.
Code:
public void drawTasks() {
TextView emptyText = (TextView) findViewById(R.id.empty_todo);
if (tasks.isEmpty()) {
emptyText.setVisibility(View.VISIBLE);
} else {
emptyText.setVisibility(View.GONE);
Iterator<Task> it = tasks.iterator();
//create views
while (it.hasNext()) {
//create a temporary object
Task tmpTask = it.next();
//get it's properties
long id = tmpTask.getId();
String title = tmpTask.getTitle();
String description = tmpTask.getDescription();
int important = tmpTask.getImportant();
int finished = tmpTask.getFinished();
//create new LinearLayout for this task
LinearLayout newTaskLayout = new LinearLayout(this);
newTaskLayout.setId((int)id);
newTaskLayout.setOrientation(LinearLayout.VERTICAL);
newTaskLayout.setPadding(5, 0, 0, 10);
taskLayouts.add(newTaskLayout);
//create new views for these properties :
//title
TextView newTaskTitle = new TextView(this);
newTaskTitle.setText(title);
newTaskTitle.setTypeface(null, Typeface.BOLD);
//important tasks are highlighted
if (important == 1)
newTaskTitle.setTextColor(Color.RED);
//finished tasks are italic
if (finished == 1)
newTaskTitle.setTypeface(null, Typeface.ITALIC);
//description
TextView newTaskDescription = new TextView(this);
newTaskDescription.setText(description);
if (finished == 1)
newTaskDescription.setTypeface(null, Typeface.ITALIC);
//add views to this tasks' LinearLayout
newTaskLayout.addView(newTaskTitle);
newTaskLayout.addView(newTaskDescription);
//add new linearLayout to tasksRootLayout
tasksRootLayout.addView(newTaskLayout);
}
}
}
This is self-explanatory. taskLayouts is an ArrayList of LinearLayouts where I keep the pointers to all layouts that need to have a context menu.
There are 2 other similar methods: drawTimedTasks() and drawGeoTasks() which do basically the same (I couldn't figure out a way to do it with one universal function).
Here's how I register them for context menu:
Code:
private void registerViewsForContextMenu() {
//register control bar buttons
registerForContextMenu(newGeoTaskButton);
registerForContextMenu(newTaskButton);
Iterator<LinearLayout> it = taskLayouts.iterator();
while (it.hasNext()) {
registerForContextMenu(it.next());
}
}
And here's how I'm checking for context menu trigger:
Code:
public boolean onContextItemSelected(MenuItem item) {
switch (item.getItemId()) {
case ...
return true;
}
...
}
return false;
}
What am I doing wrong ?
Anyone ?
----
I haven't really been following this thread so I don't know all the details of your app, but I'll try to help.
So each task has 3 views for it? Each task is in the db once? I'm a little foggy on how you're storing them and what the correlations are between views, events, and types of event, more specifically the latter.
If you explain that a little more clear, I can try to help a little better.
There are 3 types of tasks : simple, timed, and geo tasks. Each type has its own table in the db, hence it's own IDs. That means, the first geo task, first simple task, and the first timed task ever added have all the same ID = 1. That means if I want to give their views unique IDs, I can't use their IDs from the database.
So I'm trying to figure out a way how to give the view ID's so I can find out which database record they represent.
In an ideal world, I would be able to define a string ID (i.e. geo_1, simple_1, timed_1), but this is not the case. I dunno why... in XML you give your views string IDs, but programatically you can't.
grandioso said:
There are 3 types of tasks : simple, timed, and geo tasks. Each type has its own table in the db, hence it's own IDs. That means, the first geo task, first simple task, and the first timed task ever added have all the same ID = 1. That means if I want to give their views unique IDs, I can't use their IDs from the database.
So I'm trying to figure out a way how to give the view ID's so I can find out which database record they represent.
In an ideal world, I would be able to define a string ID (i.e. geo_1, simple_1, timed_1), but this is not the case. I dunno why... in XML you give your views string IDs, but programatically you can't.
Click to expand...
Click to collapse
If all of the tasks have common elements (even if they don't really), you can merge them into one table. Then define an enum or something for the task type, as a simple field in the table. This removes the issue with duplicate ID's, while still being able to differentiate what type they are. You can typically leave fields blank in a database, so you wouldn't have to worry about what's filled in for tasks that don't have particular fields associated with them, just verify all fields prior to mutating the database.
If you're hellbent on keeping three separate tables you can hold a global ID, which can be an intersection between all three tables. So this wouldn't be the primary key, just a global ID, and you can key them up by that. Not entirely sure where you'd keep it to persist over power cycles unless you just make a 4th table with one row and store it in there. Or just throw it in the program's data somewhere.
The reason you can define things in the XML is he XML is compiled into the R class at compile time...though everything in there *should* have a corresponding methodology to get it done programatically. Though if you're talking about the primary key, as far as I know that is always numerical. So the ideal world may not apply - BUT, that doesn't mean you can't create a field that stores a string id (which I wouldn't, because string comparisons take a lot of time, but whatevs).
Hope that helps you out some, I don't really touch databases and am very new to Android programming, just know what I know from absorbing info from others - but I know a pretty decent amount about programming in general and know Java pretty well so I can probably help you out the best I can in some respects.
Hello, XDA!
I have created my own 2D game engine that utilizes OpenGL and sports many features to help make programming 2D games for Android as quick and simple as possible. I created this engine for use in my own projects but then I thought why no make it open-source? I think other people could benefit from this and input from other developers could help fine tune this thing so it's as good as it can be.
So I gave my engine the name "BobEngine" after my online alias and uploaded the first public release called "BobEngine 1.0 Thingama" to GitHub. That was months ago and now I've finished working on the next update: BobEngine 2.0 Shishka.
I've got a post on my website detailing what's new in update: http://www.bobbyloujo.com/2015/01/bobengine-20-shishka-update.html
BobEngine uses a similar structure to GameMaker games so if you've ever used that you may be interested in BobEngine. BobEngine uses a specialized BobView to display the content of Rooms. Rooms are collections of GameObjects which each have a graphic and attributes such as x and y positions, width, height, angle, frame, etc... Rooms and GameObjects also have step, newpress, and released events built in. The step event happens each frame, the newpress event happens when a new pointer is touched on the screen, and the released event happens when a pointer is lifted from the screen.
There are many other tools included with BobEngine and the best way to start learning how to use them is have a look at the examples that are included! In the GitHub repository you'll find an Android Studio project called "BobEngine". This project contains the "bobEngine" library module that you'll need to include in your own projects if you want to use BobEngine. Also in the BobEngine project are modules for each of the included examples. Currently there are examples that demonstrate the structure of a BobEngine game, how to use input from the touch screen, and how to manipulate the camera. I'll be creating more examples in the future to show off all the things you can do with this engine!
All the methods and data members in BobEngine are internally documented and the examples include a lot of internal documentation to help you out as well.
I'll keep updating the library with new things as I think of them. If there is anything you think should be added go ahead and post about it in this thread.
Benjamin Blaszczak
a.k.a. Bobby Lou Jo
@Bobbyloujo on Twitter
Edit: Forgot the GitHub link: https://github.com/Bobbyloujo/BobEngine
@Bobbyloujo
Thanks man will try this today and welcome 2 xda :highfive:
Thanks sir...pls give us some game template made from your lib
Great job man. It looks great.
I will try as soon as possible
Sylvain
Thanks man. Will surely try it out. good work.
Awesome, just what I've been looking for. Thanks!
nice work, and thanks for putting your time and effort into it.
Could this be used to recreate "biomenace" for android?
Thanks everyone!
@berlyshells Anything you want to see in particular? I could probably throw together a Flappy Bird clone real quick or something...
@verbuyst It certainly looks doable if you put the time and effort into it.
Bobbyloujo said:
..
Click to expand...
Click to collapse
im not really looking for anything in particular..probably any game source with comments (of the functions/what for is this code etc..) inside the code would be nice haha i just requesting but its you're choice sir im sorry im just a newbie
TIA
A new example has been added to the repository per @berlyshells request. This example is called Jumpy Bug and it is a Flappy Bird clone. It demonstrates what a full game programmed with BobEngine looks like.
Bobbyloujo said:
....
Click to expand...
Click to collapse
thank you very much sir..you are indeed a good hearted person..this is what i really love on xda
While working on my most recent project I made a few changes to BobEngine. The changes have been uploaded to GitHub.
Changes:
The extra functionality provided by BobActivity has been moved to a new class - BobHelper. A BobHelper can be used by any activity. When using a BobHelper, be sure to call its onResume() method from your activity's onResume() method. BobActivity still functions the same way it did before. BobHelper is useful for when you want to use some other kind of activity has your application's main activity but still want the extra functions from BobActivity. For example, if you want to use BaseGameActivity from the BaseGameUtils library for Google Play services.
SplashActivity has been totally changed because, frankly, it sucked before It is now an abstract class. Create your own activity for showing splash screens and extend SplashActivity. Implement the setup() and end() methods. In the setup() method, call addSplash(R.layout.your_splash_layout, time_in_ms) to add a splash screen to show as defined by an xml layout. You can add up to 10 layouts. Add them in the order you want them to show. The end() method is called after the last splash screen has been shown. In the end() method, start an intent for your main activity and then call finish() to close the splash screen activity.
Other small changes.
How many games have made using library? Looks cool)
Thanks..I tried AndEngine and it failed to import on my Android Studio.
Marshal3 said:
How many games have made using library? Looks cool)
Click to expand...
Click to collapse
Uhm... about three. There's Plane Popper, Crazy Taxi Driver, and I just finished Bounce the Beach Ball. Other than that, I've made a few examples that you can find in the repository - including a Flappy Bird clone. Also, I've been working on a platformer.
basil2style said:
Thanks..I tried AndEngine and it failed to import on my Android Studio.
Click to expand...
Click to collapse
Let me know if you need any help with BobEngine!
Hello again, XDA!
I've updated BobEngine again. This update brings the following major additions:
Gamepad support! You can now get input from any standard gamepad using BobEngine. A new example has been added to the Android Studio project that shows and explains how to use this new gamepad support. The example is called controllerexample.
Multiple quads per GameObject. Up until now, a GameObject consisted of a single textured quad (well, two triangles that form a quad). Sometimes it is useful to have many quads grouped together. If you use this, note that all the quads for each GameObject must have the same graphic. This is a very niche feature that I added for a particular purpose but didn't end up using myself. If you'd like an example of what can be done with this, let me know and I'll make one.
Some other miscellaneous stuff has been changed as well. It's been so long since I posted an update that I forget everything I changed! One useful change I made was to the camera features. Rooms now have their own camera values, meaning if you change the camera in one room, then switch to another and change the camera there, then switch back to the first room the camera will be where you left it in the first room.
BobEngine can of course still be found here on GitHub: https://github.com/Bobbyloujo/BobEngine
Here's a video showing off gamepad support: https://youtu.be/vRdaaaJnqGk
As always, if you have any questions feel free to ask. Also, if you've made anything with BobEngine I would love to see it! Whether it's something big or something small I'd love to see how others have used my engine
If you haven't already, please follow me on Twitter. My handle is @Bobbyloujo and I post updates about the games and things I'm working on there pretty frequently. Right now I'm working on something pretty big!
Another new update today!
Changes:
* TextDisplay object added! TextDisplay is a GameObject that can be used to output text! Text can be centered, aligned left or right. A new example has been added to show how this new object can be used.
* A new 'visible' attribute has been added to GameObjects. Setting gameObject.visible to false will cause the object to be hidden so it isn't drawn.
* The getAngle() function in Room.java was broken. It has been fixed so now getAngle() and getAngleBetween() both work properly.
* The getRatioX() and getRatioY() functions sometimes would not work properly on some devices. This has been fixed.
* When using multiple quads per GameObject, the performance has been increased. This was done by collecting vertex data from the quads in a way that does not require the concatenation of many arrays.
As always, the repository can be found here: https://github.com/Bobbyloujo/BobEngine
It'll really help me out if you follow me on Twitter: https://twitter.com/Bobbyloujo
And like my Facebook page: https://www.facebook.com/BobbyLouJo
If you have any questions or would like to report a bug, please leave a message in this thread or PM me on XDA, Twitter, or Facebook.
Have a great week!!
Version 3.0 Bobsled
It's been a while, but in the time since my last update I've added a lot of new things to BobEngine. Since it's such a big update, I'm giving it a new version name: v3.0 Bobsled. Here goes:
RoomCache - In BobView.java you will find a new static class called RoomCache. As the name implies, RoomCache is used for storing and retrieving instances of Rooms. The nice thing about RoomCache is that you can call getRoom(Class roomType) with any class type that inherits Room and the function will return an instance of that room type, even if you haven't manually added a Room of that type to the cache. The function getRoom(...) will search the cache for an instance of roomType and return it if one is found OR it will create a new instance of roomType using reflection and return that. You'll also notice that there is a getRoom(Class roomType, Object... args) function. If you have created a room type that takes parameters other than (BobView view) like a default Room does, you can use this method to pass the required arguments to initialize a new instance of that room type if need be. The cache holds a specified max number of Rooms. When the cache is full and a new Room is added, the oldest Room is removed. You can make your own RoomCaches, but each BobView has it's own cache with an initial size of 3. To access it from your BobView, just call getRoomCache().
Along with RoomCache, BobView has received two new goToRoom overrides: goToRoom(Class roomType) and goToRoom(Class roomType, Object... args) for switching to rooms retrieved from the RoomCache.
Input events (newpress, released) are now handled on the main thread (same thread as step event). Handling game logic on the separate input thread was causing a lot strange glitches in my games when values were being changed when I was not expecting them to be changed. Now, input will be handled on the same thread just before the step event.
For even more convenience and even quicker game development, a new constructor has been added to GameObject: GameObject(Room room). This will automatically assign an instance ID number AND add the object to the room. What typically looked like this before:
Code:
GameObject object = new GameObject(room.nextInstance(), room);
room.addObject(object);
Now looks like this:
Code:
GameObject object = new GameObject(room);
So simple! The old constructor is still there and behaves the same way for those who want it and for backwards compatibility.
Setting GameObject.visible to false will now hide all Quads belonging to that GameObject. This will not change the Quad.visible field for any Quad. Also, similarly to GameObject, Quads are now added to the GameObject when initialized.
Animations can now be played once and looped for a limited number of times. animationFinished() will return true when an animation has finished playing.
Animation class - a new class has been added to GameObject.java. This class can be used to predefine animations with a start frame, end frame, fps, and loop times.
Previously, I was using 3 coordinates for each vertex. I learned it's possible to use only 2 in OpenGL. Since the 3rd vertex is not needed, I changed the code to use only 2 vertices. I'm not sure if this actually caused any performance improvement.
Graphic.Parameters class - A new class in Graphic.java allows you to predefine Graphic parameters to use with GameObject.setGraphic(Graphic.Parameters params). Useful for when you want to switch between graphics on a GameObject often.
A new method in the Graphic class called setDimensions(int width, int height) allows you to set the height and width of the DPI level image you want to use for setGraphic(Graphic g, int x, int y...). Previously, you would have to use setPreciseGraphic(...) if you had different sized images for different DPI levels that have multiple graphics on them.
Set the color intensity of all GameObjects on a specific layer using Room.setLayerColor(int layer, float r, float g, float b, float a).
Graphics management (this is a big one):
The Room, Graphic, and GraphicsHelper classes have been updated to improve and simplify management of graphics for large games. A new GraphicsHelper.cleanUp() method makes it easy to manage graphics. You can choose points in your game to call cleanUp(). When called, Graphics that have not been used recently will be unloaded and removed from the GraphicsHelper. Graphics have a new public field called 'persistent' which when set to true will cause the graphic to remain loaded when cleanUp() is called. All non-persistent Graphics will survive through a set number of cleanUp() calls before they are removed. If a Graphic is removed but then a GameObject tries to use it again, it will automatically be re-added to the GraphicsHelper and reloaded.
You can also manually call:
Graphic.load() to load a graphic after is has been added to the GraphicsHelper.
Graphic.unload() to unload a graphic
Graphic.remove() OR GraphicsHelper.removeGraphic(Graphic g) to unload and remove a Graphic from the GraphicsHelper.
OKAY, I think that's just about everything. I actually had to look through the changes in the GitHub commit to remember all the things I've changed xD There are a few other small changes but I didn't think they were important enough to list. Now I want to ask you guys something:
Is there any interest in a full-blown tutorial series for BobEngine?
I could start with the basics, then explain more advanced features like graphics management. I could also take requests for certain tutorials. I could even cover general game development topics and how to implement them with BobEngine. Doing this would be a lot of work so before I dive in I really want to gauge the level of interest in BobEngine. So far, it's been difficult to tell how many people are interested because I haven't gotten an overwhelming amount of replies here but every once in a while I get a PM or email asking for help. So if you're using BobEngine raise your hand!
And of course: if you've made anything with BobEngine I would love to see it! I've seen a few things and it makes me happy to see you guys using getting some use out of my engine.
Thanks for your time! If you have any questions, just ask. You find any issues with BobEngine, post them here or on GitHub and will fix them. Also don't forget to let me know if you're using BobEngine!
Once again, the repo can be found here: https://github.com/Bobbyloujo/BobEngine
Thanks again,
Ben a.k.a. Bobby Lou Jo
Twitter: https://twitter.com/Bobbyloujo
Facebook: https://www.facebook.com/BobbyLouJo
you are great and i should more from you
I am a new man in the electronic area, and you have developed your own staff, you set a good example for me.
Jackiefire said:
I am a new man in the electronic area, and you have developed your own staff, you set a good example for me.
Click to expand...
Click to collapse
Thanks! Your support means a lot.