Android - Bắt đầu dịch vụ khi khởi động


107

Từ mọi thứ tôi đã thấy trên Stack Exchange và các nơi khác, tôi đã thiết lập mọi thứ một cách chính xác để khởi động IntentService khi hệ điều hành Android khởi động. Rất tiếc, nó không bắt đầu khi khởi động và tôi không gặp bất kỳ lỗi nào. Có thể các chuyên gia có thể giúp ...

Rõ ràng:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
  package="com.phx.batterylogger"
  android:versionCode="1"
  android:versionName="1.0"
  android:installLocation="internalOnly">

<uses-sdk android:minSdkVersion="8" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.BATTERY_STATS" />

<application android:icon="@drawable/icon" android:label="@string/app_name">
    <service android:name=".BatteryLogger"/>
    <receiver android:name=".StartupIntentReceiver">  
        <intent-filter>  
            <action android:name="android.intent.action.BOOT_COMPLETED" />  
        </intent-filter>  
    </receiver>
</application>

</manifest>

BroadcastReceiver cho Startup:

package com.phx.batterylogger;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;

public class StartupIntentReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        Intent serviceIntent = new Intent(context, BatteryLogger.class);
        context.startService(serviceIntent);
    }
}

CẬP NHẬT : Tôi đã thử tất cả các đề xuất bên dưới và tôi đã thêm ghi nhật ký chẳng hạn như Log.v("BatteryLogger", "Got to onReceive, about to start service");vào trình xử lý onReceive của StartupIntentReceiver và không có gì được ghi lại. Vì vậy, nó thậm chí còn không đến được BroadcastReceiver.

Tôi nghĩ rằng tôi đang triển khai APK và thử nghiệm chính xác, chỉ cần chạy Debug trong Eclipse và bảng điều khiển cho biết nó cài đặt thành công nó vào máy tính bảng Xoom của tôi tại \ BatteryLogger \ bin \ BatteryLogger.apk. Sau đó, để kiểm tra, tôi khởi động lại máy tính bảng rồi xem nhật ký trong DDMS và kiểm tra Dịch vụ đang chạy trong cài đặt hệ điều hành. Tất cả điều này có đúng không, hay tôi đang thiếu một cái gì đó? Một lần nữa, bất kỳ sự giúp đỡ nào cũng được đánh giá cao.


1
bạn đang gặp vấn đề gì, bạn không nhận được bất kỳ giao diện người dùng nào ..?
Lalit Poptani

1
Dịch vụ không bao giờ bắt đầu, đó là vấn đề.
Gady

Làm thế nào bạn biết rằng dịch vụ của bạn chưa bắt đầu, bạn đã in Nhật ký hay bất cứ thứ gì tương tự chưa ..?
Lalit Poptani

1
Bạn không cần nhật ký để xem nó không chạy. Hệ điều hành Android hiển thị các dịch vụ đang chạy. Tuy nhiên, sẽ là khôn ngoan nếu sử dụng ghi nhật ký để xem liệu có lỗi xảy ra hay không. Tôi sẽ dự đoán rằng nó xảy ra trước context.startService () nếu có lỗi xảy ra.
Tony

1
Tôi đã thêm vào Log.v("BatteryLogger", "Got to onReceive, about to start service");trình xử lý onReceive và nó không bao giờ hiển thị trong nhật ký. Vì vậy, người nghe được không (?)
Gady

Câu trả lời:


302

Đây là một ví dụ hoàn chỉnh về Ứng dụng Tự động Khởi động

Tệp AndroidManifest

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="pack.saltriver" android:versionCode="1" android:versionName="1.0">

    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />

    <application android:icon="@drawable/icon" android:label="@string/app_name">

        <receiver android:name=".autostart">
            <intent-filter>
                <action android:name="android.intent.action.BOOT_COMPLETED" />
            </intent-filter>
        </receiver>

        <activity android:name=".hello"></activity>
        <service android:enabled="true" android:name=".service" />
    </application>
</manifest>

autostart.java

public class autostart extends BroadcastReceiver 
{
    public void onReceive(Context context, Intent arg1) 
    {
        Intent intent = new Intent(context,service.class);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            context.startForegroundService(intent);
        } else {
            context.startService(intent);
        }
        Log.i("Autostart", "started");
    }
}

service.java

public class service extends Service
{
    private static final String TAG = "MyService";
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }
    public void onDestroy() {
        Toast.makeText(this, "My Service Stopped", Toast.LENGTH_LONG).show();
        Log.d(TAG, "onDestroy");
    }

    @Override
    public void onStart(Intent intent, int startid)
    {
        Intent intents = new Intent(getBaseContext(),hello.class);
        intents.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        startActivity(intents);
        Toast.makeText(this, "My Service Started", Toast.LENGTH_LONG).show();
        Log.d(TAG, "onStart");
    }
}

hello.java - Nó sẽ bật lên mỗi khi bạn khởi động thiết bị sau khi thực hiện ứng dụng một lần.

public class hello extends Activity 
{   
    public void onCreate(Bundle savedInstanceState) 
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        Toast.makeText(getBaseContext(), "Hello........", Toast.LENGTH_LONG).show();
    }
}

10
+1 cho ví dụ hoàn chỉnh. Có lẽ tôi nên thay đổi IntentService tôi với onHandleIntent lên một Dịch vụ cũ đồng bằng
Gady

6
Điều này đã giải quyết nó cuối cùng. Vấn đề là sự kết hợp giữa dịch vụ của tôi là IntentService thay vì Dịch vụ cũ thuần túy và lỗi trong mã dịch vụ. Sự thấu đáo của câu trả lời này và đăng nhập Android đã giúp tôi giải quyết các vấn đề của mình.
Gady

3
+1 cho ví dụ chi tiết. Điều này cũng sẽ hoạt động nếu không có hoạt động?
balas

1
Gọi lại onStart () không được dùng nữa. Bạn nên sử dụng onStartCommand () để thay thế.
mmBs

1
@mmBs câu trả lời này đã gần 5 năm tuổi, vì vậy nó hiển nhiên
Lalit Poptani

3

Dịch vụ của bạn có thể bị tắt trước khi hoàn thành do thiết bị chuyển sang chế độ ngủ sau khi khởi động. Trước tiên, bạn cần phải có khóa đánh thức. May mắn thay, thư viện Hỗ trợ cung cấp cho chúng tôi một lớp để thực hiện việc này:

public class SimpleWakefulReceiver extends WakefulBroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        // This is the Intent to deliver to our service.
        Intent service = new Intent(context, SimpleWakefulService.class);

        // Start the service, keeping the device awake while it is launching.
        Log.i("SimpleWakefulReceiver", "Starting service @ " + SystemClock.elapsedRealtime());
        startWakefulService(context, service);
    }
}

sau đó, trong Dịch vụ của bạn, hãy đảm bảo mở khóa đánh thức:

    @Override
    protected void onHandleIntent(Intent intent) {
        // At this point SimpleWakefulReceiver is still holding a wake lock
        // for us.  We can do whatever we need to here and then tell it that
        // it can release the wakelock.

...
        Log.i("SimpleWakefulReceiver", "Completed service @ " + SystemClock.elapsedRealtime());
        SimpleWakefulReceiver.completeWakefulIntent(intent);
    }

Đừng quên thêm quyền WAKE_LOCK:

<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.WAKE_LOCK" />

1
Tôi đang gặp vấn đề tương tự. Bạn có giúp tôi không? Cảm ơn! stackoverflow.com/questions/35373525/starting-my-service
Ruchir Baronia

2

Sau đây sẽ hiệu quả. Tôi đã xác minh. Có thể vấn đề của bạn là ở một nơi khác.

public class MyReceiver extends BroadcastReceiver{

    @Override
    public void onReceive(Context context, Intent intent) {
        Log.d("TAG", "MyReceiver");
        Intent serviceIntent = new Intent(context, Test1Service.class);
        context.startService(serviceIntent);
    }
}




public class Test1Service extends Service {
    /** Called when the activity is first created. */
    @Override
    public void onCreate() {
        super.onCreate();
        Log.d("TAG", "Service created.");
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.d("TAG", "Service started.");
        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    public void onStart(Intent intent, int startId) {
        super.onStart(intent, startId);
        Log.d("TAG", "Service started.");
    }
    @Override
    public IBinder onBind(Intent arg0) {
        return null;
    }
}




<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="com.test"
      android:versionCode="1"
      android:versionName="1.0"
      android:installLocation="internalOnly">
    <uses-sdk android:minSdkVersion="8" />

    <application android:icon="@drawable/icon" android:label="@string/app_name">

    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.BATTERY_STATS" 
    />
<!--        <activity android:name=".MyActivity">
            <intent-filter>  
                <action android:name="android.intent.action.MAIN" /> 
                <category android:name="android.intent.category.LAUNCHER"></category> 
            </intent-filter>
       </activity> -->
        <service android:name=".Test1Service" 
                  android:label="@string/app_name"
                  >
        </service>
        <receiver android:name=".MyReceiver">  
            <intent-filter>  
                <action android:name="android.intent.action.BOOT_COMPLETED" /> 
            </intent-filter>  
        </receiver> 
    </application>
</manifest>

Cảm ơn vì điều này, nhưng nó vẫn không hoạt động. Nhật ký thậm chí không cho thấy rằng nó đến được StartupIntentReceiver. Bất kỳ ý tưởng khác?
Gady

1
Mã của bạn có đang hoạt động trong trình giả lập không? Bạn có thể nhận được ý định trong trình giả lập không?
Vivek

Tôi đã kiểm tra trong trình giả lập và gặp lỗi trong DDMS, nhưng có vẻ như ít nhất dịch vụ đang cố gắng khởi động, mặc dù không có Log()câu lệnh nào của tôi ở đó và thiết bị giả lập không hiển thị dịch vụ của tôi đang chạy trong cài đặt hệ điều hành. Đây là lỗi trong DDMS: System.err - at com.phx.batterylogger$1.onReceive(BatteryLogger.java:43)Điều đó có nghĩa là sự cố nằm ở dòng 43 của dịch vụ BatteryLogger của tôi?
Gady

2

Mình đã tìm ra cách giúp ứng dụng của bạn chạy tốt khi máy khởi động lại, bạn hãy làm theo các bước dưới đây là thành công.

Tệp AndroidManifest

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="pack.saltriver" android:versionCode="1" android:versionName="1.0">
<uses-permission 
android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS"/>
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />

<application android:icon="@drawable/icon" android:label="@string/app_name">

<activity android:name=".MainActivity">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
    <receiver android:name=".UIBootReceiver" android:enabled="true" 
    android:exported="true">
        <intent-filter>
            <action android:name="android.intent.action.BOOT_COMPLETED" />
            <category android:name="android.intent.category.DEFAULT" />
        </intent-filter>
    </receiver>
     <service android:name=".class_Service" />
</application>

UIBootReceiver

public class UIBootReceiver extends BroadcastReceiver {

private static final String TAG = "UIBootReceiver";
@Override

    public void onReceive(Context context, Intent arg1)
    {
        Toast.makeText(context, "started", Toast.LENGTH_SHORT).show();
        Intent intent = new Intent(context,class_Service.class);
        context.startService(intent);
    }
  }

Đây là yêu cầu quyền không cần quản lý tiết kiệm pin cho ứng dụng này để bạn có thể chạy ở chế độ nền ổn định.

Khai báo mã này trong onCreate () của lớp MainActivity:

   Intent myIntent = new Intent();
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        myIntent.setAction(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS);
        myIntent.setData(Uri.parse("package:" + 
   DeviceMovingSpeed.this.getPackageName()));
    }
    startActivity(myIntent);

1

Trông rất giống với của tôi nhưng tôi sử dụng tên gói đầy đủ cho người nhận:

<receiver android:name=".StartupIntentReceiver">

Tôi có:

<receiver android:name="com.your.package.AutoStart"> 

Đúng vậy, hơi khó để sắp xếp vấn đề của bạn, vì vậy tốt hơn nên đăng một ví dụ về hello world.
Lalit Poptani

1

Tôi đã thành công mà không có gói đầy đủ, bạn có biết do đâu mà chuỗi cuộc gọi bị gián đoạn không? Nếu bạn gỡ lỗi bằng Log()'s, tại thời điểm nào nó không hoạt động nữa?

Tôi nghĩ nó có thể nằm trong IntentService của bạn, tất cả đều ổn.


Tôi đã thêm vào Log.v("BatteryLogger", "Got to onReceive, about to start service");trình xử lý onReceive và nó không bao giờ hiển thị trong nhật ký. Vì vậy, người nghe đang thất bại (?)
Gady

Điều gì khiến máy thu phát sóng khởi động khi khởi động điện thoại? Cảm ơn!
Ruchir Baronia

Con trai. Tôi đã không chạm vào Android trong một vài năm. Xin lỗi @Ruchir
Phix

0

Chỉ để giúp tìm kiếm dễ dàng hơn, như đã đề cập trong phần nhận xét, điều này không thể thực hiện được vì 3.1 https://stackoverflow.com/a/19856367/6505257


Đó là không đúng, như đã nêu bởi Think Twice Code Once trong phần nhận xét của câu trả lời rất giống nhau.
Ricardo A.

Giải thích chi tiết hơn để hỗ trợ lập luận của tôi: stackoverflow.com/questions/20441308/…
Ricardo A.

Thực sự là lâu rồi tôi không làm gì với android, nhưng bạn nói đúng, nó có thể. Không cần đối số khác. (Tôi sẽ chỉnh sửa câu trả lời)
MrKew
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.