【问题标题】:Android IntentService not completing task if App is closed如果应用程序关闭,Android IntentService 不会完成任务
【发布时间】:2016-03-06 21:08:09
【问题描述】:

我正在使用 IntentService 将数据保存到 SQLDatabase 并将数据上传到 Parse。如果我保持应用程序运行,IntentService 工作正常。如果我最小化它(通过按下主页按钮),它也会正确执行。

但是如果我按下导航按钮并破坏应用程序(应用程序屏幕缩小并且您将其滑掉的东西);然后 IntentService 停止运行(它甚至不调用 onDestory)。

我想要的是让服务执行所有任务;和毁灭本身。因此,不需要 START_STICKY (Intent),因为我不希望它在后台连续运行。

启动 IntentService

Intent intent_publishService = new Intent(getApplicationContext(), PublishService.class);

Bundle basket_storyData = new Bundle();
basket_storyData.putAll( packStoryData() );
intent_publishService.putExtra(KEY_BASKET_STORY_DATA, basket_storyData);

intent_publishService.putParcelableArrayListExtra(KEY_BASKET_IMAGE_DATA, (ArrayList<? extends Parcelable>) final_image_data);
startService(intent_publishService);

PublishService.class (片段)

@Override
protected void onHandleIntent(Intent intent)
{
    Log.i(TAG, "ONHANDLEINTENT" );

    context = getApplicationContext();

    final String KEY_BASKET_IMAGE_DATA = "key_basket_image_data";
    final String KEY_BASKET_STORY_DATA = "key_basket_story_data";
    final String KEY_BASKET_EXTRA      = "key_basket_extra";


    ArrayList<ImagesData> _iDataSave = new ArrayList<ImagesData>();
    _iDataSave.addAll( (Collection<? extends ImagesData>) intent.getParcelableArrayListExtra(KEY_BASKET_IMAGE_DATA) );

    Log.i(TAG, "_iDataSize:" + Integer.toString(_iDataSave.size()) );

    //Get Bundle Values
    Bundle storyBundle = intent.getBundleExtra(KEY_BASKET_STORY_DATA);

    publishStory(storyBundle, _iDataSave);
}

Edit1:清单声明

<service android:name="com.example.create.main.PublishService" />

已解决

【问题讨论】:

    标签: android android-intent service android-service intentservice


    【解决方案1】:

    在这种情况下,您将需要 START_STICKY 向 android 表明您希望在应用程序被终止后尝试继续工作。

    当用户从应用程序选择器上滑开时,这将无条件地终止应用程序进程。您无法阻止这种情况发生 - 它旨在让用户控制当时正在运行的内容。

    【讨论】:

    • 但是'onHandleIntent'没有返回类型;并且不建议在 IntentService 中使用 onStartCommand。
    • 然后您可以创建自己的服务。很容易找到源代码并将其复制到 IntentService 以使其为所欲为。
    • 我切换到 IntentService 因为 Service 在主线程上运行,而 IntentService 在自己的线程上运行。
    • 是的,您可以复制 IntentService 及其线程策略以使其为所欲为。
    • 所以我需要来自 Service 的 START_STICKY 之类的东西 + 在 IntentService 的单独线程上运行
    【解决方案2】:

    以下是需要做的事情:

    1) 改变 IntentService >> 服务

    2) 将所有代码移至 onStartCommand

    3) 使用单独的线程,以便一切都在 UI 线程之外完成

    4) 在 Manifest 中将其声明为单独的进程

    PublishService.class (片段)

    @Override
    public int onStartCommand(final Intent intent, int flags, int startId)
    {
        Log.i(TAG, "ONSTARTCOMMAND" );
    
        Intent notificationIntent = new Intent(this, MyFriendList_Activity.class);
        PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);
    
        Notification.Builder builder = new Notification.Builder(getApplicationContext());
    
        builder.setAutoCancel(false);
        builder.setTicker("this is ticker text");
        builder.setContentTitle("WhatsApp Notification");               
        builder.setContentText("You have a new message");
        builder.setSmallIcon(R.drawable.ic_launcher);
        //builder.setContentIntent(pendingIntent);
        builder.setOngoing(true);
        builder.setNumber(100);
    
        // Sets the progress indicator to a max value, the current completion
        // percentage, and "determinate" state
        builder.setProgress(0, 0, true);
    
        Notification notificationFinal = builder.getNotification();
    
        startForeground(ONGOING_NOTIFICATION_ID, notificationFinal );
    
        Runnable r = new Runnable() 
        {       
            public void run() 
            {
                context = getApplicationContext();
    
                final String KEY_BASKET_IMAGE_DATA = "key_basket_image_data";
                final String KEY_BASKET_STORY_DATA = "key_basket_story_data";
                final String KEY_BASKET_EXTRA      = "key_basket_extra";
    
    
                ArrayList<ImagesData> _iDataSave = new ArrayList<ImagesData>();
                _iDataSave.addAll( (Collection<? extends ImagesData>) intent.getParcelableArrayListExtra(KEY_BASKET_IMAGE_DATA) );
    
                Log.i(TAG, "_iDataSize:" + Integer.toString(_iDataSave.size()) );
    
                //Get Bundle Values
                Bundle storyBundle = intent.getBundleExtra(KEY_BASKET_STORY_DATA);
    
                publishStory(storyBundle, _iDataSave);               
            }
        };
    
        Thread t = new Thread(r);
        t.start();
    
        //return START_STICKY;
        //return START_REDELIVER_INTENT;
        //return START_CONTINUATION_MASK;
        return START_NOT_STICKY;
    }
    

    清单声明

       <service
            android:name="com.example.create.main.PublishService"
            android:process=".publishservice" />
    

    关注

    startForeground() + 单独的进程 + 在单独的线程上运行

    --- 也许所有 3-都不需要?

    编辑1:还有;你可以跳过所有前景的东西;并返回 START_CONTINUATION_MASK ;但不建议这样做,因为每个设备都有不同的处理返回类型的方式

    【讨论】:

    • 我刚刚对此进行了测试,但它不起作用(模拟器,API 级别 23)。当您从选择器中滑开应用程序时,它也会杀死另一个进程。您可以在 logcat 中看到它。应用名称为“test.app”,进程名称为“proc”:ActivityManager: Killing 3390:test.app:proc/u0a60 (adj 8): remove task
    • 我在 Android(5.0.2) 上运行它对我有用。尝试在设备上运行它;让我知道。 min14;max23.
    • 还有;返回 '​​START_NOT_STICKY' 并在任务完成后调用 stopSelf() ;所以也许运行一个虚拟循环并在一段时间后调用 stopSelf()?
    • @DougStevenson 你在设备上还有同样的问题吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-12-20
    • 2012-07-29
    相关资源
    最近更新 更多