📜 ⬆️ ⬇️

Programming in Android - why is it so difficult?

Introduction

I am not a programmer for a long time, I am an admin. But sometimes it is necessary to quickly do a utility analysis of the logs, some automation - I do, if I do not find anything like it in the internet for the day of the search.

On android, my indignation immediately caused two facts - the lack of melodies in groups (why, why didn't anyone except Sonya think of this obviously necessary functionality?) And the inability to save melodies along with contacts. In Symbian, which was then the benchmark for smarts, the last function was.

The search gave nothing on the second point and almost nothing on the first. These were the harsh times of transition from Android 1.5 to Android 1.6 and somewhere on the horizon loomed Android 2.0.
')
Well, no and no - I will write, not the gods burn pots. I started with a simpler one, with melody tuned from a bakup.

As a result, the program was born, with the simplest function - to match the name-contact = set-call and then restore this data (you can find it in the market under the name Ringtone Keeper), but on what rake I stood in the process - I'll describe it here.

Android 1.6

I decided to write right under 1.6, because Google itself strongly advised with 1.5 not to bother. Well there is no way. With the online documentation, Golyak, the same example with the same comments wanders from site to site. Google itself on developer.android.com has no examples and very ascetic descriptions of fields and functions. The main resource is stackoverflow.com/questions , where it is possible to see logic in the answers to the questions. I read a couple of books for teapots and went. The program is born, the rake climb.

Well, for example: all the sound data lies in the android in the MediaStore. But they lie there in the form of an index table and extract the file names from it (and I just need the file names, after reinstalling the system with a high probability, the same files will have other indexes in the MediaStore) rather nontrivially.

Approximately the same song with contacts. But at least there were examples with them, but the whole war with sound had to be grope by trial and error.

The installation of a call to a contact is even more original. Again, you need to convert the file name - the index in the MediaStore. But this is not enough! If you assign this index to a melody to a contact, the melody of the contact will be removed and that's it. The file that is in the MediaStore must nevertheless be registered in it (with withAppendedId method) and only the Uri received during registration can be pushed into a contact.

That's why it is so difficult, I ask? Or did I not find something?

Android 2.0

The program worked, but then it was time to upgrade to android 2.0. And google has everything as usual. He changed the SDK to work with contacts, and at the same time, so as not to get up two times - he saved the old SDK, but put it into read-only mode. That is, the mode of reading contact data is working and old.
Two code examples:

SDK 1.6
String[] selectCols = { People._ID, People.NAME, People.CUSTOM_RINGTONE }; if ((ContactName == null) || (ContactName.length() < 1)) { return DATA_NOT_FOUND; } //     ContentResolver localContentResolver = this.getContentResolver(); Cursor cur = localContentResolver.query( Uri.withAppendedPath(People.CONTENT_FILTER_URI, Uri.encode(ContactName)), selectCols, null, null, null); if (cur.moveToFirst()) { int cID = cur.getInt(cur.getColumnIndex(People._ID)); return cID; } return DATA_NOT_FOUND; 


SDK 2.0
 tring[] selectCols = { ContactsContract.Contacts._ID, ContactsContract.Contacts.DISPLAY_NAME, ContactsContract.Contacts.CUSTOM_RINGTONE }; if ((ContactName == null) || (ContactName.length() < 1)) { return DATA_NOT_FOUND; } //     ContentResolver localContentResolver = this.getContentResolver(); Cursor cur = localContentResolver.query( Uri.withAppendedPath(ContactsContract.Contacts.CONTENT_FILTER_URI, Uri.encode(ContactName)), selectCols, null, null, null); if (cur.moveToFirst()) { int indID = cur.getColumnIndex(ContactsContract.Contacts._ID); return cur.getInt(indID); } return DATA_NOT_FOUND; } 


That is, you can simply change People to ContactsContract.Contacts and .NAME to .DISPLAY_NAME. You can not even change - the old way of reading works great for reading!

But with the recording of trouble.

Old SDK:
  Uri contactUri = ContentUris.withAppendedId(People.CONTENT_URI, cID); ContentValues value = new ContentValues(); value.put(People.Phones.TYPE, People.TYPE_MOBILE); value.put(People.NUMBER, "+7 (777) 777-77-77"); ContentResolver localContentResolver = this.getContentResolver(); int updRow = localContentResolver.update(contactUri, value, null, null); localContentResolver.notifyChange(People.CONTENT_URI, null); return ((updRow > 0)); 


This code is collected, started, running, not a single error - it only writes either to / dev / null, or to the old database, from which no one reads.

Here, replacing People with ContactsContract.Contacts is required, without this in any way.

Although it would seem, make synonyms and let the old code write to the real base according to the old rules. Well, or make a mistake for People, if the platform is higher than 1.6. They did neither. The question is - why such difficulties?

Market and people

At this approximately stage, I decided to put the program into the market (among my acquaintances, it went off with a bang, I thought, let it be). And at mass use the following rake got.

A contact search returns its name in the format specified by the system. If at your bakapu there was a display format of the contact “Last Name, First Name”, then the contact will be recorded as “Ivanov Vasya” (as DISPLAY_NAME returns). But after reinstalling the system, the format is “First Name, Last Name”. The user clicks Restore, the program honestly starts the contact search “Ivanov Vasya” - and does not find it, because the system believes that “Ivanov Vasya” and “Vasya Ivanov” are different people. How can I explain this to the system, I did not invent it and just made the parsing of contacts and their search into my program. The speed dropped dramatically, calls to 200 contacts are set at 20-30 seconds. It is clear that a program that hangs for 30 seconds is a bug. Need a sign with the sign "I work ..." and an indicator of activity. Glory to Google, it offers it! Then I learned a lot about parallelism in android, but in all this at least some logic can be traced, so I will keep silent. This is not a rake, this is a butcher, he sees it (c).

Next, users began to ask to make a save-restore call by default and the sound of SMS. And again the rake is the simplest obvious solution.
Settings.System.DEFAULT_RINGTONE_URI when an external (with sdcard) ringtone is set, returns the result of the form "/ system / audio / ringtone". At the same time, both MediaStore and RingtoneManager flatly refuse to guess what kind of file it is. I had to habitually climb through the anti-façade, use RingtoneManager.getActualDefaultRingtoneUri (this, RingtoneManager.TYPE_RINGTONE) and then convert it back to the file name.

And the same button accordion when installing a call or SMS - until you add it to the MediaStore, it is not installed on android 2 and 3. In android 4, this bug finally seems to be fixed, because everything works there without ContentUris.withAppendedId (MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, ringID).

Another frequent user question was the ability to choose a place where to put the backup and the file name of the backup file (this is now strictly set by the program). And then I discovered (fanfare, Win3.11 nervously rolls over in a coffin) that the android has NO standard file / directory selection dialog. Need - sit down yourself and write. At this point, I said “enough perversions” and began to respond to everyone that, due to the lack of availability, I was too lazy to write such a thing and let them use any file manager to transfer their backups to any place they want.

But why not, why?

Questions

As a result, the program was written, it works, but there are still questions - why is everything so complicated? Google android API writes several different competing teams? Why is the experience of previous systems not taken into account, why are obvious functions made autogenous through the anus or absent altogether?

Who invented all this and why?
Or is not everything so bad, but I just did not find the answers?

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


All Articles