<?xml version="1.0" encoding="UTF-8" standalone="no"?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><rss xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd" version="2.0"><channel><title>Still good magic</title><description></description><managingEditor>noreply@blogger.com (Anonymous)</managingEditor><pubDate>Wed, 2 Oct 2024 23:16:23 +0900</pubDate><generator>Blogger http://www.blogger.com</generator><openSearch:totalResults xmlns:openSearch="http://a9.com/-/spec/opensearchrss/1.0/">6</openSearch:totalResults><openSearch:startIndex xmlns:openSearch="http://a9.com/-/spec/opensearchrss/1.0/">1</openSearch:startIndex><openSearch:itemsPerPage xmlns:openSearch="http://a9.com/-/spec/opensearchrss/1.0/">25</openSearch:itemsPerPage><link>http://sigidin.blogspot.com/</link><language>en-us</language><itunes:explicit>no</itunes:explicit><itunes:subtitle/><itunes:owner><itunes:email>noreply@blogger.com</itunes:email></itunes:owner><item><title>Edit Google Chrome thumbnail page</title><link>http://sigidin.blogspot.com/2011/12/edit-google-chrome-thumbnail-page.html</link><author>noreply@blogger.com (Anonymous)</author><pubDate>Fri, 30 Dec 2011 21:41:00 +0900</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-7864970685809107300.post-2684623445639547564</guid><description>&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;
Maybe sometime you've asked yourself a question: "How the heck do I customize my Chrome' speed dial page?" If you don't, you can always do it right now. The problem is, when you accidentally delete you favorite web-site shortcut from the Google Chrome's top page (of course, if you use it for speed dial), you don't have any obvious way to restore the link. Or, perhaps, you want to add a new shortcut to your speed dial screen.&lt;br /&gt;
&lt;br /&gt;
Well, there are a couple of magic things you actually can do. First, you can download some extension for your Chrome browser (just google for "&lt;a href="https://chrome.google.com/webstore/detail/jpfpebmajhhopeonhlcgidhclcccjcik"&gt;Speed dial 2&lt;/a&gt;"). But this magic is too straightforward for real jedi.&amp;nbsp;
&lt;br /&gt;
&lt;br /&gt;
The true way is to modify Chrome browser's program files directly, as it doesn't require much of experience or mana.&lt;br /&gt;
&lt;br /&gt;
When you delete a thumbnail from the speed dial page, the identification of the deleted thumbnail is stored inside Chrome's preferences. So, you can do the trick in two possible ways: edit preferences to make Chrome "forget" than you deleted thumbnail once (kind of &amp;nbsp;"Obliviate" spell), or you can manually add and set up required link on the speed dial page.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Close all Chrome's windows and stop all Chrome's processes.&amp;nbsp;Navigate to the following folder on your computer:&lt;br /&gt;
&amp;nbsp;-- C:\Users\XXXXX\AppData\Local\Google\Chrome\User Data\Default (where "XXXXX" is for you current user account name. This one is for Windows Vista/7 users, XP adepts should find their own path inside "Programs and Settings" directory).&lt;br /&gt;
There you should find "Preferences" file (nope, no extension, folks) -- it stores every thing you set up in you Chrome browser, including ids of deleted top pages. Open this file with your favorite text editor and meet JSON format, used to store the Chrome's settings. Now find "ntp" node and "most_visited_blacklist" sub-node: you have all the deleted thumbnails listed here. I'm pretty sure it will be hard to understand, which hash key belongs to which deleted url, so just delete everything starting from&amp;nbsp;"most_visited_blacklist"&amp;nbsp;until&amp;nbsp;the first &amp;nbsp;"}," sign. Don't forget to save the file!&lt;br /&gt;
&lt;br /&gt;
Try to launch Chrome browser and see, if you deleted thumbnail appeared on the top page or not. If you can't see it, or you want to modify your speed dial page more, proceed to the following magic.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Top page's thumbnails and links are stored in a SQLite-database in Google Chrome work folder in file "Top Sites". Navigate to the same folder:&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;-- C:\Users\XXXXX\AppData\Local\Google\Chrome\User Data\Default (where "XXXXX" is for you current user account name)&lt;br /&gt;
and look for the file "Top Sites" (that's right, no extension here again).&lt;br /&gt;
&lt;br /&gt;
To open and edit this file you should have SQLite browser on your computer. If you still don't have it -- you can get it &lt;a href="http://sourceforge.net/projects/sqlitebrowser/"&gt;here&lt;/a&gt; (requires no installation). Once you launched SQLite browser exe file, open database file ("Top Sites") located at the path mentioned above -- at this point you should see database structure shown int he browser's main window. On the "Database structure" tab you can see two datatables in the file: "meta" and "thumbnails". "Meta" datatable contains meta-information (information about information) and is not a target for our magic. We will be modifying "thumbnails" datatable, so click on the "Browse data" tab and select "thumbnals" in the table combobox.&lt;br /&gt;
&lt;br /&gt;
Now you should see a data table with several columns:&lt;br /&gt;
&lt;br /&gt;
&lt;ul style="text-align: left;"&gt;
&lt;li&gt;&lt;b&gt;url&lt;/b&gt; - link to the webpage;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;url rank&lt;/b&gt; - order position, started from 0 (top left thumbnail) to 7 (bottom right);&lt;/li&gt;
&lt;li&gt;&lt;b&gt;title&lt;/b&gt; - title of the link;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;thumbnail&lt;/b&gt; - blob data (binary image data);&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
and some others.&lt;br /&gt;
&lt;br /&gt;
Now click on the "New record" button, and new record will be added to the bottom of the table. Modify the columns' contents (i.e. insert "http://www.google.com" or whatever in "url" field, edit position in "url rank" field, etc.). Save the file in the Database browser, launch Chrome and enjoy the results of this simple magic.&lt;br /&gt;
&lt;br /&gt;
You can&amp;nbsp;surprise&amp;nbsp;your friend with this simple trick by modifying his/her thumbnail image or link title on the speed dial page of the Chrome. If you do -- we have not ever met.&lt;/div&gt;</description></item><item><title>Check external SD card on Android device</title><link>http://sigidin.blogspot.com/2011/08/check-external-sd-card-on-android.html</link><author>noreply@blogger.com (Anonymous)</author><pubDate>Tue, 9 Aug 2011 23:52:00 +0900</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-7864970685809107300.post-3743526942948578843</guid><description>Want to check if external (I mean the one which can be freely removed from the device without removing the battery) SD card is inserted on the device? The standard Android API has only one method to call for it:&lt;br /&gt;
&lt;br /&gt;
&lt;span class="Apple-style-span" style="color: #666600; font-family: monospace;"&gt;&lt;span class="Apple-style-span" style="white-space: pre;"&gt;&lt;a href="http://developer.android.com/reference/android/os/Environment.html#getExternalStorageDirectory()"&gt;Environment.getExternalStorageDirectory()&lt;/a&gt;&lt;/span&gt;&lt;/span&gt;
&lt;br /&gt;
&lt;br /&gt;
Sad, but this one returns only directory, which is mounted on the device as "external" (usually, "/mnt/sdcard/"), but not the actual removable media. You can hard-code the real external storage directory, which can differ on different devices. For instance, Samsung's Galaxy family devices state the external SD drive to be mounted on&lt;br /&gt;
&lt;br /&gt;
/mnt/sdcard/external_sd/&lt;br /&gt;
&lt;br /&gt;
Anyway, before trying to get actual external path you should consult to the device manufacturer, for what mount path you should be looking for. And still, even when you know external path, you can be fucked up trying to look that folder directly.&lt;br /&gt;
&lt;br /&gt;
Consider we have a Galasy S which has external SD card path as of "/mnt/sdcard/external_sd". The most obvious way to check it is to create a File object and look for its&amp;nbsp;&lt;span class="Apple-style-span" style="color: #666600; font-family: monospace;"&gt;&lt;span class="Apple-style-span" style="white-space: pre;"&gt;isExists()&lt;/span&gt;&lt;/span&gt; boolean:&lt;br /&gt;
&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: monospace;"&gt;File f = new File("/mnt/sdcard/external_sd");&lt;br /&gt;
if (f.isExists()) {&lt;br /&gt;
&amp;nbsp; &amp;nbsp; // Dance&lt;br /&gt;
}&lt;/span&gt;
&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: monospace;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;
But your program can screw things up if no SD card is really mounted onto this directory. It's Linux, they can have external drive been mounted as your finger! So don't trust that file's &lt;span class="Apple-style-span" style="color: #666600; font-family: monospace;"&gt;&lt;span class="Apple-style-span" style="white-space: pre;"&gt;isExists()&lt;/span&gt;&lt;/span&gt; flag - it can return true when "external_sd" is exists, but no physical external SD card is mounted onto it.&lt;br /&gt;
&lt;br /&gt;
So, you fought to death with phone manufacturer to get that "&lt;i&gt;external path&lt;/i&gt;" value just to realize that it's useless anyway? No, my little&amp;nbsp;sorcerer, there is always a bit of saving magic for every "impossible" task.&lt;br /&gt;
&lt;br /&gt;
We're still on Linux' territory, remember? I mean, yeah, we are on Android, but still on Linux. It's some kind of Two-Face.&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://www.keilanluke.com/two_face.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://www.keilanluke.com/two_face.jpg" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
Well, &amp;nbsp;let's use this for our advantages. On Android device, we can get system file, which contains all currently mounted folders and path, and check, if our "external" path has actually been mounted with real media.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: monospace;"&gt;try {&lt;br /&gt;
&amp;nbsp; &amp;nbsp; // Open the file&lt;br /&gt;
&amp;nbsp; &amp;nbsp; FileInputStream fs = new FileInputStream("/proc/mounts");&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; &amp;nbsp; DataInputStream in = new DataInputStream(fs);&lt;br /&gt;
&amp;nbsp; &amp;nbsp; BufferedReader br = new BufferedReader(new InputStreamReader(in));&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; &amp;nbsp; String strLine;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; StringBuilder sb = new StringBuilder();&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; &amp;nbsp; //Read File Line By Line&lt;br /&gt;
&amp;nbsp; &amp;nbsp; while ((strLine = br.readLine()) != null) &amp;nbsp; {&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; // Remember each line&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; sb.add(strLine);&lt;br /&gt;
&amp;nbsp; &amp;nbsp; }&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; &amp;nbsp; //Close the stream&lt;br /&gt;
&amp;nbsp; &amp;nbsp; in.close();&lt;br /&gt;
} catch (Exception e) {&lt;br /&gt;
&amp;nbsp; &amp;nbsp; //Catch exception if any&lt;br /&gt;
&amp;nbsp; &amp;nbsp; e.printStackTrace();&lt;br /&gt;
}&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
So, we read&amp;nbsp;"/proc/mounts" file line by line, adding each one to the StringBuilder class instance. After all, if there nothing screwed up, we'll have file contents in memory, and can therefore cast any "contains-like" spell'&lt;br /&gt;
&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: monospace;"&gt;if (sb.contains("mnt/sdcard/external_sd")) {&lt;br /&gt;
&amp;nbsp; &amp;nbsp; // Dance&lt;br /&gt;
}&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
Sweet coding.</description></item><item><title>Выбор элементов в кастомном ArrayAdapter</title><link>http://sigidin.blogspot.com/2011/05/arrayadapter.html</link><category>GUI</category><category>андроид</category><author>noreply@blogger.com (Anonymous)</author><pubDate>Sun, 1 May 2011 23:12:00 +0900</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-7864970685809107300.post-6055860734503339898</guid><description>Недавно попался баг, из-за которого не происходил выбор айтема в кастомном ArrayAdapter.&lt;br /&gt;
&lt;br /&gt;
Актовность ListActivity вместе со всем своим волшебством в большинстве случаев хорошо справляется с задачей представления списков меню:&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://developer.android.com/reference/android/widget/ListView.html" imageanchor="1"&gt;&lt;img border="0" src="http://developer.android.com/resources/tutorials/views/images/hello-listview.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
Однако временами возникает потребность показать пользователю более информативный список, чем показан на картинке выше. В таком случае нужно немного модернизировать магию построения списка.&lt;br /&gt;
&lt;br /&gt;
В нашем случае программа должна была в списке показывать не только название каждого элемента, но и дополнительную информацию, а также предоставлять пользователю без лишних телодвижений включить-выключить любой пункт меню посредством стандартного чекбокса. На экране все это колдунство выглядело приблезительно так:&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiAQnMLtw5NzvPVndRFV3LFllIMUUsCsrv-3a227KBznSrwah_De-H39fVSbgcx2jnW-EtRVXaEKemQ0lRkFuTjNwiIYV_mGGWE7C450714Kx1RcEy1hjQixxDWNPUFWPPqG9S7t8_osKmy/s1600/device.png" imageanchor="1"&gt;&lt;img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiAQnMLtw5NzvPVndRFV3LFllIMUUsCsrv-3a227KBznSrwah_De-H39fVSbgcx2jnW-EtRVXaEKemQ0lRkFuTjNwiIYV_mGGWE7C450714Kx1RcEy1hjQixxDWNPUFWPPqG9S7t8_osKmy/s320/device.png" width="212" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
Т.е. вместо стандартного текста каждый элемент этого кастомного меню содержит а) текстбокс для названия (большой шрифт), б) текстбокс для описания (мелкий щрифт) и ц) чекбокс для увлекательного чеканья.&lt;br /&gt;
&lt;br /&gt;
В коде эта картинка звучит следующим образом:&lt;br /&gt;
&lt;pre style="background: #EEE; color: black; padding: 10px 5px;"&gt;&lt;span style="color: #7f0055; font-weight: bold;"&gt;public&lt;/span&gt; &lt;span style="color: #7f0055; font-weight: bold;"&gt;class&lt;/span&gt; MyAdapter &lt;span style="color: #7f0055; font-weight: bold;"&gt;extends&lt;/span&gt; ArrayAdapter&amp;lt;MyDataClass&amp;gt;
{
    &lt;span style="color: #7f0055; font-weight: bold;"&gt;public&lt;/span&gt; MyAdapter(&lt;span style="color: #7f0055; font-weight: bold;"&gt;final&lt;/span&gt; Context context, &lt;span style="color: #7f0055; font-weight: bold;"&gt;final&lt;/span&gt; &lt;span style="color: #7f0055; font-weight: bold;"&gt;List&lt;/span&gt;&amp;lt;MyDataClass&amp;gt; items)
    {
        &lt;span style="color: #3f7f59;"&gt;// Конструктор&lt;/span&gt;
        &lt;span style="color: #7f0055; font-weight: bold;"&gt;super&lt;/span&gt;(context, R.layout.sensorslist, items);
    }

   @Override
    &lt;span style="color: #7f0055; font-weight: bold;"&gt;public&lt;/span&gt; View getView(&lt;span style="color: #7f0055; font-weight: bold;"&gt;final&lt;/span&gt; &lt;span style="color: #7f0055; font-weight: bold;"&gt;int&lt;/span&gt; position,
                &lt;span style="color: #7f0055; font-weight: bold;"&gt;final&lt;/span&gt; View convertView,
                &lt;span style="color: #7f0055; font-weight: bold;"&gt;final&lt;/span&gt; ViewGroup parent)
    {
        &lt;span style="color: #3f7f59;"&gt;// Инициализация пунктов меню, каждого в отдельности&lt;/span&gt;
        TextView title = (TextView) v.findViewById(R.id.sensor_text);
        TextView details = (TextView) v.findViewById(R.id.sensor_comments);
        CheckBox enabled = (CheckBox) v.findViewById(R.id.sensor_enabled);
        &lt;span style="color: #3f7f59;"&gt;// И потом делаем с ними что хотим...&lt;/span&gt;
    }
}
&lt;/pre&gt;NB. Метод getView вызывается автоматически классом-родителем при создании пунктов меню, причем вызывается для каждого пункта, а не для всего списка сразу.&lt;br /&gt;
&lt;br /&gt;
В конструктор помимо контекста передается список с кастомным классом данных (о нем еще ниже будет). К созданному классу MyAdapter применяется свой лэйаут, который определяет расположение элементов внутри каждого пункта меню:&lt;br /&gt;
&lt;pre style="background: #EEE; color: black; padding: 10px 5px;"&gt;&lt;span style="color: #7f0055;"&gt;&amp;lt;?&lt;/span&gt;&lt;span style="color: #7f0055;"&gt;xml&lt;/span&gt; &lt;span style="color: #7f0055;"&gt;version&lt;/span&gt;="1.0" &lt;span style="color: #7f0055;"&gt;encoding&lt;/span&gt;=&lt;span style="color: #2a00ff;"&gt;"utf-8"&lt;/span&gt;&lt;span style="color: #7f0055;"&gt;?&amp;gt;&lt;/span&gt;

&lt;span style="color: #7f0055;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #7f0055;"&gt;RelativeLayout&lt;/span&gt; xmlns:android=&lt;span style="color: #2a00ff;"&gt;"&lt;/span&gt;&lt;span style="color: #2a00ff;"&gt;http&lt;/span&gt;&lt;span style="color: #2a00ff;"&gt;:&lt;/span&gt;&lt;span style="color: #7f0055; font-weight: bold;"&gt;//&lt;/span&gt;&lt;span style="color: #3f3fbf;"&gt;schemas.android.com&lt;/span&gt;&lt;span style="color: #3f3fbf;"&gt;/apk/res/android&lt;/span&gt;&lt;span style="color: #2a00ff;"&gt;"&lt;/span&gt;
    android:layout_width=&lt;span style="color: #2a00ff;"&gt;"&lt;/span&gt;&lt;span style="color: #2a00ff;"&gt;fill_parent&lt;/span&gt;&lt;span style="color: #2a00ff;"&gt;"&lt;/span&gt;
    android:layout_height=&lt;span style="color: #2a00ff;"&gt;"&lt;/span&gt;&lt;span style="color: #2a00ff;"&gt;wrap_content&lt;/span&gt;&lt;span style="color: #2a00ff;"&gt;"&lt;/span&gt;
    android:orientation=&lt;span style="color: #2a00ff;"&gt;"&lt;/span&gt;&lt;span style="color: #2a00ff;"&gt;horizontal&lt;/span&gt;&lt;span style="color: #2a00ff;"&gt;"&lt;/span&gt;&lt;span style="color: #7f0055;"&gt;&amp;gt;&lt;/span&gt;

    &lt;span style="color: #7f0055;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #7f0055;"&gt;LinearLayout&lt;/span&gt;
        android:layout_width=&lt;span style="color: #2a00ff;"&gt;"&lt;/span&gt;&lt;span style="color: #2a00ff;"&gt;wrap_content&lt;/span&gt;&lt;span style="color: #2a00ff;"&gt;"&lt;/span&gt;
        android:layout_height=&lt;span style="color: #2a00ff;"&gt;"&lt;/span&gt;&lt;span style="color: #2a00ff;"&gt;wrap_content&lt;/span&gt;&lt;span style="color: #2a00ff;"&gt;"&lt;/span&gt;
        android:orientation=&lt;span style="color: #2a00ff;"&gt;"&lt;/span&gt;&lt;span style="color: #2a00ff;"&gt;vertical&lt;/span&gt;&lt;span style="color: #2a00ff;"&gt;"&lt;/span&gt;&lt;span style="color: #7f0055;"&gt;&amp;gt;&lt;/span&gt;

        &lt;span style="color: #7f0055;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #7f0055;"&gt;TextView&lt;/span&gt; android:id=&lt;span style="color: #2a00ff;"&gt;"&lt;/span&gt;&lt;span style="color: #2a00ff;"&gt;@+id/sensor_text&lt;/span&gt;&lt;span style="color: #2a00ff;"&gt;"&lt;/span&gt;
            android:layout_width=&lt;span style="color: #2a00ff;"&gt;"&lt;/span&gt;&lt;span style="color: #2a00ff;"&gt;200dp&lt;/span&gt;&lt;span style="color: #2a00ff;"&gt;"&lt;/span&gt;
            android:layout_height=&lt;span style="color: #2a00ff;"&gt;"&lt;/span&gt;&lt;span style="color: #2a00ff;"&gt;wrap_content&lt;/span&gt;&lt;span style="color: #2a00ff;"&gt;"&lt;/span&gt;
            android:lines=&lt;span style="color: #2a00ff;"&gt;"&lt;/span&gt;&lt;span style="color: #2a00ff;"&gt;1&lt;/span&gt;&lt;span style="color: #2a00ff;"&gt;"&lt;/span&gt;
            android:scrollHorizontally=&lt;span style="color: #2a00ff;"&gt;"&lt;/span&gt;&lt;span style="color: #2a00ff;"&gt;true&lt;/span&gt;&lt;span style="color: #2a00ff;"&gt;"&lt;/span&gt;
            android:ellipsize=&lt;span style="color: #2a00ff;"&gt;"&lt;/span&gt;&lt;span style="color: #2a00ff;"&gt;end&lt;/span&gt;&lt;span style="color: #2a00ff;"&gt;"&lt;/span&gt;
            android:paddingLeft=&lt;span style="color: #2a00ff;"&gt;"&lt;/span&gt;&lt;span style="color: #2a00ff;"&gt;2sp&lt;/span&gt;&lt;span style="color: #2a00ff;"&gt;"&lt;/span&gt;
            android:paddingTop=&lt;span style="color: #2a00ff;"&gt;"&lt;/span&gt;&lt;span style="color: #2a00ff;"&gt;2sp&lt;/span&gt;&lt;span style="color: #2a00ff;"&gt;"&lt;/span&gt;
            android:textSize=&lt;span style="color: #2a00ff;"&gt;"&lt;/span&gt;&lt;span style="color: #2a00ff;"&gt;18sp&lt;/span&gt;&lt;span style="color: #2a00ff;"&gt;"&lt;/span&gt;
            android:textStyle=&lt;span style="color: #2a00ff;"&gt;"&lt;/span&gt;&lt;span style="color: #2a00ff;"&gt;bold&lt;/span&gt;&lt;span style="color: #2a00ff;"&gt;"&lt;/span&gt;
            android:shadowColor=&lt;span style="color: #2a00ff;"&gt;"&lt;/span&gt;&lt;span style="color: #2a00ff;"&gt;#90909090&lt;/span&gt;&lt;span style="color: #2a00ff;"&gt;"&lt;/span&gt;
            android:shadowDx=&lt;span style="color: #2a00ff;"&gt;"&lt;/span&gt;&lt;span style="color: #2a00ff;"&gt;1.0&lt;/span&gt;&lt;span style="color: #2a00ff;"&gt;"&lt;/span&gt;
            android:shadowDy=&lt;span style="color: #2a00ff;"&gt;"&lt;/span&gt;&lt;span style="color: #2a00ff;"&gt;1.0&lt;/span&gt;&lt;span style="color: #2a00ff;"&gt;"&lt;/span&gt;
            android:shadowRadius=&lt;span style="color: #2a00ff;"&gt;"&lt;/span&gt;&lt;span style="color: #2a00ff;"&gt;1.0&lt;/span&gt;&lt;span style="color: #2a00ff;"&gt;"&lt;/span&gt;&lt;span style="color: #7f0055;"&gt;/&amp;gt;&lt;/span&gt;

        &lt;span style="color: #7f0055;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #7f0055;"&gt;TextView&lt;/span&gt; android:id=&lt;span style="color: #2a00ff;"&gt;"&lt;/span&gt;&lt;span style="color: #2a00ff;"&gt;@+id/sensor_comments&lt;/span&gt;&lt;span style="color: #2a00ff;"&gt;"&lt;/span&gt;
            android:layout_width=&lt;span style="color: #2a00ff;"&gt;"&lt;/span&gt;&lt;span style="color: #2a00ff;"&gt;wrap_content&lt;/span&gt;&lt;span style="color: #2a00ff;"&gt;"&lt;/span&gt;
            android:layout_height=&lt;span style="color: #2a00ff;"&gt;"&lt;/span&gt;&lt;span style="color: #2a00ff;"&gt;wrap_content&lt;/span&gt;&lt;span style="color: #2a00ff;"&gt;"&lt;/span&gt;
            android:textSize=&lt;span style="color: #2a00ff;"&gt;"&lt;/span&gt;&lt;span style="color: #2a00ff;"&gt;12sp&lt;/span&gt;&lt;span style="color: #2a00ff;"&gt;"&lt;/span&gt;
            android:textColor=&lt;span style="color: #2a00ff;"&gt;"&lt;/span&gt;&lt;span style="color: #2a00ff;"&gt;#FF808080&lt;/span&gt;&lt;span style="color: #2a00ff;"&gt;"&lt;/span&gt;
            android:paddingLeft=&lt;span style="color: #2a00ff;"&gt;"&lt;/span&gt;&lt;span style="color: #2a00ff;"&gt;2sp&lt;/span&gt;&lt;span style="color: #2a00ff;"&gt;"&lt;/span&gt;
            android:paddingTop=&lt;span style="color: #2a00ff;"&gt;"&lt;/span&gt;&lt;span style="color: #2a00ff;"&gt;2sp&lt;/span&gt;&lt;span style="color: #2a00ff;"&gt;"&lt;/span&gt;&lt;span style="color: #7f0055;"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span style="color: #7f0055;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #7f0055;"&gt;LinearLayout&lt;/span&gt;&lt;span style="color: #7f0055;"&gt;&amp;gt;&lt;/span&gt;

    &lt;span style="color: #7f0055;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #7f0055;"&gt;CheckBox&lt;/span&gt; android:id=&lt;span style="color: #2a00ff;"&gt;"&lt;/span&gt;&lt;span style="color: #2a00ff;"&gt;@+id/sensor_enabled&lt;/span&gt;&lt;span style="color: #2a00ff;"&gt;"&lt;/span&gt;
        android:layout_width=&lt;span style="color: #2a00ff;"&gt;"&lt;/span&gt;&lt;span style="color: #2a00ff;"&gt;wrap_content&lt;/span&gt;&lt;span style="color: #2a00ff;"&gt;"&lt;/span&gt;
        android:layout_height=&lt;span style="color: #2a00ff;"&gt;"&lt;/span&gt;&lt;span style="color: #2a00ff;"&gt;wrap_content&lt;/span&gt;&lt;span style="color: #2a00ff;"&gt;"&lt;/span&gt;
        android:layout_centerVertical=&lt;span style="color: #2a00ff;"&gt;"&lt;/span&gt;&lt;span style="color: #2a00ff;"&gt;true&lt;/span&gt;&lt;span style="color: #2a00ff;"&gt;"&lt;/span&gt;
        android:layout_alignParentRight=&lt;span style="color: #2a00ff;"&gt;"&lt;/span&gt;&lt;span style="color: #2a00ff;"&gt;true&lt;/span&gt;&lt;span style="color: #2a00ff;"&gt;"&lt;/span&gt;
        android:paddingRight=&lt;span style="color: #2a00ff;"&gt;"&lt;/span&gt;&lt;span style="color: #2a00ff;"&gt;5sp&lt;/span&gt;&lt;span style="color: #2a00ff;"&gt;"&lt;/span&gt;&lt;span style="color: #7f0055;"&gt;/&amp;gt;&lt;/span&gt;
&lt;span style="color: #7f0055;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #7f0055;"&gt;RelativeLayout&lt;/span&gt;&lt;span style="color: #7f0055;"&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;br /&gt;
И, наконец, вызывается все это волшебство в нужной активности с помощью нехитрых махинаций &lt;strike&gt;волшебным посохом&lt;/strike&gt;:&lt;br /&gt;
&lt;pre style="background: #EEE; color: black; padding: 10px 5px;"&gt;&lt;span style="color: #7f0055; font-weight: bold;"&gt;public&lt;/span&gt; &lt;span style="color: #7f0055; font-weight: bold;"&gt;class&lt;/span&gt; ExtendedListActivity &lt;span style="color: #7f0055; font-weight: bold;"&gt;extends&lt;/span&gt; ListActivity
{
    @Override
    &lt;span style="color: #7f0055; font-weight: bold;"&gt;public&lt;/span&gt; &lt;span style="color: #7f0055; font-weight: bold;"&gt;void&lt;/span&gt; onCreate(&lt;span style="color: #7f0055; font-weight: bold;"&gt;final&lt;/span&gt; Bundle savedInstanceState)
    {
        &lt;span style="color: #7f0055; font-weight: bold;"&gt;super&lt;/span&gt;.onCreate(savedInstanceState);
        
        &lt;span style="color: #7f0055; font-weight: bold;"&gt;List&lt;/span&gt;&amp;lt;MyDataClass&amp;gt; datas = &lt;span style="color: #7f0055; font-weight: bold;"&gt;new&lt;/span&gt; &lt;span style="color: #7f0055; font-weight: bold;"&gt;List&lt;/span&gt;&amp;lt;MyDataClass&amp;gt;();
        
        &lt;span style="color: #3f7f59;"&gt;// Здесь мы совершаем необходимые нам махинации с классами данных,&lt;/span&gt;
        &lt;span style="color: #3f7f59;"&gt;// добавляя созданные инстансы в список&lt;/span&gt;
        &lt;span style="color: #7f0055; font-weight: bold;"&gt;for&lt;/span&gt; (&lt;span style="color: #7f0055; font-weight: bold;"&gt;int&lt;/span&gt; i = 0; i &amp;lt; 10; i++)
        {
            MyDataClass cl = &lt;span style="color: #7f0055; font-weight: bold;"&gt;new&lt;/span&gt; MyDataClass();
            datas.add(cl)
        }

        MyAdapter adapter = &lt;span style="color: #7f0055; font-weight: bold;"&gt;new&lt;/span&gt; MyAdapter(&lt;span style="color: #7f0055; font-weight: bold;"&gt;this&lt;/span&gt;.getApplicationContext(), datas);

        setListAdapter(adapter);
        
        &lt;span style="color: #3f7f59;"&gt;// А теперь создадим слушателя для тыков в меню&lt;/span&gt;
        ListView v = &lt;span style="color: #7f0055; font-weight: bold;"&gt;this&lt;/span&gt;.getListView();
        v.setOnItemClickListener(&lt;span style="color: #7f0055; font-weight: bold;"&gt;new&lt;/span&gt; OnItemClickListener() {
            @Override
            &lt;span style='color:#7f0055; font-weight:bold; '&gt;public&lt;/span&gt; &lt;span style='color:#7f0055; font-weight:bold; '&gt;void&lt;/span&gt; onItemClick(&lt;span style='color:#7f0055; font-weight:bold; '&gt;final&lt;/span&gt; AdapterView&amp;lt;?&gt; arg0,
                    &lt;span style='color:#7f0055; font-weight:bold; '&gt;final&lt;/span&gt; View view,
                    &lt;span style='color:#7f0055; font-weight:bold; '&gt;final&lt;/span&gt; &lt;span style='color:#7f0055; font-weight:bold; '&gt;int&lt;/span&gt; clicked,
                    &lt;span style='color:#7f0055; font-weight:bold; '&gt;final&lt;/span&gt; &lt;span style='color:#7f0055; font-weight:bold; '&gt;long&lt;/span&gt; position)
            {
                &lt;span style='color:#3f7f59; '&gt;// Получаем номер пункта меню и исполняем
                // свой танец&lt;/span&gt;
            }
        });
    }    
}
&lt;/pre&gt;&lt;br /&gt;
Все, вроде, в порядке вещей, однако не слишком подкованные гипнотезеры часто упускают из вида один совсем неочевидный (к сожалению, довольно обычное дело для дядьки Андроида) момент, и в итоге это может приводить к непонятному хаосу в погоне за невидимым багом. Дело в том, что активность ListActivity, которая ответственна за показ элементов в виде списка, напрочь отказывается запускать OnItemClickListener (отросток, который помогает отлавливать события нажатий на пункты меню) ни за какие деньги. Принципиальная.&lt;br /&gt;
&lt;br /&gt;
Чтобы нерадивые гипнотезеры и дальше паниковали под действием своего же хаоса, незаметно добавляем строчку в лэйаут, описывающий чекбокс:&lt;br /&gt;
&lt;pre style="background-attachment: initial; background-clip: initial; background-color: #eeeeee; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; padding-bottom: 10px; padding-left: 5px; padding-right: 5px; padding-top: 10px;"&gt;&lt;span class="Apple-style-span" style="color: black;"&gt;&lt;span style="color: #7f0055;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #7f0055;"&gt;CheckBox&lt;/span&gt; android:id=&lt;span style="color: #2a00ff;"&gt;"&lt;/span&gt;&lt;span style="color: #2a00ff;"&gt;@+id/sensor_enabled&lt;/span&gt;&lt;span style="color: #2a00ff;"&gt;"&lt;/span&gt;
        android:layout_width=&lt;span style="color: #2a00ff;"&gt;"&lt;/span&gt;&lt;span style="color: #2a00ff;"&gt;wrap_content&lt;/span&gt;&lt;span style="color: #2a00ff;"&gt;"&lt;/span&gt;
        android:layout_height=&lt;span style="color: #2a00ff;"&gt;"&lt;/span&gt;&lt;span style="color: #2a00ff;"&gt;wrap_content&lt;/span&gt;&lt;span style="color: #2a00ff;"&gt;"&lt;/span&gt;
        android:layout_centerVertical=&lt;span style="color: #2a00ff;"&gt;"&lt;/span&gt;&lt;span style="color: #2a00ff;"&gt;true&lt;/span&gt;&lt;span style="color: #2a00ff;"&gt;"&lt;/span&gt;
        android:layout_alignParentRight=&lt;span style="color: #2a00ff;"&gt;"&lt;/span&gt;&lt;span style="color: #2a00ff;"&gt;true&lt;/span&gt;&lt;span style="color: #2a00ff;"&gt;"&lt;/span&gt;
        &lt;/span&gt;&lt;span class="Apple-style-span" style="color: red;"&gt;android:focusable="false"&lt;/span&gt;
        android:paddingRight=&lt;span style="color: #2a00ff;"&gt;"&lt;/span&gt;&lt;span style="color: #2a00ff;"&gt;5sp&lt;/span&gt;&lt;span style="color: #2a00ff;"&gt;"&lt;/span&gt;&lt;span style="color: #7f0055;"&gt;/&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;br /&gt;
И молча хихикаем в сторонке, зная, что Андроид не позволяет выбирать из списка айтемы, элементы которых могут быть фокусируемыми (focusable).</description><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" height="72" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiAQnMLtw5NzvPVndRFV3LFllIMUUsCsrv-3a227KBznSrwah_De-H39fVSbgcx2jnW-EtRVXaEKemQ0lRkFuTjNwiIYV_mGGWE7C450714Kx1RcEy1hjQixxDWNPUFWPPqG9S7t8_osKmy/s72-c/device.png" width="72"/></item><item><title>Ошибка транзакций в приложениях</title><link>http://sigidin.blogspot.com/2011/03/blog-post.html</link><category>android</category><category>apps</category><author>noreply@blogger.com (Anonymous)</author><pubDate>Tue, 8 Mar 2011 18:50:00 +0900</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-7864970685809107300.post-7063414046830265059</guid><description>Мутантская ошибка, которая может послужить причиной длительного брейнфакерства.&lt;br /&gt;
&lt;br /&gt;
Приложение для Андроид (Froyo, но также воспроизводится и на Gingerbread, т.е. встречается на API версий 8-9), по событию читает страницу в интернете и отображает ее в виджете. Вроде вся магия простая как в мультфильмах, но почему-то картинки в виджете в одних случаях показываются, в других - не показываются. Стали разбираться. &lt;br /&gt;
&lt;br /&gt;
Проблемы начинаются после перехода на девайсы с большим разрешением экрана - это стало понятно сразу. Лог - чистый и красивый, за исключением одной строки:&lt;br /&gt;
&lt;span class="Apple-style-span" style="color: red;"&gt;&lt;b&gt;JavaBinder "!!! Failed binder transaction !!!"&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
Ясно, что кто-то куда-то не может прицепиться, из-за чего система выкидывает ошибку и перестает апдейтить процесс. Но что куда не может прицепиться и по какой причине - оставалось загадкой.&lt;br /&gt;
&lt;br /&gt;
Указанную выше ошибку выкидывает JavaBinder, у которого платформой ограничены размеры транзакций (что-то около 100 кб). Ошибка возникает, если между двумя отдельно взятыми процессами единовременно передается большой (т.е. гораздо больше размера транзакции) кусок информации. В нашем случае, колдунство предполагает создание скриншота веб-страницы в одном процессе и передача его для обновления в виджет. То есть прямо по учебнику.&lt;br /&gt;
&lt;br /&gt;
Ключем к пониманию этой магии послужила смена разрешения экранов. Для того, чтобы сохранить отображаемую веб-страницу в качестве картинки, нам нужно воспользоваться контроллом WebView (переопределив его PictureListener). Получаемая на выходе картинка представляет собой загруженную и отображеную в контролле веб-страницу. Линейные размеры картинки не отличаются в зависимости от количества пукселей на дисплее девайса, однако при отображении в WebView или в виджете размер конечного файла может сильно отличаться.&lt;br /&gt;
&lt;br /&gt;
Например, нам надо отобразить скриншот веб-страницы размером 600х600 пукселей на экране разрешением 300х300 (таких экранов на рынок не выпускают, это для примера). Очевидно, что в этом случае требуется вмешательство волшебства, уменьшающего реальный размер картинки в четыре раза (каждую сторону - в два раза). Понятно, что для экранов разрешением 600х600 уменьшать ничего не придется и размер картинки будет в 4 раза большим. Поэтому для относительно небольших экранов картинки удачно обрабатываются транзакциями, в то время как для больших экранов переброска объемных данных вызывает ошибки в транзакциях: виртуальная машина выбрасывает исключение и перестает обновлять процесс, от этого виджет хоть и существует в памяти, на самом деле не обновляется (в нашем случае он оставался невидимым, но это зависит только от лэйаута).&lt;br /&gt;
&lt;br /&gt;
Самый простой способ предотвратить слишком большой размер файла - принудительное уменьшение размера файла:&lt;br /&gt;
&lt;br /&gt;
&lt;pre style='color:#000000;background:#EEE;padding:10px 5px;'&gt;&lt;span style='color:#7f0055; font-weight:bold; '&gt;public&lt;/span&gt; &lt;span style='color:#7f0055; font-weight:bold; '&gt;static&lt;/span&gt; Bitmap makeBitmap() {
    Bitmap bitmap = &lt;span style='color:#7f0055; font-weight:bold; '&gt;null&lt;/span&gt;;
    BitmapFactory.Options bmOp = &lt;span style='color:#7f0055; font-weight:bold; '&gt;new&lt;/span&gt; BitmapFactory.Options();
    &lt;span style='color:#7f0055; font-weight:bold; '&gt;String&lt;/span&gt; filePath = &lt;span style='color:#2a00ff; '&gt;"foo/bar/baz"&lt;/span&gt;;

    &lt;span style='color:#3f7f59; '&gt;// Здесь указываем, во сколько раз нужно&lt;/span&gt;
    &lt;span style='color:#3f7f59; '&gt;// уменьшить каждую сторону картинки&lt;/span&gt;
    bmOp.inSampleSize = 2;
    bitmap = BitmapFactory.decodeFile(filePath, bmOp);

    &lt;span style='color:#7f0055; font-weight:bold; '&gt;return&lt;/span&gt; bitmap;
}
&lt;/pre&gt;&lt;br /&gt;
NB. Рекомендую использовать четные числа для семплирования (в &lt;a href="http://en.wikipedia.org/wiki/Chroma_subsampling"&gt;теоретическом разделе&lt;/a&gt; интернета всем всегда рады).&lt;br /&gt;
&lt;br /&gt;
Однако такой колдунство не всегда прокатывает по двум причинам:&lt;br /&gt;
1. Не всегда понятно, во сколько раз нужно уменьшать размеры&lt;br /&gt;
2. Уменьшенная картинка - это уменьшенная картинка, т.е. если вы (или ваш заказчик в лице Докомо) придумали показывать такую картинку на весь экран девайса - картика будет в 2 (3, 4, 5 и т.д.) раз меньше размера экрана.&lt;br /&gt;
&lt;br /&gt;
Может, причин сущетсвует еще больше (практически уверен).&lt;br /&gt;
&lt;br /&gt;
Поэтому сейчас колдунство следует совместить с алхимией. Для этого нужно полученную картинку сначала явно уменьшить до какого-нибудь приемлимого значения, а потом вписать уменьшенную картинку в нужную область на Canvas'е:&lt;br /&gt;
&lt;br /&gt;
&lt;pre style='color:#000000;background:#EEE;padding:10px 5px;'&gt;&lt;span style='color:#7f0055; font-weight:bold; '&gt;public&lt;/span&gt; &lt;span style='color:#7f0055; font-weight:bold; '&gt;static&lt;/span&gt; void makeBitmap(Picture picture) {
    Context con = getApplicationContext();
    Resources r = con.getResources();
    DisplayMetrics me = r.getDisplayMetrics();

    &lt;span style='color:#7f0055; font-weight:bold; '&gt;float&lt;/span&gt; screenWidth = me.widthPixels;
    &lt;span style='color:#7f0055; font-weight:bold; '&gt;float&lt;/span&gt; screenHeight = me.heightPixels;

    &lt;span style='color:#7f0055; font-weight:bold; '&gt;float&lt;/span&gt; screenScale;
    Bitmap b;
    &lt;span style='color:#7f0055; font-weight:bold; '&gt;Canvas&lt;/span&gt; c;

    &lt;span style='color:#7f0055; font-weight:bold; '&gt;int&lt;/span&gt; newPicWidth, newPicHeight;

    &lt;span style='color:#3f7f59; '&gt;// Смотрим, во сколько ширина дисплея больше высоты&lt;/span&gt;
    screenScale = screenWidth / screenHeight;
    
    &lt;span style='color:#3f7f59; '&gt;// Устанавливаем размер картинки на 80% от размера экрана&lt;/span&gt;
    &lt;span style='color:#3f7f59; '&gt;// При разрешении 854х600 ошибок переполнения буффера транзакции&lt;/span&gt;
    &lt;span style='color:#3f7f59; '&gt;// возникать не должно, но если что - число можно подрегулировать&lt;/span&gt;
    newPicWidth = (&lt;span style='color:#7f0055; font-weight:bold; '&gt;int&lt;/span&gt;)(screenWidth * 0.8);
    newPicHeight = (&lt;span style='color:#7f0055; font-weight:bold; '&gt;int&lt;/span&gt;)(newPicWidth / screenScale * 0.8);
    
    &lt;span style='color:#3f7f59; '&gt;// Создаем битмап и холст для него&lt;/span&gt;
    b = Bitmap.createBitmap(newPicWidth, newPicHeight, Bitmap.Config.RGB_565);
    c = &lt;span style='color:#7f0055; font-weight:bold; '&gt;new&lt;/span&gt; &lt;span style='color:#7f0055; font-weight:bold; '&gt;Canvas&lt;/span&gt;(b);

    Rect dst = &lt;span style='color:#7f0055; font-weight:bold; '&gt;new&lt;/span&gt; Rect();
    dst.top = 0;
    dst.left = 0;
    dst.right = newPicWidth;
    dst.bottom = picHeight;

    &lt;span style='color:#3f7f59; '&gt;// Рисуем картинку на битмап&lt;/span&gt;
    &lt;span style='color:#3f7f59; '&gt;// Картинка растягивается или ужимается при необходимости&lt;/span&gt;
    c.drawPicture(picture, dst);
    
    &lt;span style='color:#3f7f59; '&gt;// После этого можем сохранить битмап как файл&lt;/span&gt;
    &lt;span style='color:#3f7f59; '&gt;// или открыть его в виджете&lt;/span&gt;
}
&lt;/pre&gt;</description></item><item><title>Программирование сокетов в Linux</title><link>http://sigidin.blogspot.com/2011/01/linux.html</link><category>android</category><category>linux</category><category>network</category><author>noreply@blogger.com (Anonymous)</author><pubDate>Sun, 30 Jan 2011 17:55:00 +0900</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-7864970685809107300.post-5600590827704063323</guid><description>При написании приложения для Андроид иногда (очень редко) возникает необходимость пообщаться с сервером на уровне более низком, чем Java　SDK. Например, если вы создаете низкоуровневый сервис, работающий напрямую с данными оператора (загрузка обновления системы, активация телефонного девайса в сети оператора и т.д.), приходится иметь дело с сокетами (в грубом приближении - инетрфейсами между железом и програмной частью).&lt;br /&gt;
&lt;br /&gt;
Работать с сокетами на низком уронде в Андроиде (т.е. на ядре линукс) можно с помощью следующего набора заклинаний.&lt;br /&gt;
&lt;br /&gt;
&lt;pre style='color:#000000;background:#FAF2EF;'&gt;&lt;span style='color:#7f0055; '&gt;#&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;define&lt;/span&gt;&lt;span style='color:#7f0055; '&gt; WIN32&lt;/span&gt;

&lt;span style='color:#3f7f59; '&gt;// заголовки стандартного C&lt;/span&gt;
&lt;span style='color:#7f0055; '&gt;#&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;include &lt;/span&gt;&lt;span style='color:#2a00ff; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#3f3fbf; '&gt;string.h&lt;/span&gt;&lt;span style='color:#2a00ff; '&gt;&gt;&lt;/span&gt;
&lt;span style='color:#7f0055; '&gt;#&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;include &lt;/span&gt;&lt;span style='color:#2a00ff; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#3f3fbf; '&gt;stdio.h&lt;/span&gt;&lt;span style='color:#2a00ff; '&gt;&gt;&lt;/span&gt;

&lt;span style='color:#3f7f59; '&gt;// подключаем заголовки для разных OS&lt;/span&gt;
&lt;span style='color:#7f0055; '&gt;#&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;if&lt;/span&gt;&lt;span style='color:#7f0055; '&gt; &lt;/span&gt;&lt;span style='color:#7f0055; '&gt;defined&lt;/span&gt;&lt;span style='color:#7f0055; '&gt; WIN32&lt;/span&gt;
&lt;span style='color:#7f0055; '&gt;#&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;include &lt;/span&gt;&lt;span style='color:#2a00ff; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#3f3fbf; '&gt;winsock.h&lt;/span&gt;&lt;span style='color:#2a00ff; '&gt;&gt;&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;  &lt;/span&gt;&lt;span style='color:#3f7f59; '&gt;// WinSock&lt;/span&gt;
&lt;span style='color:#7f0055; '&gt;#&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;elif&lt;/span&gt;&lt;span style='color:#7f0055; '&gt; &lt;/span&gt;&lt;span style='color:#7f0055; '&gt;defined&lt;/span&gt;&lt;span style='color:#7f0055; '&gt; LINUX&lt;/span&gt;
&lt;span style='color:#7f0055; '&gt;#&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;include &lt;/span&gt;&lt;span style='color:#2a00ff; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#3f3fbf; '&gt;unistd.h&lt;/span&gt;&lt;span style='color:#2a00ff; '&gt;&gt;&lt;/span&gt;
&lt;span style='color:#7f0055; '&gt;#&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;include &lt;/span&gt;&lt;span style='color:#2a00ff; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#3f3fbf; '&gt;netdb.h&lt;/span&gt;&lt;span style='color:#2a00ff; '&gt;&gt;&lt;/span&gt;
&lt;span style='color:#7f0055; '&gt;#&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;include &lt;/span&gt;&lt;span style='color:#2a00ff; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#3f3fbf; '&gt;sys/types.h&lt;/span&gt;&lt;span style='color:#2a00ff; '&gt;&gt;&lt;/span&gt;
&lt;span style='color:#7f0055; '&gt;#&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;include &lt;/span&gt;&lt;span style='color:#2a00ff; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#3f3fbf; '&gt;sys/socket.h&lt;/span&gt;&lt;span style='color:#2a00ff; '&gt;&gt;&lt;/span&gt;
&lt;span style='color:#7f0055; '&gt;#&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;include &lt;/span&gt;&lt;span style='color:#2a00ff; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#3f3fbf; '&gt;arpa/inet.h&lt;/span&gt;&lt;span style='color:#2a00ff; '&gt;&gt;&lt;/span&gt;
&lt;span style='color:#7f0055; '&gt;#&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;endif&lt;/span&gt;

&lt;span style='color:#3f7f59; '&gt;// переопределяем некоторые типы и константы&lt;/span&gt;
&lt;span style='color:#3f7f59; '&gt;// в зависимости от OS&lt;/span&gt;
&lt;span style='color:#7f0055; '&gt;#&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;if&lt;/span&gt;&lt;span style='color:#7f0055; '&gt; &lt;/span&gt;&lt;span style='color:#7f0055; '&gt;defined&lt;/span&gt;&lt;span style='color:#7f0055; '&gt; WIN32&lt;/span&gt;
&lt;span style='color:#7f0055; font-weight:bold; '&gt;typedef&lt;/span&gt; &lt;span style='color:#7f0055; font-weight:bold; '&gt;int&lt;/span&gt; socklen_t;  &lt;span style='color:#3f7f59; '&gt;// размер сокета в Unix&lt;/span&gt;
&lt;span style='color:#7f0055; '&gt;#&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;elif&lt;/span&gt;&lt;span style='color:#7f0055; '&gt; &lt;/span&gt;&lt;span style='color:#7f0055; '&gt;defined&lt;/span&gt;&lt;span style='color:#7f0055; '&gt; LINUX&lt;/span&gt;
&lt;span style='color:#7f0055; font-weight:bold; '&gt;typedef&lt;/span&gt; &lt;span style='color:#7f0055; font-weight:bold; '&gt;int&lt;/span&gt; SOCKET;
&lt;span style='color:#7f0055; '&gt;#&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;define&lt;/span&gt;&lt;span style='color:#7f0055; '&gt; INVALID_SOCKET &lt;/span&gt;&lt;span style='color:#7f0055; '&gt;-&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;1  &lt;/span&gt;&lt;span style='color:#3f7f59; '&gt;// костанта WinSock&lt;/span&gt;
&lt;span style='color:#7f0055; '&gt;#&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;define&lt;/span&gt;&lt;span style='color:#7f0055; '&gt; SOCKET_ERROR   &lt;/span&gt;&lt;span style='color:#7f0055; '&gt;-&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;1  &lt;/span&gt;&lt;span style='color:#3f7f59; '&gt;// стандартная ошибка WinSock&lt;/span&gt;

&lt;span style='color:#3f7f59; '&gt;// WinSock, в отличие от Unix, не использует файл-дескрипторы&lt;/span&gt;
&lt;span style='color:#3f7f59; '&gt;// поэтому переопределяем наименование метода&lt;/span&gt;
&lt;span style='color:#7f0055; '&gt;#&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;define&lt;/span&gt;&lt;span style='color:#7f0055; '&gt; closesocket&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;(&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;s&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;)&lt;/span&gt;&lt;span style='color:#7f0055; '&gt; close&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;(&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;s&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;)&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;;&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;  &lt;/span&gt;
&lt;span style='color:#7f0055; '&gt;#&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;endif&lt;/span&gt;

&lt;span style='color:#7f0055; font-weight:bold; '&gt;int&lt;/span&gt; init_sockaddr_in(&lt;span style='color:#7f0055; font-weight:bold; '&gt;char&lt;/span&gt; *hostname, &lt;span style='color:#7f0055; font-weight:bold; '&gt;struct&lt;/span&gt; sockaddr_in *sin);
&lt;span style='color:#7f0055; font-weight:bold; '&gt;int&lt;/span&gt; client_process(&lt;span style='color:#7f0055; font-weight:bold; '&gt;int&lt;/span&gt; fd, &lt;span style='color:#7f0055; font-weight:bold; '&gt;char&lt;/span&gt; *hostname);
&lt;span style='color:#7f0055; font-weight:bold; '&gt;int&lt;/span&gt; send_request(&lt;span style='color:#7f0055; font-weight:bold; '&gt;int&lt;/span&gt; fd, &lt;span style='color:#7f0055; font-weight:bold; '&gt;char&lt;/span&gt; *hostname);
&lt;span style='color:#7f0055; font-weight:bold; '&gt;int&lt;/span&gt; recv_reply(&lt;span style='color:#7f0055; font-weight:bold; '&gt;int&lt;/span&gt; fd);


&lt;span style='color:#7f0055; font-weight:bold; '&gt;int&lt;/span&gt; &lt;span style='color:#7f0055; font-weight:bold; '&gt;main&lt;/span&gt;()
{
    &lt;span style='color:#7f0055; font-weight:bold; '&gt;struct&lt;/span&gt; sockaddr_in  server;
    SOCKET              sockfd;
    &lt;span style='color:#7f0055; font-weight:bold; '&gt;int&lt;/span&gt;                    recvMsgSize;
    
    &lt;span style='color:#3f7f59; '&gt;// имя сервера, может быть вида "www."""".com" и т.д.&lt;/span&gt;
    &lt;span style='color:#7f0055; font-weight:bold; '&gt;char&lt;/span&gt; * srv =        &lt;span style='color:#2a00ff; '&gt;"&lt;/span&gt;&lt;span style='color:#2a00ff; '&gt;localhost&lt;/span&gt;&lt;span style='color:#2a00ff; '&gt;"&lt;/span&gt;; 

&lt;span style='color:#7f0055; '&gt;#&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;if&lt;/span&gt;&lt;span style='color:#7f0055; '&gt; &lt;/span&gt;&lt;span style='color:#7f0055; '&gt;defined&lt;/span&gt;&lt;span style='color:#7f0055; '&gt; WIN32&lt;/span&gt;
    &lt;span style='color:#3f7f59; '&gt;// для Windows мы должны инициализировать Winsock&lt;/span&gt;
    WSADATA wsa_data;
    &lt;span style='color:#7f0055; font-weight:bold; '&gt;WSAStartup&lt;/span&gt;(&lt;span style='color:#7f0055; font-weight:bold; '&gt;MAKEWORD&lt;/span&gt;(1,1), &amp;amp;wsa_data);
&lt;span style='color:#7f0055; '&gt;#&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;endif&lt;/span&gt;

    &lt;span style='color:#3f7f59; '&gt;// создаем сокет&lt;/span&gt;
    sockfd = &lt;span style='color:#7f0055; font-weight:bold; '&gt;socket&lt;/span&gt;(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    &lt;span style='color:#7f0055; font-weight:bold; '&gt;if&lt;/span&gt;(sockfd == INVALID_SOCKET) {
        perror(&lt;span style='color:#2a00ff; '&gt;"&lt;/span&gt;&lt;span style='color:#2a00ff; '&gt;Could not create socket.&lt;/span&gt;&lt;span style='color:#2a00ff; '&gt;\n&lt;/span&gt;&lt;span style='color:#2a00ff; '&gt;"&lt;/span&gt;);
        &lt;span style='color:#7f0055; font-weight:bold; '&gt;return&lt;/span&gt;(SOCKET_ERROR);
    }

    &lt;span style='color:#3f7f59; '&gt;// пробуем создать метаданные сервера&lt;/span&gt;
    recvMsgSize = init_sockaddr_in(srv, &amp;amp;server);
    &lt;span style='color:#7f0055; font-weight:bold; '&gt;if&lt;/span&gt;(recvMsgSize &amp;lt; 0)
    {
        perror(&lt;span style='color:#2a00ff; '&gt;"&lt;/span&gt;&lt;span style='color:#2a00ff; '&gt;Could not initialize address.&lt;/span&gt;&lt;span style='color:#2a00ff; '&gt;\n&lt;/span&gt;&lt;span style='color:#2a00ff; '&gt;"&lt;/span&gt; );
        &lt;span style='color:#7f0055; font-weight:bold; '&gt;return&lt;/span&gt;(SOCKET_ERROR);
    }
    
    &lt;span style='color:#3f7f59; '&gt;// пытаемся соединиться через сокет&lt;/span&gt;
    recvMsgSize = &lt;span style='color:#7f0055; font-weight:bold; '&gt;connect&lt;/span&gt;(sockfd, (&lt;span style='color:#7f0055; font-weight:bold; '&gt;struct&lt;/span&gt; &lt;span style='color:#7f0055; font-weight:bold; '&gt;sockaddr&lt;/span&gt;*)&amp;amp;server, &lt;span style='color:#7f0055; font-weight:bold; '&gt;sizeof&lt;/span&gt;(server));
    &lt;span style='color:#7f0055; font-weight:bold; '&gt;if&lt;/span&gt;(recvMsgSize &amp;lt; 0)
    {
        perror(&lt;span style='color:#2a00ff; '&gt;"&lt;/span&gt;&lt;span style='color:#2a00ff; '&gt;Error while connecting to server.&lt;/span&gt;&lt;span style='color:#2a00ff; '&gt;\n&lt;/span&gt;&lt;span style='color:#2a00ff; '&gt;"&lt;/span&gt;);
        &lt;span style='color:#7f0055; font-weight:bold; '&gt;return&lt;/span&gt;(SOCKET_ERROR);
    }
    
    &lt;span style='color:#3f7f59; '&gt;// посылаем сообщения на сервер и принимаем респонс&lt;/span&gt;
    recvMsgSize = client_process(sockfd, srv);
    
    printf(&lt;span style='color:#2a00ff; '&gt;"&lt;/span&gt;&lt;span style='color:#2a00ff; '&gt;Program has ended successfully.&lt;/span&gt;&lt;span style='color:#2a00ff; '&gt;"&lt;/span&gt;);
    
&lt;span style='color:#7f0055; '&gt;#&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;if&lt;/span&gt;&lt;span style='color:#7f0055; '&gt; &lt;/span&gt;&lt;span style='color:#7f0055; '&gt;defined&lt;/span&gt;&lt;span style='color:#7f0055; '&gt; WIN32&lt;/span&gt;
    &lt;span style='color:#3f7f59; '&gt;// для Windows мы должны явно указать, что завершаем работу Winsock&lt;/span&gt;
    &lt;span style='color:#7f0055; font-weight:bold; '&gt;WSACleanup&lt;/span&gt;();
&lt;span style='color:#7f0055; '&gt;#&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;endif&lt;/span&gt;
    
    &lt;span style='color:#7f0055; font-weight:bold; '&gt;return&lt;/span&gt; 0;
}

&lt;span style='color:#7f0055; font-weight:bold; '&gt;int&lt;/span&gt; init_sockaddr_in(&lt;span style='color:#7f0055; font-weight:bold; '&gt;char&lt;/span&gt; *hostname, &lt;span style='color:#7f0055; font-weight:bold; '&gt;struct&lt;/span&gt; sockaddr_in *sin)
{
    &lt;span style='color:#7f0055; font-weight:bold; '&gt;struct&lt;/span&gt; servent *serv;

    &lt;span style='color:#3f7f59; '&gt;// утсанавливаем поинтер в памяти&lt;/span&gt;
    memset(sin, 0, &lt;span style='color:#7f0055; font-weight:bold; '&gt;sizeof&lt;/span&gt;(*sin));
    sin-&gt;sin_family = AF_INET;

    &lt;span style='color:#3f7f59; '&gt;// проверяем, в каком виде записан адрес сервера: IP или "&lt;/span&gt;&lt;span style='color:#3f3fbf; '&gt;www.****.com&lt;/span&gt;&lt;span style='color:#3f7f59; '&gt;"&lt;/span&gt;
&lt;span style='color:#7f0055; '&gt;#&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;if&lt;/span&gt;&lt;span style='color:#7f0055; '&gt; &lt;/span&gt;&lt;span style='color:#7f0055; '&gt;defined&lt;/span&gt;&lt;span style='color:#7f0055; '&gt; LINUX&lt;/span&gt;
    &lt;span style='color:#7f0055; font-weight:bold; '&gt;if&lt;/span&gt;( !inet_aton( hostname, &amp;amp;sin-&gt;sin_addr ) )
&lt;span style='color:#7f0055; '&gt;#&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;endif&lt;/span&gt;
    {
        &lt;span style='color:#3f7f59; '&gt;// если запись в виде "&lt;/span&gt;&lt;span style='color:#3f3fbf; '&gt;www.****.com&lt;/span&gt;&lt;span style='color:#3f7f59; '&gt;", ищем IP адрес&lt;/span&gt;
        &lt;span style='color:#7f0055; font-weight:bold; '&gt;struct&lt;/span&gt; &lt;span style='color:#7f0055; font-weight:bold; '&gt;hostent&lt;/span&gt; *host = &lt;span style='color:#7f0055; font-weight:bold; '&gt;gethostbyname&lt;/span&gt;(hostname);
        &lt;span style='color:#7f0055; font-weight:bold; '&gt;if&lt;/span&gt;(!host)
            &lt;span style='color:#7f0055; font-weight:bold; '&gt;return&lt;/span&gt; SOCKET_ERROR;

        sin-&gt;sin_addr.s_addr = *(&lt;span style='color:#7f0055; font-weight:bold; '&gt;unsigned&lt;/span&gt; &lt;span style='color:#7f0055; font-weight:bold; '&gt;long&lt;/span&gt;*)host-&gt;h_addr_list[0];
    }

    &lt;span style='color:#3f7f59; '&gt;// получаем дефолтный порт для выбранного протокола&lt;/span&gt;
    serv = &lt;span style='color:#7f0055; font-weight:bold; '&gt;getservbyname&lt;/span&gt;(&lt;span style='color:#2a00ff; '&gt;"&lt;/span&gt;&lt;span style='color:#2a00ff; '&gt;http&lt;/span&gt;&lt;span style='color:#2a00ff; '&gt;"&lt;/span&gt;, &lt;span style='color:#2a00ff; '&gt;"&lt;/span&gt;&lt;span style='color:#2a00ff; '&gt;tcp&lt;/span&gt;&lt;span style='color:#2a00ff; '&gt;"&lt;/span&gt;);
    &lt;span style='color:#7f0055; font-weight:bold; '&gt;if&lt;/span&gt;(!serv)
        &lt;span style='color:#7f0055; font-weight:bold; '&gt;return&lt;/span&gt; SOCKET_ERROR;

    sin-&gt;sin_port = serv-&gt;s_port;

    &lt;span style='color:#7f0055; font-weight:bold; '&gt;return&lt;/span&gt; EXIT_SUCCESS;
}

&lt;span style='color:#7f0055; font-weight:bold; '&gt;int&lt;/span&gt; client_process(&lt;span style='color:#7f0055; font-weight:bold; '&gt;int&lt;/span&gt; socketId, &lt;span style='color:#7f0055; font-weight:bold; '&gt;char&lt;/span&gt; *hostname)
{
    &lt;span style='color:#3f7f59; '&gt;// посылаем данные    &lt;/span&gt;
    printf(&lt;span style='color:#2a00ff; '&gt;"&lt;/span&gt;&lt;span style='color:#2a00ff; '&gt;Sending...&lt;/span&gt;&lt;span style='color:#2a00ff; '&gt;\n&lt;/span&gt;&lt;span style='color:#2a00ff; '&gt;"&lt;/span&gt;);
    &lt;span style='color:#7f0055; font-weight:bold; '&gt;if&lt;/span&gt;(send_request(socketId, hostname))
    {
        &lt;span style='color:#3f7f59; '&gt;// неудачно скастовали заклинание&lt;/span&gt;
        &lt;span style='color:#7f0055; font-weight:bold; '&gt;return&lt;/span&gt; SOCKET_ERROR;
    }
    
    &lt;span style='color:#3f7f59; '&gt;// получаем ответ от сервера&lt;/span&gt;
    printf(&lt;span style='color:#2a00ff; '&gt;"&lt;/span&gt;&lt;span style='color:#2a00ff; '&gt;Receiving reply...&lt;/span&gt;&lt;span style='color:#2a00ff; '&gt;\n&lt;/span&gt;&lt;span style='color:#2a00ff; '&gt;"&lt;/span&gt;);
    &lt;span style='color:#7f0055; font-weight:bold; '&gt;if&lt;/span&gt;(recv_reply(socketId))
    {
        &lt;span style='color:#3f7f59; '&gt;// ошибка магии&lt;/span&gt;
        &lt;span style='color:#7f0055; font-weight:bold; '&gt;return&lt;/span&gt; SOCKET_ERROR;
    }
    &lt;span style='color:#7f0055; font-weight:bold; '&gt;return&lt;/span&gt; EXIT_SUCCESS;
}

&lt;span style='color:#7f0055; font-weight:bold; '&gt;int&lt;/span&gt; send_request(&lt;span style='color:#7f0055; font-weight:bold; '&gt;int&lt;/span&gt; fd, &lt;span style='color:#7f0055; font-weight:bold; '&gt;char&lt;/span&gt; *hostname)
{
    &lt;span style='color:#3f7f59; '&gt;// здесь мы должны сформировать запрос к серверу&lt;/span&gt;
    &lt;span style='color:#3f7f59; '&gt;// запрос должен содержать стандартные заголовки и константы&lt;/span&gt;
    &lt;span style='color:#3f7f59; '&gt;// типа таких: "GET /foo/bar/baz/ HTTP/1.1\r\nHost: &lt;/span&gt;&lt;span style='color:#3f3fbf; '&gt;www.myfoo.com&lt;/span&gt;&lt;span style='color:#3f7f59; '&gt; Connection: close"&lt;/span&gt;
    &lt;span style='color:#3f7f59; '&gt;// &lt;/span&gt;
    &lt;span style='color:#7f0055; font-weight:bold; '&gt;char&lt;/span&gt; format[150] = &lt;span style='color:#2a00ff; '&gt;"&lt;/span&gt;&lt;span style='color:#2a00ff; '&gt;GET /foo/bar/baz/ HTTP/1.1&lt;/span&gt;&lt;span style='color:#2a00ff; '&gt;\r&lt;/span&gt;&lt;span style='color:#2a00ff; '&gt;\n&lt;/span&gt;&lt;span style='color:#2a00ff; '&gt;Host: &lt;/span&gt;&lt;span style='color:#2a00ff; '&gt;"&lt;/span&gt;;
    &lt;span style='color:#7f0055; font-weight:bold; '&gt;int&lt;/span&gt; length = 0;
    &lt;span style='color:#7f0055; font-weight:bold; '&gt;int&lt;/span&gt; ret = 0;

    strcat(format, hostname);
    strcat(format, &lt;span style='color:#2a00ff; '&gt;"&lt;/span&gt;&lt;span style='color:#2a00ff; '&gt;\r&lt;/span&gt;&lt;span style='color:#2a00ff; '&gt;\n&lt;/span&gt;&lt;span style='color:#2a00ff; '&gt;Connection: close&lt;/span&gt;&lt;span style='color:#2a00ff; '&gt;\r&lt;/span&gt;&lt;span style='color:#2a00ff; '&gt;\n&lt;/span&gt;&lt;span style='color:#2a00ff; '&gt;\r&lt;/span&gt;&lt;span style='color:#2a00ff; '&gt;\n&lt;/span&gt;&lt;span style='color:#2a00ff; '&gt;"&lt;/span&gt;);

    length = strlen(format);

    &lt;span style='color:#3f7f59; '&gt;// посылаем запрос format длиной length через сокет fd  &lt;/span&gt;
    ret = &lt;span style='color:#7f0055; font-weight:bold; '&gt;send&lt;/span&gt;(fd, format, length, 0);
    &lt;span style='color:#7f0055; font-weight:bold; '&gt;if&lt;/span&gt;(ret != length )
        &lt;span style='color:#7f0055; font-weight:bold; '&gt;return&lt;/span&gt; SOCKET_ERROR;

    &lt;span style='color:#7f0055; font-weight:bold; '&gt;return&lt;/span&gt; EXIT_SUCCESS;
}

&lt;span style='color:#7f0055; font-weight:bold; '&gt;int&lt;/span&gt; recv_reply(&lt;span style='color:#7f0055; font-weight:bold; '&gt;int&lt;/span&gt; fd)
{
    &lt;span style='color:#7f0055; font-weight:bold; '&gt;fd_set&lt;/span&gt; readfds;
    
    &lt;span style='color:#3f7f59; '&gt;// определяем буффер для входящих данных&lt;/span&gt;
    &lt;span style='color:#7f0055; font-weight:bold; '&gt;char&lt;/span&gt; buf[256];
    &lt;span style='color:#7f0055; font-weight:bold; '&gt;int&lt;/span&gt; length;

    &lt;span style='color:#7f0055; font-weight:bold; '&gt;while&lt;/span&gt;(1)
    {
        &lt;span style='color:#3f7f59; '&gt;// инициализируем буффер&lt;/span&gt;
        FD_ZERO(&amp;amp;readfds);
        FD_SET(fd, &amp;amp;readfds);
        memset(buf, 0, &lt;span style='color:#7f0055; font-weight:bold; '&gt;sizeof&lt;/span&gt;(buf));

        &lt;span style='color:#3f7f59; '&gt;// ждем прибытия данных с сервера&lt;/span&gt;
        &lt;span style='color:#7f0055; font-weight:bold; '&gt;if&lt;/span&gt;(&lt;span style='color:#7f0055; font-weight:bold; '&gt;select&lt;/span&gt;(fd+1, &amp;amp;readfds, &lt;span style='color:#7f0055; font-weight:bold; '&gt;NULL&lt;/span&gt;, &lt;span style='color:#7f0055; font-weight:bold; '&gt;NULL&lt;/span&gt;, &lt;span style='color:#7f0055; font-weight:bold; '&gt;NULL&lt;/span&gt;) &amp;lt; 0 )
        {
            &lt;span style='color:#3f7f59; '&gt;// ошибочка в заклинании&lt;/span&gt;
            &lt;span style='color:#7f0055; font-weight:bold; '&gt;return&lt;/span&gt; SOCKET_ERROR;
        }
        
        &lt;span style='color:#3f7f59; '&gt;// проверяем, если ли в дескрипторе переданные данные&lt;/span&gt;
        &lt;span style='color:#7f0055; font-weight:bold; '&gt;if&lt;/span&gt;(FD_ISSET(fd, &amp;amp;readfds))
        {
            &lt;span style='color:#3f7f59; '&gt;// получаем их&lt;/span&gt;
            length = &lt;span style='color:#7f0055; font-weight:bold; '&gt;recv&lt;/span&gt;(fd, buf, &lt;span style='color:#7f0055; font-weight:bold; '&gt;sizeof&lt;/span&gt;(buf)-1, 0);
            &lt;span style='color:#7f0055; font-weight:bold; '&gt;if&lt;/span&gt;(length &amp;lt; 0)
                &lt;span style='color:#7f0055; font-weight:bold; '&gt;return&lt;/span&gt; SOCKET_ERROR;
            &lt;span style='color:#7f0055; font-weight:bold; '&gt;else&lt;/span&gt; &lt;span style='color:#7f0055; font-weight:bold; '&gt;if&lt;/span&gt;(length == 0)    &lt;span style='color:#3f7f59; '&gt;// данные закончились&lt;/span&gt;
                &lt;span style='color:#7f0055; font-weight:bold; '&gt;break&lt;/span&gt;;
            
            &lt;span style='color:#3f7f59; '&gt;// вываливаем полученный буфер куда хотим&lt;/span&gt;
            printf(&lt;span style='color:#2a00ff; '&gt;"&lt;/span&gt;&lt;span style='color:#2a00ff; '&gt;%s&lt;/span&gt;&lt;span style='color:#2a00ff; '&gt;\n&lt;/span&gt;&lt;span style='color:#2a00ff; '&gt;"&lt;/span&gt;, (&lt;span style='color:#7f0055; font-weight:bold; '&gt;char&lt;/span&gt;*)buf);
        }
    }
    &lt;span style='color:#7f0055; font-weight:bold; '&gt;return&lt;/span&gt; EXIT_SUCCESS;
}
&lt;/pre&gt;&lt;br /&gt;
&lt;br /&gt;
Немного примечаний к волшебству.&lt;br /&gt;
&lt;br /&gt;
Отношения с сокетами на этом уровне примерно одинаковые в Linux и в Windows. Я по долгу работы и в силу личных предпочтений пишу код в Windows (и чтобы не запусать лишний раз ресурсоемкий билд). Для этого в коде введен переключатель для определения условия компиляции. При отсутствии необходимости в нем, его легко можно удалить и компилироваться исключительно под выбранную ОС.</description></item><item><title>Измерение заряда батареи</title><link>http://sigidin.blogspot.com/2011/01/blog-post.html</link><category>android</category><author>noreply@blogger.com (Anonymous)</author><pubDate>Wed, 19 Jan 2011 22:39:00 +0900</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-7864970685809107300.post-9126809320511186318</guid><description>Иногда перед каким-нибудь долгим, но важным процессом может понадобиться узнать уровень заряда батареи. Это бывает полезно, к примеру, когда пользователь собирается загрузить на девайс объемное обновление, и мы не хотим, чтобы этот завораживающий процесс прервался.&lt;br /&gt;
&lt;br /&gt;
Для этой магии существует простое заклинание. В той Activity, где будет происходить длительный процесс, который лучше не прерывать, вставляем проверку:&lt;br /&gt;
&lt;br /&gt;
&lt;pre style="background: #FAF2EF; color: black;"&gt;&lt;span style="color: #7f0055; font-weight: bold;"&gt;private&lt;/span&gt; int checkBatteryLow(){
        BroadcastReceiver wIntentReceiver = &lt;span style="color: #7f0055; font-weight: bold;"&gt;new&lt;/span&gt; BroadcastReceiver() {
            @Override
            &lt;span style="color: #7f0055; font-weight: bold;"&gt;public&lt;/span&gt; &lt;span style="color: #7f0055; font-weight: bold;"&gt;void&lt;/span&gt; onReceive(Context context, Intent intent) {
                &lt;span style="color: #3f7f59;"&gt;// Получаем сообщение от девайса&lt;/span&gt;
                &lt;span style="color: #7f0055; font-weight: bold;"&gt;String&lt;/span&gt; wAction = intent.getAction();
                &lt;span style="color: #7f0055; font-weight: bold;"&gt;if&lt;/span&gt;(wAction.equals(Intent.ACTION_BATTERY_CHANGED))
                {
                    &lt;span style="color: #3f7f59;"&gt;// Здесь можно информировать пользователя об изменении
                    // заряда батареи&lt;/span&gt;
                }
                &lt;span style="color: #7f0055; font-weight: bold;"&gt;else&lt;/span&gt; &lt;span style="color: #7f0055; font-weight: bold;"&gt;if&lt;/span&gt;(wAction.equals(Intent.ACTION_BATTERY_LOW))
                {
                    &lt;span style="color: #3f7f59;"&gt;// Здесь можно информаровать пользователя о низком
                    // заряде батареи&lt;/span&gt;
                }
            }
        };

        &lt;span style="color: #3f7f59;"&gt;// Создаем фильтры&lt;/span&gt;
        IntentFilter filter = &lt;span style="color: #7f0055; font-weight: bold;"&gt;new&lt;/span&gt; IntentFilter();
        filter.addAction(Intent.ACTION_BATTERY_CHANGED);
        filter.addAction(Intent.ACTION_BATTERY_LOW);

        &lt;span style="color: #3f7f59;"&gt;// Подключаем получателя сообщений от девайса с установленными фильтрами&lt;/span&gt;
        Intent intent = &lt;span style="color: #7f0055; font-weight: bold;"&gt;this&lt;/span&gt;.registerReceiver(wIntentReceiver, filter);
        
        &lt;span style="color: #3f7f59;"&gt;// Получем значение "level" из данных о заряде батареи&lt;/span&gt;
        &lt;span style="color: #7f0055; font-weight: bold;"&gt;Object&lt;/span&gt; l = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, -1);
        &lt;span style="color: #7f0055; font-weight: bold;"&gt;Object&lt;/span&gt; s = intent.getIntExtra(BatteryManager.EXTRA_SCALE, -1);
        &lt;span style="color: #7f0055; font-weight: bold;"&gt;int&lt;/span&gt; level = (&lt;span style="color: #7f0055; font-weight: bold;"&gt;Integer&lt;/span&gt;)l;
        &lt;span style="color: #7f0055; font-weight: bold;"&gt;int&lt;/span&gt; scale = (&lt;span style="color: #7f0055; font-weight: bold;"&gt;Integer&lt;/span&gt;)s;
        
        &lt;span style="color: #7f0055; font-weight: bold;"&gt;if&lt;/span&gt; (level &amp;gt;= 0 &amp;amp;&amp;amp; scale &amp;gt; 0) {
            level = (level * 100) / scale;
        }
        
        &lt;span style="color: #3f7f59;"&gt;// Отключаем получателя&lt;/span&gt;
        unregisterReceiver(wIntentReceiver);
        &lt;span style="color: #7f0055; font-weight: bold;"&gt;return&lt;/span&gt; level;
    }
&lt;/pre&gt;&lt;br /&gt;
&lt;br /&gt;
После этого в нужном месте вызываем проверку и получаем из нее число, показывающее текущий заряд батареи (от 0 до 100). Это значение проверяем с надуманным пороговым значением и по езультатам проверки принимаем решение, запускать ли длительный процесс в приложении или заставить пользователя зарядить девайс.</description></item></channel></rss>