在 Android 中使用服务 class 在 Popup Window 中显示 ListView

Show ListView inside Popup Window using service class in Android

我想使用服务 class 在弹出窗口 window 中显示自定义列表视图。此列表正在从数据库中获取数据,并且在 activity 中工作正常,但在弹出窗口 window 中工作正常。下面是我的代码。任何帮助将不胜感激。

这是我的服务class:

public class PopupService extends Service{

    final static String URL = "https://billspill.com/json.php";
    private WindowManager mWindowManager;
    private View popupview;

    public PopupService() {
    }

    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public void onCreate() {
        popupview  = LayoutInflater.from(this).inflate(R.layout.popup, null);
        //Add the view to the window.
        final WindowManager.LayoutParams params = new WindowManager.LayoutParams(
                WindowManager.LayoutParams.MATCH_PARENT,
                WindowManager.LayoutParams.MATCH_PARENT,
                WindowManager.LayoutParams.TYPE_PHONE,
                WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
                PixelFormat.TRANSLUCENT);

        params.gravity = Gravity.TOP | Gravity.START;  
        params.x = 0;
        params.y = 100;

        mWindowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
        mWindowManager.addView(popupview, params);
        Button close = (Button)popupview.findViewById(R.id.dismiss);
        close.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                stopSelf();

            }
        });

        ListView lv = (ListView)popupview.findViewById(R.id.pager);
        new Downloader(this,lv,URL).execute();
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        if (popupview != null) mWindowManager.removeView(popupview);
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        return START_NOT_STICKY;
    }

下面是我的下载器 class,它扩展了 AsyncTask。此下载器 class 从 DataParser class 调用 DataParser 方法,后者进一步调用适配器 class 以将数据膨胀到列表中。这三个 classes 在 activity 中运行良好,但是当我在我的服务中调用 Downloader 时,应用程序崩溃了。我认为从服务 class.

传递 Downloader 中的上下文存在问题
public class Downloader extends AsyncTask<Void,Void,String> {

    Context ctx;
    ListView lv;
    ProgressDialog pd;

    @Override
    protected void onPreExecute() {
        super.onPreExecute();
        pd=new ProgressDialog(ctx);
        pd.setTitle("Retrive");
        pd.setMessage("Retrieving....please wait");
        pd.show();
    }

    @Override
    protected void onPostExecute(String jsonData) {
        super.onPostExecute(jsonData);
        pd.dismiss();
        if(jsonData==null)
        {
            Toast.makeText(ctx,"Unsuccessfull,No data Retrieved",Toast.LENGTH_SHORT).show();
        }
        else {
            DataParser parser = new DataParser(ctx,jsonData,lv);

            parser.execute();
        }
    }

    private String downloadData(){

        HttpURLConnection con = Connector.connect(urlAddress);
        if(con==null) {
            Toast.makeText(ctx,"Connection is null",Toast.LENGTH_LONG).show();
        }

        try{
            InputStream is = new BufferedInputStream(con.getInputStream());
            BufferedReader br = new BufferedReader(new InputStreamReader(is));

            String line;
            StringBuffer jsonData= new StringBuffer();

            while ((line=br.readLine())!=null)
            {

                jsonData.append(line+"/n");
            }
            br.close();
            is.close();
            return jsonData.toString();

        } catch (IOException e) {
            e.printStackTrace();
        }

        return null;
    }

    public Downloader(Context ctx, ListView lv, String urlAddress) {
        this.ctx = ctx;
        this.lv = lv;

        this.urlAddress = urlAddress;
    }

    String urlAddress;

    @Override
    protected String doInBackground(Void... params) {
        return downloadData();
    }

崩溃开始:

 --------- beginning of crash
05-14 18:58:00.694 10664-10664/com.billspillsmoothshopping.android E/AndroidRuntime: FATAL EXCEPTION: main
 Process: com.billspillsmoothshopping.android, PID: 10664
 java.lang.RuntimeException: Unable to create service com.billspillsmoothshopping.android.PopupService: android.view.WindowManager$BadTokenException: Unable to add window -- token null is not for an application
     at android.app.ActivityThread.handleCreateService(ActivityThread.java:2771)
     at android.app.ActivityThread.access00(ActivityThread.java:151)
     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1386)
     at android.os.Handler.dispatchMessage(Handler.java:102)
     at android.os.Looper.loop(Looper.java:135)
     at android.app.ActivityThread.main(ActivityThread.java:5254)
     at java.lang.reflect.Method.invoke(Native Method)
     at java.lang.reflect.Method.invoke(Method.java:372)
     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:902)
     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:697)
  Caused by: android.view.WindowManager$BadTokenException: Unable to add window -- token null is not for an application
     at android.view.ViewRootImpl.setView(ViewRootImpl.java:584)
     at android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:282)
     at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:85)
     at android.app.Dialog.show(Dialog.java:298)
     at com.billspillsmoothshopping.android.m_MySQL.CompareDownloader.onPreExecute(CompareDownloader.java:32)
     at android.os.AsyncTask.executeOnExecutor(AsyncTask.java:591)
     at android.os.AsyncTask.execute(AsyncTask.java:539)
     at com.billspillsmoothshopping.android.PopupService.onCreate(PopupService.java:81)
     at android.app.ActivityThread.handleCreateService(ActivityThread.java:2761)
     at android.app.ActivityThread.access00(ActivityThread.java:151) 
     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1386) 
     at android.os.Handler.dispatchMessage(Handler.java:102) 
     at android.os.Looper.loop(Looper.java:135) 
     at android.app.ActivityThread.main(ActivityThread.java:5254) 
     at java.lang.reflect.Method.invoke(Native Method) 
     at java.lang.reflect.Method.invoke(Method.java:372) 

您不能将弹出窗口 window 附加到服务,您必须传递实际的 activity 上下文而不是服务上下文,这就是您收到此错误的原因。

我建议您只使用 asynctask https://developer.android.com/reference/java/lang/Object.html to fetch the data and show it if the service is not so necessary and if its too necessary to use service after downloading data pass this data to some activity using broadcast receiver https://developer.android.com/reference/android/content/BroadcastReceiver.html,然后显示弹出窗口 window。 希望能帮助到你。 P.S。 "We use service for long running task and with no attachment with UI like playing audio, downloading big data's from server etc."