Ответы пользователя по тегу Java
  • Как делать параллельно 1000 https запросов?

    mitaichik
    @mitaichik Автор вопроса
    Ребята, в общем на OkHttp зря грешил - вроде норм держит.
    Мой косяк бы в том что я тело ответа не закрывал.
    Ответ написан
    Комментировать
  • Как правильно отправлять информацию на сервер?

    mitaichik
    @mitaichik
    Я думаю вас вряд-ли инетересует отправка веб-форм.

    Отсылайте данные в формате JSON методом POST (создание) или PUT (изменение). Со стороны Android лучшим решением будет Retrofit. Ну а сервер - на ваш выбор. Большинство фреймворков уже имеют встроенную поддержку REST API - лучше его и заюзать.
    Ответ написан
    3 комментария
  • Как сделать так, чтобы recycler view прокручивался не отдельно, а вместе с элементом перед ним?

    mitaichik
    @mitaichik
    Тебе надо юзать CoordinatorLayout + AppBar + разные типы поведения. Тут все описывать нет смысла - вот пару статей https://habrahabr.ru/post/270121/ https://android.jlelse.eu/scrolling-behavior-for-a...
    Ответ написан
    Комментировать
  • Удаление данных из массива, в чем подвох?

    mitaichik
    @mitaichik
    Смотри: у List есть 2 метода remove:

    boolean remove(Object o);
    E remove(int index);

    Первый удаляет по объекту. Грубо говоря, он ищет в списке передаваемый объект, и если находит - удаляет его.
    Второй удаляет по индексу - то есть удаляет объект с индексом index.

    Обрати внимание на тип параметра: у первого это Object, у второго - скалярный int.

    В ipList.remove(id) ты передаешь переменную типа Integer (который, в свою очередь, наследуется от Object). Таким образом java вызывает первый метод. Он пытается найти этот объект в списке, а его там нет - у тебя же там Ip, и, в итоге, ничего не удаляет.

    Тебе надо приводить твой Integer к int ( с помощью id.intValue() или (int) id). Тогда java вызовет второй метод, который удаляет по индексу.

    Но! Скорее всего, в запросе ты будешь передавать не индекс, а иммено id класса Ip. Поэтому, на самом деле, решение с ipList.removeIf(i -> i.getId().equals(id)); является самым правильным. Ну, или использовать Map, как сказали выше.
    Ответ написан
    1 комментарий
  • OkHTTP как игнорировать SSL сертификат?

    mitaichik
    @mitaichik
    Хз поможет ли, делал временное решения для работы с самоподписанными сертификатами, все ненужное вырезал оставил только суть:
    @Component
    public class ClientFactory
    {
    	@Value("${api.certificate.path}")
    	private String certificatePath;
    
    	@Value("${api.certificate.password}")
    	private String certificatePassword;
    
    	@Value("${api.params.site}")
    	private String paramSite;
    
    	/**
    	 *
    	 * @return
    	 * @throws Throwable
    	 */
    	public OkHttpClient createClient() throws Throwable
    	{
    		return new OkHttpClient.Builder()
    			.socketFactory(createSslContext().getSocketFactory())
    			.build();
    	}
    
    	/**
    	 *
    	 * @return
    	 * @throws Throwable
    	 */
    	private SSLContext createSslContext() throws Throwable
    	{
    		KeyStore ks = getCertificateKeyStore();
    
    		KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
    		kmf.init(ks, certificatePassword.toCharArray());
    
    		SSLContext sslContext = SSLContext.getInstance("SSL");
    		sslContext.init(kmf.getKeyManagers(), trustAll509(), new java.security.SecureRandom());
    
    		return sslContext;
    
    	}
    
    	/**
    	 * @return
    	 */
    	private TrustManager[] trustAll509()
    	{
    		return new TrustManager[] {
    			new X509TrustManager() {
    				public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {}
    				public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {}
    				public X509Certificate[] getAcceptedIssuers() {return null;}
    			}
    		};
    	}
    }


    Самое главное здесь - подставить в SSLContext свой X509TrustManager, который тупо будет всех пропускать и ничего не проверять.

    Но!!! Это должно быть временным решением для разработки/отладки/тестов. Если вы юзаете невалидные сертификаты - что то вы делаете не так.
    Ответ написан
    1 комментарий
  • При написании бэкэнда для андроид почему предпочтение отдает php, а не java?

    mitaichik
    @mitaichik
    PHP программисты дешевле и их легче найти. Это единственная причина. Почему? Потому что порог входа в php ниже.

    В Java порог входа выше, это факт. Но писать бэкенд на Java (когда умееш) не сложнее чем на php, имхо, даже гораздо проще.
    Ответ написан
    Комментировать
  • Как хранить токены Android?

    mitaichik
    @mitaichik
    По заявлению Android хранить в Shared Preferences с private mode безопасно. Небезопасно это на рутованных устройствах, ибо там к файлу Shared Preferences можно получить доступ (без рута андройд не пускает в папку приложения).

    Так что если что-то серьезное - то лучше шифровать. Как шифровать? Я бы сам хотел увидеть ответ профессионала.

    У себя я сделал так: генерирую сессионны ключ AES, беру информацию, шифрую ее на сессионном ключе, результат сохраняю в приватный файл. Далее сессионный ключ шифрую на постоянном ключе RSA и сохраняю результат в файл. Сам же ключ RSA храниться в KeyStore. Почему нужен сессионный ключ? Потому что RSA может шифровать только небольшое кол-во инфы (245 байт вроде на ключе в 2048 бит).

    Получается что инфа зашифрована сессионным ключом, который в свою очередь зашифрован ключе который храниться в KeyStore. Сам же KeyStore, как я понял, является аппаратным хранилищем (по крайней мере в современных устройствах) и доверять ему можно. Доступ к сохраненному ключу доступен только инстансу вашего приложения, да и то не сам ключ, а только возможность им оперировать. То есть просто так спереть инфу, без модификации вашего приложения, не получиться.

    Но сейчас думаю, не сморозил ли я фигню, ибо тот же сессионный AES ключ можно было бы сохранить в KeyStore. Ну и RSA кажется лишним - это же шифрование с открытом ключем. Думал сначала хранить часть ключа на устройстве, часть на сервере с доступом по пинкоду и удалением после пару неправильных вводов, но потом решил что это лишнее...

    В конце концов даже разработчики гос приложений тупо пихают конфинденциальную инфу в приватные файлы и не паряться с шифрованием, и ничего, сертификацию ФСБ проходят.
    Ответ написан
    4 комментария
  • Как в программе сервере на JAVA лучше реализовать многопоточность?

    mitaichik
    @mitaichik
    Юзайте Netty
    Ответ написан
    Комментировать
  • Как обновлять контент своего приложения?

    mitaichik
    @mitaichik
    Рекомендую воспользоваться Firebase от Гугла https://firebase.google.com/docs/database/. На клиентах (в приложении пользователей) она будет обновляться автоматически. А как вам редактировать - можно сделать свою админку для удобства, можно прям на сайте Firebase редактировать свою базу. Так же там можно задать права, кто что может редактировать. Очень удобно, советую.
    Ответ написан
    Комментировать
  • Как правильно организовать работу с сокетами?

    mitaichik
    @mitaichik Автор вопроса
    В общем, потестировал я ServerSocket со своими параметрами (посылал 100 байт текста, выводил его в консоль, отдавал 4Кб). На рабочем компе получилось что такой вариант способен обработать ~ 70 тыс запросов в секунду. С учетом того, что сервер куда более мощьный чем рабочий комп, этот результат более чем удовлетворителен.
    Ответ написан
    Комментировать
  • Одна Activity и множество Fragment, best practices?

    mitaichik
    @mitaichik
    Ого!! 4000 строк - тут явно что то не то. Вам срочно нужно разбивать. Логика UI должна быть во фрагментах, классах вьюх, адаптерах и пр.. В хостовой активити у вас должна быть логика смены фрагментов (хотя тут можно тоже выделить отдельные классы). Бизнес логику выделяйте в отдельный слой. 4000 строк - это ужас!
    Ответ написан
    Комментировать
  • Как взять имя файла из БД и сопоставить его файлу в drawable?

    mitaichik
    @mitaichik
    https://developer.android.com/reference/android/co..., java.lang.String, java.lang.String)

    Но на всякий случай спрошу: Вы уверенны что это правильный подход?
    Ответ написан
  • Android HttpURLConnection подгружается только часть ответа на запрос, как загрузить весь?

    mitaichik
    @mitaichik
    Используйте okhttp/retrofit
    Ответ написан
    Комментировать
  • Как использовать gradle модуль как библиотеку в других модулях?

    mitaichik
    @mitaichik
    В settings.gradle вы должны описать где находится ваша библиотека:

    rootProject.name = 'api'
    include ':requester'
    project(':requester').projectDir = new File(settingsDir, '../requester')

    Здесь api - основной модуль, requester - библиотека.
    В build.gradle нужно указать его как зависимость:

    dependencies {
    compile project(':requester')
    }
    Ответ написан
    1 комментарий
  • Что такое "call back interface"?

    Комментировать
  • Первый проект на java. Как решить NetworkOnMainThreadException?

    mitaichik
    @mitaichik
    Ява многопоточная, у приложения есть главный поток (отрисовывает UI например) и чтоб его всякие запросы в инет не блокировали, андройд запрещает делать их в главном потоке. Соответсвенно, вам нужно запустить интернет-запрос в отдельном потоке.

    Мой совет - юзайте библиотеки которые делют запросы за вас: okhttp / retrofit
    Ответ написан
    Комментировать
  • Код ревью или что не так с моим тестовым заданием?

    mitaichik
    @mitaichik
    Сам в андройде не профессионал, скорее любитель, но свои 5 копеек вставлю:

    private static Context mContext;
    
        @Override
        public void onCreate() {
            super.onCreate();
            mContext = this;
        }


    Хз почему так, но это считается не камильфо. Сам так юзаю, и не одного краш-дампа не словил, но в android-сообществе это не приветствуется (надеюсь в комментах кто-то опишет почему). Принято передавать контекст.

    В MainActivity методы для работ с меню можно было удалить, ибо, судя по всему они нигде не юзаются (и видимо остались от типового шаблона).

    В RestClient идет присвоение в статическю переменную.

    private static RestClient instance;

    Я так понимаю ты делал синглтон. Хз приемлемо ли это в андройде, но я б сделал его как компонент приложения. В идеале вся эта фигня должна создаваться через DI (по карйней мере в бэкенд-разработке DI везде используется). Для андройда это библиотека Dagger 2 (сам еще не юзал, но выглядит многообещающе).

    Плюс там же:

    public static RestAPI get() {
            if(instance == null) instance = new RestClient();
            return instance.restAPI;
        }


    Этот метод по хорошему должен быть помечен как synchronized: если туда зайдут одновременно 2 потока, то может получиться что создадутся 2 RestClient'a. Тут конечно побоку - это вряд-ли что то сломает, но в крупных приложениях это ого-го какие проблемы создаст (я опять таки про бэкенд, ибо я больше по нему).

    Хранить во так параметры аутентификации - тоже не есть хорошо, но это тестовое задание, так что побоку.

    Теперь по фрагментам:

    list = (RecyclerView) v.findViewById(R.id.list);

    Ты присваиваешь свойствам фрагмента вьюхи, в onDestroyView не плохо бы их обнулить. А еще лучше, юзать butterknife.

    Вызов запросов в фрагменте нынче не моден. По хорошему бы сделать какую-нить службу-обертку над retrofit (службу не в смысле андройд службу, а в смысле паттерн), которой ты говоришь загрузи-ка мне данные, и ловишь потом от нее сообщения (в этом тебе поможет otto от square). При показе фрагмента ты запрашиваешь данные и подписываешся на события от сервиса, при скрытии фрагмента - отписываешся.

    В обработке ответов ты проверяешь if (getActivity() == null) return;. Но этим ты проверяешь наличие активити, но не фрагмента, фрагмент может быть уничтожен, или его вьюха может быть уничтожена, или у активити может быть вообще другой фрагмент или еще что. Короче, это все приведет к крэшу.

    onTaskClick: По хорошему, менять фрагменты должна активити, фрагмент списка просто должен сказать "выбран такая-то задача", и вызвать каллбэк активити. А уже активити принять решение что делать дальше. В официальной документации описано как это сделать (механизм каллбэков).

    Реально смутил DetailsTaskFragment: для представления информации о одной задаче ты юзаешь RecyclerView. Имхо, это в корне не правильно. Я понимаю твою мотивацию, почему ты так сделал (экономия память на вьюхах и прочее). Но ты жестко задал структуру и тип отображения. Малейшее изменение требования отображения задачи, и весь этот код под удаление. Ну и инструмент неправильный: RecyclerView - это для списков, для больших списков, а задача - это не список, это сущьность. Если бы ты отказался от этой идеи, и заюзал обычный layout + DataBinding все было бы более удобно, изменяемо, и кода было бы раз в 10 меньше.

    В TaskListAdapter у тебя примешана бизнес-логика, а именно сортировка. По хорошему ты должен делать сортировку в другом месте, например, в службе которая тебе отдает данные, или где то еще, но точно не в UI, которым является адаптер.

    ItemViewHolder - там у тебя обработчик. Хз правильно это или нет, но в примерх гугла обработчик вешается в onBindViewHolder.

    Так же не совсем понимаю (возможно просто задание не читал) метод addAll: почему бы просто не обновить список? Плюс опять это по большой части бизнес-логика. И что странно - не вижу notifyDataSetChanged().

    В общем как-то так.
    Ответ написан
    2 комментария
  • Как правильно связать приложение на Java и Nginx?

    mitaichik
    @mitaichik
    Возможно подойдет https://www.nginx.com/resources/wiki/modules/java_...
    Ответ написан
    Комментировать