Как при создании меню установить иконку из интернета?

117
14 декабря 2020, 05:50

изучаю Android (Java). Необходимо создать меню программно с иконками. Я посылаю запрос на сервер и мне сервер отдает Json строку, я в Java ее конвертирую в объект и работаю с ним. Картинка передается в виде URL ссылки на файл. Задача такая, создать меню из этого объекта вместе с иконками. Сами меню создать не проблема, проблема в том что иконки не подставляются.

Привожу укороченный код

package com.example.app;
public class MainActivity extends AppCompatActivity implements OnNavigationItemSelectedListener, AsyncInternetTasks.MainInterfaceFunctions {
    TextView testTextStatus;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Toolbar toolbar = findViewById(R.id.toolbar);
        toolbar.setTitle(R.string.empty_text);
        setSupportActionBar(toolbar);

        // Менюшка
        NavigationView navigationView = findViewById(R.id.nav_view);
        navigationView.setNavigationItemSelectedListener(this);
         testTextStatus =  findViewById(R.id.textView);
        DrawerLayout drawer = findViewById(R.id.drawer_layout);
        ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
                this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
        drawer.addDrawerListener(toggle);
        toggle.syncState();

    }
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Нет иконки
        menu.add(R.id.main_group, 1, 5, "Тест1")
                .setIcon(Drawable.createFromPath("http://www.test.ru/images/test_icon1.jpg"))
                .setCheckable(true);
        // Иконки нет
         menu.add(R.id.main_group, 1, 5, "Тест2")
                .setIcon(Drawable.createFromPath("http://www.test.ru/images/test_icon2.png"))
                .setCheckable(true);
        // Нет иконки
       menu.add(R.id.main_group, 1, 5, "Тест3")
                    .setIcon(Drawable.createFromPath(getTempFile(getApplicationContext(), "http://www.test.ru/images/test_icon2.png"))).setCheckable(true);
        // тут NULL
        Log.d("myTag1", String.valueOf(Drawable.createFromPath(getTempFile(getApplicationContext(), "http://www.test.ru/images/test_icon2.png"))));
        return super.onCreateOptionsMenu(menu);
    }
    private String getTempFile(Context context, String url) {
        File file = null;
        try {
            String fileName = Uri.parse(url).getLastPathSegment();
            file = File.createTempFile(fileName, null, context.getCacheDir());
        } catch (IOException e) {
            // Error while creating file
        }
        // файлы также есть
        Log.d("myTag1", file.getPath());
        return file.getPath();
    }
}

Подскажите пожалуйста, что не так я делаю. Спасибо!

Answer 1

Drawable.createFromPath - метод принимает путь к локальному файлу, а не сетевой адрес.
И, поскольку, сетевые вызовы в главном потоке запрещены - то загрузить их прямо в onCreateOptionsMenu не выйдет.
Самым разумным вариантом будет предварительная загрузка нужных картинок в локальный кэш или (если они легковесные) сразу в память.

Answer 2

Valeriy, спасибо за совет по Glide, классная библиотека - она мне пригодится.

Woesss, спасибо за подсказку, я понял что не так было в моем коде и почему возвращался null

// тут NULL
    Log.d("myTag1", String.valueOf(Drawable.createFromPath(getTempFile(getApplicationContext(), "http://www.test.ru/images/test_icon2.png"))));

я создавал пустой файл (как оказалась) в методе getTempFile, собственно поэтому иконка в менюшку не подставлялась.

Завел для этого отдельный класс. Он сохраняет в кеше и возвращает путь к изображению (я вот сейчас думаю в этом же классе реализовать сохранение пути к файлам в БД или вынести в отдельный класс? И стоило ли реализовывать это отдельным классом).

Ниже приведу код класса, если что - то не так - подскажите пожалуйста что можно улучшить.

package com.example.app.helpers;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.AsyncTask;
import android.util.Log;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
public class AsyncFilesTasks extends AsyncTask<Void, Void, String> {
    private MainInterfaceFunctions callback;
    private String folder, urlFilePath;
    private Context context;
    public AsyncFilesTasks(final MainInterfaceFunctions callback, Context context, String folder, String urlFilePath){
        this.callback = callback;
        this.context = context;
        this.folder = folder;
        this.urlFilePath = urlFilePath;
    }
    public interface MainInterfaceFunctions {
        void afterTasksSaveFileToCashe(String filePatch);
        void beforeTasksSaveFileToCashe();
    }
    @Override
    protected void onPreExecute() {
        super.onPreExecute();
        if (callback != null)
            callback.beforeTasksSaveFileToCashe();
    }
    @Override
    protected String doInBackground(Void... voids) {
        return getTempFile(context, urlFilePath);
    }
    @Override
    public void onPostExecute(String filePatch) {
        super.onPostExecute(filePatch);
        if(callback!=null) {
            callback.afterTasksSaveFileToCashe(filePatch);
        }
    }
    private String getTempFile(Context context, String url_img) {
        File file = null;
        URL url = null;
        try {
            url = new URL(url_img);
        } catch (MalformedURLException e) {
            e.printStackTrace();
        }
        try {
            String fileName = Uri.parse(url_img).getLastPathSegment();
            File folder = new File(context.getCacheDir(), this.folder);
            if (!folder.exists()) {
                if (!folder.mkdir()) {
                    Log.e("myTag1", "Cannot create a directory!");
                } else {
                    folder.mkdirs();
                }
            }
            file = File.createTempFile(fileName, null, folder);
            Bitmap bitmap;
            if (url != null) {
                bitmap = BitmapFactory.decodeStream(url.openStream());
                bitmap.compress(Bitmap.CompressFormat.PNG, 100, new FileOutputStream(file));
            }
        } catch (IOException e) {
            // Error while creating file
        }
        return file.getPath();
    }
}

вызывать вот так

AsyncFilesTasks AFT = new AsyncFilesTasks(this, getApplicationContext(), "/menu_icons/", "http://www.test.ru/local/images/test.png");
AFT.execute();

// в классе где выполняется объект класса AsyncFilesTasks необходимо переопределить эти методы, так как они будут вызваны до сохранения картинки и после сохранения
@Override
public void beforeTasksSaveFileToCashe() {
}
@Override
public void afterTasksSaveFileToCashe(String filePatch) {
    Log.d("myTag1", filePatch);
}
READ ALSO
Как найти элементы массива по индексу из другого массива и вывести обновлённый список во Vue

Как найти элементы массива по индексу из другого массива и вывести обновлённый список во Vue

Делаю фильтр по нажатию на кнопку должно найти у item категорию которая совпадает с категорией на кнопку, эти элементы оставить а остальные...

112
Передача значение input на другую страничку

Передача значение input на другую страничку

У меня есть две странички takenamehtml и givename

87
пользовательский статус на сайте nodejs

пользовательский статус на сайте nodejs

задача состоит в том чтоб, создать кнопку onlineточнее когда любой пользователь/гость на сайте смотри любой пост, нужно чтоб статус автора был...

94
Не работает js на моб устройствах

Не работает js на моб устройствах

В браузерах на андроидах не работает выпадающие меню на сайтеJS код:

94