GetLaunchIntentForPackage имеет значение null для некоторых приложений

Я создаю службу, которая отправляет список установленных приложений с Android TV или Fire TV на мобильный телефон. Затем телефон отправляет обратно имя пакета приложения, которое он хочет запустить, и служба запускает его.

Это код, который создает список

public List<InstalledApp> GetInstalledApps(boolean isAndroid) {
    PackageManager pm = getPackageManager();
    List<ApplicationInfo> allPackages = pm.getInstalledApplications(PackageManager.GET_META_DATA);
    List<InstalledApp> userPackages = new ArrayList<InstalledApp>();

    for (ApplicationInfo packageInfo : allPackages) {

        if (isSystemPackage(packageInfo)) continue;

        InstalledApp app = new InstalledApp();
        app.setPackageName(packageInfo.packageName);
        app.setAppName(pm.getApplicationLabel(packageInfo).toString());
        if (!isAndroid) {
            app.setIcon(pm.getApplicationIcon(packageInfo));
        }
        app.setAccentColor(getAccentColor(pm.getApplicationIcon(packageInfo)));


        userPackages.add(app);
    }

    return userPackages;
}

Вот как я запускаю приложения

public void launchApp(String packageName) {
    PackageManager pm = getPackageManager();
    Intent intent = pm.getLaunchIntentForPackage(packageName);
    startActivity(intent);
}

В Fire TV все работает отлично, но на Android-телевизоре намерение для многих приложений всегда равно нулю. Это всего лишь несколько.

  • com.haystack.android
  • com.netflix.ninja
  • tv.pluto.android
  • com.bamnetworks.mlbtv

Однако с тем же кодом эти приложения работают нормально.

  • com.hulu.livingroomplus
  • com.sling
  • com.frogmind.badland
  • com.songza.tv

Может ли кто-нибудь дать представление о том, что я могу сделать неправильно?

Спасибо!

EDIT: Я также пробовал это, и я получаю исключение

android.content.ActivityNotFoundException: не найдено действий для обработки Intent {cat = [android.intent.category.LEANBACK_LAUNCHER] flg = 0x10000000 pkg = com.netflix.ninja}

public void launchApp(String packageName) {
    Intent intent = new Intent();
    intent.setPackage(packageName);
    intent.addCategory("android.intent.category.LEANBACK_LAUNCHER");
    intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    startActivity(intent);
}

ИЗМЕНИТЬ 2:

Это код, который работает для меня:

public void launchApp(String packageName) {
    Intent intent = new Intent();
    intent.setPackage(packageName);

    PackageManager pm = getPackageManager();
    List<ResolveInfo> resolveInfos = pm.queryIntentActivities(intent, 0);
    Collections.sort(resolveInfos, new ResolveInfo.DisplayNameComparator(pm));

    if(resolveInfos.size() > 0) {
        ResolveInfo launchable = resolveInfos.get(0);
        ActivityInfo activity = launchable.activityInfo;
        ComponentName name=new ComponentName(activity.applicationInfo.packageName,
                activity.name);
        Intent i=new Intent(Intent.ACTION_MAIN);

        i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
                Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
        i.setComponent(name);

        startActivity(i);
    }
}

Ответ 1

Чтобы создать панель запуска в стиле главного экрана, не ищите приложения, а затем пытайтесь запустить Intents для каждого. Найдите запускаемые действия, используя queryIntentActivities() на PackageManager.

Например, эта активность (из этот примерный проект) реализует средство запуска в стиле главного экрана, используя эту технику:

/***
  Copyright (c) 2008-2012 CommonsWare, LLC
  Licensed under the Apache License, Version 2.0 (the "License"); you may not
  use this file except in compliance with the License. You may obtain a copy
  of the License at http://www.apache.org/licenses/LICENSE-2.0. Unless required
  by applicable law or agreed to in writing, software distributed under the
  License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS
  OF ANY KIND, either express or implied. See the License for the specific
  language governing permissions and limitations under the License.

  From _The Busy Coder Guide to Android Development_
    http://commonsware.com/Android
*/

package com.commonsware.android.launchalot;

import android.app.ListActivity;
import android.content.ComponentName;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.os.Bundle;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;
import java.util.Collections;
import java.util.List;

public class Launchalot extends ListActivity {
  AppAdapter adapter=null;

  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    PackageManager pm=getPackageManager();
    Intent main=new Intent(Intent.ACTION_MAIN, null);

    main.addCategory(Intent.CATEGORY_LAUNCHER);

    List<ResolveInfo> launchables=pm.queryIntentActivities(main, 0);

    Collections.sort(launchables,
                     new ResolveInfo.DisplayNameComparator(pm)); 

    adapter=new AppAdapter(pm, launchables);
    setListAdapter(adapter);
  }

  @Override
  protected void onListItemClick(ListView l, View v,
                                 int position, long id) {
    ResolveInfo launchable=adapter.getItem(position);
    ActivityInfo activity=launchable.activityInfo;
    ComponentName name=new ComponentName(activity.applicationInfo.packageName,
                                         activity.name);
    Intent i=new Intent(Intent.ACTION_MAIN);

    i.addCategory(Intent.CATEGORY_LAUNCHER);
    i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
                Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
    i.setComponent(name);

    startActivity(i);    
  }

  class AppAdapter extends ArrayAdapter<ResolveInfo> {
    private PackageManager pm=null;

    AppAdapter(PackageManager pm, List<ResolveInfo> apps) {
      super(Launchalot.this, R.layout.row, apps);
      this.pm=pm;
    }

    @Override
    public View getView(int position, View convertView,
                          ViewGroup parent) {
      if (convertView==null) {
        convertView=newView(parent);
      }

      bindView(position, convertView);

      return(convertView);
    }

    private View newView(ViewGroup parent) {
      return(getLayoutInflater().inflate(R.layout.row, parent, false));
    }

    private void bindView(int position, View row) {
      TextView label=(TextView)row.findViewById(R.id.label);

      label.setText(getItem(position).loadLabel(pm));

      ImageView icon=(ImageView)row.findViewById(R.id.icon);

      icon.setImageDrawable(getItem(position).loadIcon(pm));
    }
  }
}

На устройстве Android TV вы также должны искать действия LEANBACK_LAUNCHER, как и то, что использует Android TV, и APK, специфичные для ТВ, могут не иметь регулярной активности LAUNCHER или, в лучшем случае, иметь тот, который не обязательно идеально подходит для использования на телевизоре.

Ответ 2

Я получил ту же ошибку при вызове getLaunchIntentForPackage(packageName). Это было исправлено добавлением этого в тег intent-filter активности запуска в файле манифеста.

<category android:name="android.intent.category.LAUNCHER" />

При создании нового телевизионного приложения в Android Studio оно не имело вышеуказанного значения по умолчанию, вместо этого оно использовалось по умолчанию в теге intent-filter активности запуска в файле манифеста.

<category android:name="android.intent.category.LEANBACK_LAUNCHER" />

Ответ 3

    Intent launchIntent = null;

                try{
                        launchIntent = context.getPackageManager().getLeanbackLaunchIntentForPackage(pkgName);
                    } catch (java.lang.NoSuchMethodError e){
                    }

                    if (launchIntent == null) launchIntent = context.getPackageManager().getLaunchIntentForPackage(pkgName);

                if (launchIntent != null)  {
                    launchIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                    context.startActivity(launchIntent);
                } else {
                   // failure message
                }