android - android中的可 sleep 后台服务

标签 android service

我可以在 android 中创建一个后台服务,它可以在特定时间完成工作后进入休眠状态吗? 有这方面的想法请指导。

最佳答案

作为初学者的好问题,但是为此您需要了解 Intent Service。

<强>1。什么是 IntentService?

  • IntentService 是 android.app.Service 类的子类。一个声明 Intent 服务允许处理长时间运行的任务而不影响 应用程序 UI 线程。这不受任何 Activity 的约束,因此,它 不会因 Activity 生命周期中的任何更改而受到影响。一次 IntentService 启动,它使用 worker 处理每个 Intent 线程并在它用完工作时自行停止。
  • 使用 IntentService,任何时候只能处理一个请求 单点时间。如果您请求另一个任务,那么新的 作业将等到上一个作业完成。这意味着 IntentService 处理请求。
  • 使用 IntentService 声明的任务不能被中断

<强>2。创建一个 IntentService:

我们将创建一个 IntentService 来从服务器下载数据。下载完成后,响应将发送回 Activity 。让我们创建一个新类 DownloadService.java 并从 android.app.IntentService 扩展它。现在让我们覆盖 onHandleIntent() 方法。

public class DownloadService extends IntentService {

    public static final int STATUS_RUNNING = 0;
    public static final int STATUS_FINISHED = 1;
    public static final int STATUS_ERROR = 2;

    private static final String TAG = "DownloadService";

    public DownloadService() {
        super(DownloadService.class.getName());
    }

    @Override
    protected void onHandleIntent(Intent intent) {

        Log.d(TAG, "Service Started!");

        final ResultReceiver receiver = intent.getParcelableExtra("receiver");
        String url = intent.getStringExtra("url");

        Bundle bundle = new Bundle();

        if (!TextUtils.isEmpty(url)) {
            /* Update UI: Download Service is Running */
            receiver.send(STATUS_RUNNING, Bundle.EMPTY);

            try {
                String[] results = downloadData(url);

                /* Sending result back to activity */
                if (null != results && results.length > 0) {
                    bundle.putStringArray("result", results);
                    receiver.send(STATUS_FINISHED, bundle);
                }
            } catch (Exception e) {

                /* Sending error message back to activity */
                bundle.putString(Intent.EXTRA_TEXT, e.toString());
                receiver.send(STATUS_ERROR, bundle);
            }
        }
        Log.d(TAG, "Service Stopping!");
        this.stopSelf();
    }

    private String[] downloadData(String requestUrl) throws IOException, DownloadException {
        InputStream inputStream = null;
        HttpURLConnection urlConnection = null;

        /* forming th java.net.URL object */
        URL url = new URL(requestUrl);
        urlConnection = (HttpURLConnection) url.openConnection();

        /* optional request header */
        urlConnection.setRequestProperty("Content-Type", "application/json");

        /* optional request header */
        urlConnection.setRequestProperty("Accept", "application/json");

        /* for Get request */
        urlConnection.setRequestMethod("GET");
        int statusCode = urlConnection.getResponseCode();

        /* 200 represents HTTP OK */
        if (statusCode == 200) {
            inputStream = new BufferedInputStream(urlConnection.getInputStream());
            String response = convertInputStreamToString(inputStream);
            String[] results = parseResult(response);
            return results;
        } else {
            throw new DownloadException("Failed to fetch data!!");
        }
    }

    private String convertInputStreamToString(InputStream inputStream) throws IOException {

        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
        String line = "";
        String result = "";

        while ((line = bufferedReader.readLine()) != null) {
            result += line;
        }

            /* Close Stream */
        if (null != inputStream) {
            inputStream.close();
        }

        return result;
    }

    private String[] parseResult(String result) {

        String[] blogTitles = null;
        try {
            JSONObject response = new JSONObject(result);
            JSONArray posts = response.optJSONArray("posts");
            blogTitles = new String[posts.length()];

            for (int i = 0; i < posts.length(); i++) {
                JSONObject post = posts.optJSONObject(i);
                String title = post.optString("title");
                blogTitles[i] = title;
            }

        } catch (JSONException e) {
            e.printStackTrace();
        }
        return blogTitles;
    }

    public class DownloadException extends Exception {

        public DownloadException(String message) {
            super(message);
        }

        public DownloadException(String message, Throwable cause) {
            super(message, cause);
        }
    }
}

3.工作原理

  1. DownloadService 类扩展了 IntentService 并覆盖了 onHandleIntent() 方法。在 onHandleIntent() 方法中,我们将执行网络请求以从服务器下载数据

  2. 在它从服务器下载数据之前,请求是从 bundle 中获取的。我们的 Activity 将在启动时将此数据作为额外发送

  3. 一旦下载成功,我们将通过 ResultReceiver 将响应发送回 Activity

  4. 对于任何异常或错误,我们将通过 ResultReceiver 将错误响应传回 Activity 。

  5. 我们已经声明了自定义异常类 DownloadException 来处理我们所有的自定义错误消息。你可以这样做

<强>4。在 list 中声明服务

与服务一样,IntentService 也需要在您的应用程序 list 中有一个条目。提供元素条目并声明您使用的所有 IntentServices。此外,当我们执行从互联网下载数据的操作时,我们将请求 android.permission.INTERNET 权限。

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.javatechig.intentserviceexample">

    <!-- Internet permission, as we are accessing data from server -->
    <uses-permission android:name="android.permission.INTERNET" />

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme">
        <activity
            android:name=".MyActivity"
            android:label="@string/app_name">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

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


        <!-- Declaring Service in Manifest -->
        <service
            android:name=".DownloadService"
            android:exported="false" />

    </application>

</manifest>

6.向 IntentService 发送工作请求

要启动DownloadService下载数据,必须创建一个显式的Intent,并在其中添加所有的请求参数。可以通过调用 startService() 方法来启动服务。您可以从 Activity 或 Fragment 启动 IntentService。

这里额外的 DownloadResultReceiver 是什么,嗯?请记住,我们必须将下载请求的结果从服务传递到 Activity 。这将通过 ResultReceiver 完成。

/* Starting Download Service */
mReceiver = new DownloadResultReceiver(new Handler());
mReceiver.setReceiver(this);
Intent intent = new Intent(Intent.ACTION_SYNC, null, this, DownloadService.class);

/* Send optional extras to Download IntentService */
intent.putExtra("url", url);
intent.putExtra("receiver", mReceiver);
intent.putExtra("requestId", 101);

startService(intent);

只需按照您的要求进行更改即可。 记住***** IntentService 启动后,它会使用工作线程处理每个 Intent,并在它用完工作时自行停止。

关于android - android中的可 sleep 后台服务,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33938695/

相关文章:

android - 带有Gradle的Android Jacoco测试带有compileDebugSources和compileDebugTestSources的dependsOn顺序

Android:如何在不耗尽电池的情况下定期检查当前位置

android - 如何在真正的平板设备上运行我的 Android 应用程序?

android - RecyclerView 上的 VideoView

android - 使单个 Observable 发射多次

javascript - 使用 angularjs 中的自定义服务交换 ng-src 属性

c - C 后台编程

java - 永无休止的后台服务 - Java for Android

logging - 更改 Upstart 服务的日志记录目录/文件

ubuntu - docker daemon 没有在我的 ubuntu vm 中启动, "service start"ok by "ps"没有结果