📜 ⬆️ ⬇️

My experience of writing a program for Android



Hello!
In this article I would like to tell you about writing a program for the Android platform for sending animated messages. It will be more a small story of creation than a recess in programming.
It was about two months ago, I thought a lot about what you can write now, so that it will be in demand, the users like it and it is original. Considering how much the market is already cluttered up, it seemed to me difficult to even come up with an idea. There were already all sorts of system utilities, hundreds of animated wallpapers, programs for cameras, clients for social networks, games and even antiviruses (which are for some reason wildly popular!). Of course, the Chinese city is most of all there, which has become less noticeable with the advent of the new market.

The idea came quite suddenly and pushed me to her site livetyping.ru . “Why not?” I thought and began to think how it would look and how to write it. Who was too lazy to go to the site, I will explain that the point is that the user wrote the text, and then it was generated in the hyphae file, displaying the process of writing, including all the changes. It turns out quite funny, you can write a message with one meaning, then wipe everything and write with the opposite. In general, the user is limited only by his imagination.
Someone will say that the idea of ​​the program is not very ... because many Android phones do not know how to view animated gifs with built-in tools. And partly it will be right, as judging by the reviews on the Internet, many Androids do not have this support. But, as it turned out, my phone with firmware 2.3.3 can do this, which gave me hope that in the future manufacturers will add support to all devices. Maybe a little optimistic, but at the office. This Android should be able to decode the hyphae (although it is not said what).

Development


Core program

The first difficulty was that the generated text should be formatted in exactly the same way as the original. There were two options:
')
  1. Make a server to which to send all the text typed by the user, the size of the field, the size and color of the font, generate the hyphae and give back the link or the file itself.
  2. Generate everything on the client.

Immediately, the second option was chosen, since I am not friends with the web, I don’t need server costs.
In order to make the gif animation, it was necessary to first generate all the frames, and then collect them in a heap. Thinking that this operation would work faster on C, and not on Java, I rummaged through the internet and found the source code of the class I needed, which I successfully compiled using NDK. This class allowed to add a frame as an array of pixels obtained from an instance of the Bitmap class, generating an animated gif file at the end.
Just as it is written in the example at the link:

static { System.loadLibrary("gifflen"); } .... public native int Init(String gifName, int w, int h, int numColors, int quality, int frameDelay); public native void Close(); public native int AddFrame(int[] inArray); .... // Filename, width, height, colors, quality, frame delay if(Init("/sdcard/foo.gif", width, height, 256, 100, 4) != 0) { Log.e("gifflen", "Init failed"); } int[] pixels = new int[width*height]; // bitmap should be 32-bit ARGB, eg like the ones you get when decoding // a JPEG using BitmapFactory bitmap.getPixels(pixels, 0, width, 0, 0, width, height); // Convert to 256 colors and add to foo.gif AddFrame(pixels); Close(); 

The next task was to figure out how to render the typed text in a Bitmap. Rummaging through the Android API, the StaticLayout class was found, which allows you to draw this text using Paint in Canvas, which in turn in Bitmap. It all looks something like this:

 Canvas canvas = new Canvas(); TextPaint paint = new TextPaint(Paint.LINEAR_TEXT_FLAG | Paint.ANTI_ALIAS_FLAG); Bitmap bitmap; paint.setStyle(Paint.Style.FILL); paint.setColor(fontColor); paint.setTextSize((int) (fontSizeDP * mDensityScale + 0.5f)); paint.setAntiAlias(true); paint.setTypeface(font); paint.setTextAlign(Align.LEFT); StaticLayout[] layoutTexts = new StaticLayout[mLiveTypeStringArray.size()]; for(int i = 0; i < layoutTexts.length; i++) { layoutTexts[i] = new StaticLayout(mLiveTypeStringArray.get(i), paint, (int) (gifWidthDP * mDensityScale + 0.5f), Alignment.ALIGN_NORMAL, 1, 1, true); if(gifHeight < layoutTexts[i].getHeight()) gifHeight = layoutTexts[i].getHeight(); } if(gifHeight == 0) return 0; bitmap = Bitmap.createBitmap((int) (gifWidthDP * mDensityScale + 0.5f), gifHeight, Bitmap.Config.RGB_565); canvas.setBitmap(bitmap); for(int i = 0; i < layoutTexts.length; i++) { canvas.drawColor(backColor); layoutTexts[i].draw(canvas); gifEncoder.addFrame(bitmap); } 

Fine! The typed text, more precisely, each of its changes, was rendered to the Bitmaps from which the gif file was collected.
Then came the next problem. Gif files turned out huge! On average, hyphae up to 200 frames took 3-5 mb. This is a lot, especially if you want to send it from a mobile device. Then I noticed that these gifs take much less on livetyping (30-50 kb) and asked the author how he achieved this result. The answer was the Gifsicle library, which could very well and efficiently optimize gifs. A similar result was achieved due to not saving each hotel frame, but only the difference between them, which was ideally suited for us to save animated text.
Then I started porting Gifsicle to Android using NDK, which was soon successfully completed.
Who cares, here is my Android.mk:
 LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := malloc LOCAL_SRC_FILES := fmalloc.c dmalloc.c LOCAL_ARM_MODE := arm LOCAL_CFLAGS := -DFPM_ARM -ffast-math -O3 LOCAL_C_INCLUDES := $(LOCAL_PATH)/include include $(BUILD_STATIC_LIBRARY) include $(CLEAR_VARS) LOCAL_MODULE := gifwrite LOCAL_SRC_FILES := ungifwrt.c LOCAL_ARM_MODE := arm LOCAL_CFLAGS := -DFPM_ARM -ffast-math -O3 LOCAL_C_INCLUDES := $(LOCAL_PATH)/include include $(BUILD_STATIC_LIBRARY) include $(CLEAR_VARS) LOCAL_MODULE := gifopt LOCAL_SRC_FILES := clp.c giffunc.c gifread.c gifunopt.c \ merge.c optimize.c quantize.c support.c xform.c \ gifsicle.c LOCAL_ARM_MODE := arm LOCAL_CFLAGS := -DFPM_ARM -ffast-math -O3 LOCAL_C_INCLUDES := $(LOCAL_PATH)/include LOCAL_LDLIBS := -llog LOCAL_STATIC_LIBRARIES := gifwrite malloc include $(BUILD_SHARED_LIBRARY) 

What was my surprise when I saw that it was working incorrectly on a mobile device. Generating and optimizing the same file hyphae each time gave a different result. Very different, the spread was from 50kb to 2 mb. Then I started compiling again, recompiling with different parameters, looking for a memory leak, etc ... anything to explain this phenomenon. But I did not find anything. So two weeks have passed.
One fine morning, I realized that Gifsicle might not fail, because its author also could not understand what the problem was, but the first library (class) that generates the hyphae. I turned off the optimization and looked at the result: the files were almost always the same size, only sometimes differed by 1-2kb. Strange, but not deadly. Not wanting to poke around in someone else’s raw C code, I found a similar library in Java ME, and ported it to Android. I also noticed for myself the striking similarity of the Java ME and Android API - many almost identical functions (I hadn’t dealt with ME before). Now everything has become normal.

But again, not for long ... it turned out that after optimizing when playing a gif file on my Android device using the standard Image Viewer, sometimes there are horrible glitches of colors and loss of frames. At the same time on the computer the same file was viewed perfectly. I thought that this was all due to the poor support of the LZW compression viewer and disconnected it in the sifs of Gifsicle. Now everything really became good, although the files began to occupy a little more than before.

Interface

Up to this point I spent about a month. For the second month was to write the program interface. I always wanted to use some kind of Android UI pattern, I chose Dashboard from all possible. Since “everything is already written to us,” I downloaded the Google IO source and took the code from there. It turned out somewhere like this:


The window for writing a new message was:

You can view the written animated message or generate it in the hyphal animation, then the Share button appears with the ability to send by email, mms, twitter, etc.

The height of the field for typing was chosen so that the keyboard did not cover it on different screens. The smallest screens were banned, because there the keyboard takes well a lot of space. Of course, it would be possible to make the height depending on the size of the screen, but ... it became lazy.

Then settings were made based on the standard PreferenceActivity class:


And also a list of my posts.
On the memory card is saved only an array of texts (frames) in binary form. When viewing a message, it is possible to generate it anew, after changing the settings (font color and size, background color, animation speed).

Result


At first two versions were planned: free and paid. Now only free is implemented, which is in the market for about 20 days. In the paid plan, more fonts were planned, more font and background colors, more frame limits — 500 (now 140). But, unfortunately, the success of the free version leaves much to be desired: there are 583 installations in total, of which 227 are active, that is, more than half of the downloads have already been deleted. Apparently the idea is not rolled =)
Therefore, the development of the program is suspended and is unlikely to be continued.

That's all, thank you all for your attention! I will answer your questions in the comments. Also apologize for any errors.

Update: Several mini-reviews on foreign sites:
www.androidapplog.com/2011/09/android-app-reviews/animado-animated-messaging-app-review
www.addictivetips.com/mobile/animado-for-android-share-animated-text-messages-as-gif-files

Who cares here is a link to the market .

Source: https://habr.com/ru/post/130087/


All Articles