Как я боролся с iOS 8.1.3

rouse

Давно я не брал в руки йОС, но давеча мне говорят: «ну-ка, покажи нам на айпаде пару новых идей»! Я говорю: «сей момент»! И показываю.

Читать на сайте автора.

Обезжириваем apk

Что из себя представляет apk файл?

Это просто архив с ресурсами и кодом приложения.

Если, например, картинки и файлы xml ужать серьезно не получится, то вот сам код ужать можно.

Возможно, это потому, как в каждом проекте есть не используемые части библиотек.

Наше IDE  по умолчанию соберёт все, что только есть, и конечный apk получится большим.

Стоить заметить , что в старой виртуальной машине есть ограничение Dalvik 65K methods limit, т.е.вы можете ссылаться на очень большое число методов в DEX файле, но вызывать можете только первые 65536, потому что это вся память, которая у вас есть для инструкции вызова метода, львиную долю которых может съесть одна только Google Play Services.
В недавно в неё включили аналитику, которая до этого была отдельной библиотекой.
Поэтому Google Play Services растет, как на дрожжах.
На помощь нам пришла сама Google, т.к.начиная с версии 6.5 сервисы Google Play могут подключаться в виде нескольких небольших клиентских библиотек.
Нам остается только выбрать необходимые модули, а не таскаться со всей пачкой сервисов.

Весь пакет описанных сервисов подключается в файле build.gralde вот так:

dependencies {
    compile 'com.android.support:appcompat-v7:21.0.3'
    compile 'com.google.android.gms:play-services:+'
}

Библиотеку поддержки appcompat, я не знаю как можно урезать, а вот вторую знаю, мы возьмем только модуль с рекламой (ads) :

dependencies {
    compile 'com.android.support:appcompat-v7:21.0.3'
    compile 'com.google.android.gms:play-services-ads:+'
}

Знак + обозначает, что нужно брать последнюю версию.
Чтобы обрезать не нужный код, так же был придуман инструмент ProGuard.
Как ясно сказано в документации, он может обрезать, оптимизировать и обфусцировать (сделать не читаемым) наш код.
Для его включения нужно выставить в build.gralde свойство minifyEnabled в true и добавить файл proguard-rules.txt в папку app.

 buildTypes {
        release {
            minifyEnabled true
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
        }
    }

В этом файле нужно прописать правила для работы proguard.
Как я понял, достаточно указать в нем классы, упомянутые в манифесте.

-keep public class <MainActivity>

И так мы можем обрезать все с помощью proguard, можем взять библиотеку полегче, а можем сделать и то и другое, а потом посмотреть на полученный apk.

Теперь покажу, что получилось после всех этих манипуляций.

СнимокРазница очевидна, удачного обезжиривания!

 

Читать на сайте автора.

Используем True Type шрифт для хранения иконок

Это сообщение описывает шаги, необходимые для создания Android приложения, которое использует True Type шрифт (Font Awesome), с целью хранения иконок. Использование шрифта для хранения иконок

Читать на сайте автора.

Горячие клавиши в Android Studio

В прошлой статье я уже начал изготовлять из Android Studio нечто похожее на Eclipse. Там был выбрана схема клавиш (Keymap)  как в Eclipse.

Теперь разберёмся, как сделать кучу полезных действий при сохранении.

В Eclipse  есть настройка Save Actions, т.е. при сохранении вы ещё какие-то действия производите с кодом.

Находится она по пути Preferenses-Java-Editor-Save Actions

БезымянныйТут я ставлю форматировать код (Ctrl+Shift+F) и подправить все сторонние пакеты в заголовке (Ctrl+Shift+O).

В общем экономим целых два нажатия горячих клавиш!

Как это удобно — не опишешь словами.Лучше один раз попробовать.

А вот теперь поищем такую настройку в Android Studio и не найдем.

Но голь на выдумку хитра и товарищи предложили переопределить сочетание Ctrl+S  на запуск макроса, который всю эту работу быстренько и проделает!

Макрос можно записать не отходя от кассы: Edit — Macros- StartMacroRecording

— делаем форматирование (Ctrl+Shift+F)

— организуем импорты (Ctrl+Shift+O)

— по вкусу добавить свои действия

Как  сделали, что хотели, сохраняем макрос под свои именем (например formatted save).

Теперь идем File-Settings-Keymap-Macros выделяем наш макрос и жмем правой кнопкой мыши по нему в меню Add Keyboard ShortCut.

БезымянныйIDE скажет, что у нас есть конфликт с другой горячей клавишей, но мы его переопределим.

БезымянныйБезымянныйВот и всё, так можно и в магазине стенку убрать, если постараться)

Читать на сайте автора.

Как хранить числа в объектах TStringList

rouse

Как хранить числа в объектах TStringList прекрасно известно: MyStrings.AddObject( MyString, TObject( MyNumber ) )…казалось бы. Однако, мне (да вот — дошла очередь и до меня) пришлось

Читать на сайте автора.

Как несовершенны константные аргументы

rouse

Я тут попал в такие чудеса на виражах, что уже хотел застрелить компилятор и повеситься на шею кому-нибудь с жилеткой, чтобы рыдать аки дитя малое.

Читать на сайте автора.

Почему системный файловый диалог меняет текущий каталог?

Это перевод Why does the common file dialog change the current directory? Автор: Реймонд Чен.

Когда вы перемещаетесь по папкам в системном диалоге открытия (или сохранения) файлов, то диалог вызывает функцию Set­Current­Directory, передавая ей каталог, в который вы перешли (эй, не заставляйте меня возрождать уголок зануды).

Окей, возможно, вашей первой реакцией будет: «Правда? Я вообще не знал, что он так делает!» Что ж, это ещё одна страница в истории проклятия текущего каталога.

Хорошо, но теперь возникает вопрос: «А зачем диалог это делает?»

Вообще-то, вы уже должны знать ответ на этот вопрос. Многие программы рассчитывают, что текущий каталог совпадает с каталогом открываемого документа.

Но, оказывается, существует способ сказать: «Нет, я — это не такая ламерская программа. Я не делаю предположений о текущем каталоге, я могу работать с любым. Так что не меняй текущий каталог». Вы можете сделать это, передав флаг OFN_NO­CHANGE­DIR (а если ваша программа использует интерфейс IFile­Dialog, то опция NO­CHANGE­DIR включена перманентно — ура Прогрессу!).

Прим.пер.: для Delphi флаг OFN_NO­CHANGE­DIR соответствует значению ofNoChangeDir в TCommonDialog.Options (значение fdoNoChangeDir в TCustomFileDialog.Options всегда игнорируется), а интерфейс IFile­Dialog используется Delphi в «диалогах Vista» (например, TFileOpenDialog), а также в стандартных файловых диалогах — автоматически на Vista+ при условии подключения манифеста (только в новых IDE, конечно же). В последнем случае опция ofNoChangeDir игнорируется.

Но теперь, когда вы знаете про второе проклятие текущего каталога, вы можете использовать его против первого проклятия.

Если вы смогли определить программу, удерживающую открытым каталог, и вы подозреваете, что программа пала жертвой проклятия текущего каталога, то вы можете зайти в эту программу и открыть в ней файловый диалог (например, Файл / Открыть… или Файл / Сохранить как…). В этом диалоге вы меняете папку на, скажем, корень диска или на рабочий стол. А затем закрываете (отменяете) диалог.

Поскольку системный файловый диалог изменяет текущий каталог, то вы, фактически, внедрили вызов Set­Current­Directory прямо в целевой процесс, уводя, таким образом, текущий каталог с каталога, который вы хотите удалить. Заметьте, однако, что этот трюк сработает только если это приложение не передаёт флаг OFN_NO­CHANGE­DIR в вызов Get­Save­File­Name.

Для Проводника вы можете вызвать файловый диалог нажатием Win + R и кнопки «Обзор» — и в версиях Windows вплоть до Windows XP Проводник не передаёт флаг OFN_NO­CHANGE­DIR.

Читать на сайте автора.

Ваш отладочный код может быть уязвимостью в безопасности: подгрузка опциональной отладочной DLL без указания полного пути

Это перевод Your debugging code can be a security vulnerability: Loading optional debugging DLLs without a full path. Автор: Реймонд Чен.

Запомните: плохих парней не заботит, если вы добавили код лишь для целей отладки. Если есть код — они его атакуют.

Посмотрите на такой код:

type
TDocLoadingProc = procedure(Stream: TStream);

var
OnDocLoading: TDocLoadingProc;

procedure LoadDebuggingHooks;
var
hmodDebug: HMODULE;
begin
hmodDebug := LoadLibrary('DebugHooks.dll');
if hmodDebug = 0 then
Exit;
OnDocLoading := GetProcAddress(hmodDebug, 'OnDocLoading');
end;

function LoadDocument({...}): HRESULT;
begin
// ...
if Assigned(OnDocLoading)
// Дадим отладочной ловушке изменить документ перед загрузкой
OnDocLoading(DocStream);
// ...
end;

Если вы хотите отлаживать вашу программу, вы копируете DebugHooks.dll в папку приложения. Код выше ищет эту DLL и загружает её, если она есть. Для примера я включил код одной из возможных ловушек из этой отладочной DLL. Идея примера (и это просто пример, так что давайте не будем обсуждать, хороший ли это пример) состоит в том, что непосредственно перед загрузкой документа мы вызываем функцию OnDocLoading. Эта функция может обернуть переданный ей поток в другой поток, так что содержимое потока можно логгировать при его чтении — в попытке локализовать на чём стопорится загрузка документа. Или её можно использовать для инъекции ошибок ввода-вывода с целью тестирования. В общем, используйте своё воображение.

Но этот отладочный код также содержит уязвимость.

Вспомните, что пути для поиска DLL ищут библиотеки в таком порядке:

  1. Каталог приложения;
  2. Каталог system32;
  3. Каталог system;
  4. Каталог Windows;
  5. Текущий каталог;
  6. Пути из PATH.

Когда вы отлаживаете программу, вы копируете DebugHooks.dll в папку приложения, откуда она и загружается (шаг 1 в списке выше). Но если вы не отлаживаете свою программу, то шаг 1 пропускается, и поиск продолжается дальше. DLL не будет найдена на шаге 2, 3 и 4, и в итоге мы достигаем шага 5: текущего каталога.

И теперь вас хакнули.

Как правило, ваше приложение не имеет прямого контроля над текущим каталогом. Пользователь может запустить вашу программу из любого каталога — и это каталог станет вашим текущим каталогом. И когда вызов LoadLibrary будет искать DLL в текущем каталоге, плохие парни могут положить в него их собственную DLL, ваша программа станет жертвой инъекции кода.

Это особенно опасно, если ваше приложение ассоциировано с каким-то типом файла, поскольку пользователь может запустить вашу программу просто дважды-щёлкнув по файлу, с которым вы ассоциированы.

Когда вы дважды-щёлкаете по файлу, Проводник устанавливает текущий каталог для приложения-обработчика этого файла равным каталогу, в котором расположен этот файл. Это необходимо для правильной работы приложений, которые ищут в текущем каталоге вспомогательные файлы. Например, представьте гипотетическое приложение LitWare Writer, ассоциированное с файлами *.LIT. Документ приложения LitWare Writer, представленный файлом ABC.LIT — это просто представитель семейства файлов: ABC.LIT (главный документ), ABC.LTC (индекс документа и содержание), ABC.LDC (словарь грамматики для документа), ABC.LLT (пользовательский шаблон для документа) и так далее. Когда вы открываете документ C:PROPOSALABC.LIT, LitWare Writer ищет остальные части документа в текущей папке, вместо C:PROPOSAL. Чтобы помочь таким приложениям найти все необходимые файлы, Проводник указывает функции CreateProcess, что текущий каталог для приложения LitWare Writer должен быть равен C:PROPOSAL.

Так, вы можете сказать, что программы вроде этого LitWare Writer (которые ищут файлы в текущей папке вместо папки с главным документом) плохо написаны, и я в этом с вами соглашусь. Однако Windows нужно работать даже с плохо написанными программами (упреждающее ехидное замечание: Windows сама плохо написана). В реальном мире есть слишком много плохо написанных программ, некоторые из которых являются лидерами в своих сегментах (см. выше упреждающий остроумный комментарий), и если Windows перестанет их запускать, люди скажут, что это вина Windows, а не этих программ.

Мне даже не надо закрывать глаза, чтобы представить, как нам присылают баг-отчёт с этим поведением:

«Эта программа отлично работает в MS-DOS, но в Windows она не работает. Тупая Windows».

Клиент не будет счастлив услышать следующий ответ: «Вообще-то, эта программа никогда и не работала верно, ей просто везло все эти X лет. Авторы этой программы никогда не рассматривали случай, если открываемый документ расположен вне текущего каталога. Им это сошло с рук, потому что обычно вы открываете файлы в MS-DOS следующим образом: вы переходите в каталог с документом и потом набираете LWW ABC.LIT. Но если вы выполните в MS-DOS LWW C:PROPOSALABC.LIT, то увидите то же (неверное) поведение программы. Иными словами, это поведение системы — не баг, а дизайн».

Ответ на «Это поведение по проекту» обычно звучит как «Я скажу так, что дизайн, который не даёт мне выполнять мою работу — отстойный дизайн» или кратко: «Нет, это не дизайн, это баг» (вы не верите мне, что такое происходит? Просто почитайте Slashdot).

Итак, чтобы все такие программы продолжили бы работу в Windows, система устанавливает текущий каталог для программы в каталог, содержащий открываемый документ. Это вовсе не чрезмерное и не безрассудное решение — ведь благодаря ему начала работать программа. Не то чтобы запускаемой программе было важно конкретное значение текущего каталога — ведь у неё нет контроля над ним!

Но сказанное также означает, что если вы запустили программу двойным щелчком по ассоциированному документу, то программа будет удерживать каталог с документом — потому что этот каталог будет текущим. Если только, конечно, сама программа потом не изменит свой текущий каталог.

Бонус-замечание: изначально я написал эту серию заметок более двух лет назад. Но даже тогда я не считал их чем-то удивительным, новаторским или интересным. Но, похоже, некоторые люди вновь открыли это несколько месяцев назад, и вылезли из кожи вон, чтобы присвоить себе лавры первооткрывателей. Это как новое поколение подростков, которые думают, что они изобрели секс. Чисто для протокола: вот некоторые официальные инструкции (и, чтобы расставить все точки над i: это официальные инструкции по атаке на текущий каталог, а не официальные инструкции по сексу).

Историческое замечание: почему вообще есть текущий каталог? Ответ: это идёт со времён CP/M. В CP/M не было PATH. Всё запускалось из текущего каталога. Сегодняшнее состояние вещей — это цепочка из обратных совместимостей.

Читать на сайте автора.

Одна из причин, почему ShellExecute возвращает SE_ERR_ACCESSDENIED, а ShellExecuteEx возвращает ERROR_ACCESS_DENIED

Это перевод One possible reason why ShellExecute returns SE_ERR_ACCESSDENIED and ShellExecuteEx returns ERROR_ACCESS_DENIED. Автор: Реймонд Чен.

(этот странный заголовок написан для поисковой оптимизации)

Один клиент сообщил, что при вызове ShellExecute эта функция иногда завершалась с ошибкой SE_ERR_ACCESSDENIED (= 5) — в зависимости от того, что они пытались открыть (а если бы они использовали ShellExecuteEx, то они получали бы ошибку ERROR_ACCESS_DENIED (перевод поста)).

После долгой «игры в пинг-понг», проверки файловых ассоциаций и т.п., один из разработчиков из нашей команды использовал свой хрустальный шар и спросил: «А вы случайно не вызываете её из MTA?» (MTA = multi-threaded apartment, многопоточный апартмент).

«Да», — ответил клиент. — «ShellExecute вызывается из специально выделенного MTA-потока. Проблема в этом?».

Ну, вообще-то, да. И об этом явно сказано в документации к ShellExecute:

Поскольку ShellExecute может делегировать выполнение расширениям Оболочки (источникам данных, обработчикам контекстных меню, реализациям действий), которые активируются через COM, то COM должен быть инициализирован до того, как ваш код вызовет ShellExecute. Некоторые расширения Оболочки требуют, чтобы COM был инициализирован в однопоточном апартменте (STA).

Как правило, функции Оболочки требуют STA. Вспомните, что MTA подразумевает отсутствие интерфейса пользователя. Если вы попытаетесь использовать apartment-threaded объект из MTA-потока, вам потребуется маршаллер, а если такого маршаллера нет, то вызов провалится.

Это также объясняет, почему вызов ShellExecute завершается неудачей только для некоторых типов файлов: если обработка типа файла не требует создания объекта COM, то ситуация с несовпадением MTA/STA никогда не произойдёт.

Читать на сайте автора.

На одну короткую минуту славы DirectX стал более популярным чем другое слово, заканчивающееся на X

Это перевод For a brief shining moment, DirectX was more popular than another word that ends in x. Автор: Реймонд Чен.

В месяц сразу после выхода DirectX 3 слово «directx» стало самым популярным для поиска на microsoft.com. Само по себе, это не было столь удивительным.

Удивительным было слово на шестом месте: «sex».

Вы знаете, это вводит меня в ступор до сих пор. Кто вообще ищет «sex» на microsoft.com? И что, собственно говоря, они ожидают найти?

Читать на сайте автора.