Android服务的良好实践?

Android服务的良好实践?,android,Android,我想为我的主要活动创建一个独立的服务。此服务在启动我的手机时启动,每x分钟通过webservice检索一次信息 实现这一点的最佳实践是什么 启动服务时启动操作是否已完成 在不启动主活动的情况下启动服务还有其他操作吗? 另一种设计或最佳实践 例如,我想要一个行为与Facebook相同的服务。此服务始终处于活动状态,并在您收到消息时显示通知。如果单击通知,它将打开Facebook应用程序。但这会终止应用程序,并在接收新消息时保持活动状态 当我想终止我的主要活动时,我的第一次测试终止了我的服务 <

我想为我的主要活动创建一个独立的服务。此服务在启动我的手机时启动,每x分钟通过webservice检索一次信息

实现这一点的最佳实践是什么

启动服务时启动操作是否已完成

在不启动主活动的情况下启动服务还有其他操作吗? 另一种设计或最佳实践

例如,我想要一个行为与Facebook相同的服务。此服务始终处于活动状态,并在您收到消息时显示通知。如果单击通知,它将打开Facebook应用程序。但这会终止应用程序,并在接收新消息时保持活动状态

当我想终止我的主要活动时,我的第一次测试终止了我的服务

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

<uses-sdk android:minSdkVersion="15" android:targetSdkVersion="19" />

<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="com.google.android.providers.gsf.permission.READ_GSERVICES"/>
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
<!-- The following two permissions are not required to use
    Google Maps Android API v2, but are recommended. -->
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>


<uses-feature android:glEsVersion="0x00020000" android:required="true" />

<application
    android:allowBackup="true"
    android:icon="@drawable/ic_launcher"
    android:label="@string/app_name"
    android:theme="@style/AppTheme" >

    <activity
        android:name="fr.mr.MainActivity"
        android:label="@string/app_name" >
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

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

    <receiver android:name="fr.mr.service.MyReceiver"
        android:enabled="true"
        android:exported="false"
        android:label="OnBootReceiver">
        <intent-filter>
            <action android:name="android.intent.action.BOOT_COMPLETED" />
        </intent-filter>
    </receiver>

    <service 
        android:name="fr.mr.service.LocalService" 
        android:enabled="true"
        android:exported="false"
        android:label="LocalService" />

<meta-data android:name="com.google.android.maps.v2.API_KEY" android:value="@string/mapKey"/>
    <meta-data android:name="com.google.android.gms.version" android:value="@integer/google_play_services_version" />

</application>
我想为我的主要活动创建一个独立的服务。这 服务在启动我的手机时启动,并通过 每x分钟提供一次Web服务

您当然可以通过在
AndroidManifest.xml
上注册一个
BroadcastReceiver
来实现这一点,它响应
BOOT\u COMPLETED
并从中启动
服务。您的应用程序需要至少运行一次才能交付
BOOT_COMPLETED
(在API 11之前并非如此)。此外,考虑从服务器(例如电池等)中拉取数据的含义。 例如,我想要一个行为与facebook相同的服务。这 服务始终处于活动状态,当您 收到消息。如果单击初始化,它将打开 facebook应用程序。但这扼杀了应用程序,仍然存在 用于接收新消息的活动


至少对于他们的聊天应用程序,Facebook使用MQTT,这是一种M2M发布/订阅异步机制。它们不会每X分钟从服务器中提取数据。广播时,他们只收听传入的数据。如果您想使用MQTT,您可能会对一个名为的开源项目感兴趣。

您的服务不需要一直处于活动状态才能接收消息。Facebook,以及几乎所有其他基于推送的系统,用于唤醒您的设备,并从远程服务器向您的应用程序发送消息

当然,如果你只需要定期检查(而不是几乎实时地推送信息),那么你可以每隔X分钟启动一次服务,或者构建一个安卓组件——专门为远程服务器构建的安卓组件

请注意,许多应用程序结合了这两种方法和

public class MyReceiver extends BroadcastReceiver {

private static final String TAG = MyReceiver.class.getName();

@Override
public void onReceive( Context ctx, Intent i ) {
    Log.d( TAG, "MyReceiver.onReceive : " + i.getAction() );

    ctx.startService(new Intent().setComponent(new ComponentName(
            ctx.getPackageName(), LocalService.class.getName())));
}
}




public class LocalService extends Service{

private static final String TAG = LocalService.class.getName();
private NotificationManager mNM;
// Unique Identification Number for the Notification.
    // We use it on Notification start, and to cancel it.
    private int NOTIFICATION = 1332;
    private Timer timer ;    
    private int mId;


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

    @Override
    public void onCreate() {
        Log.i(TAG, "onCreate");
        mNM = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
        timer = new Timer(); 

        Notification note = new Notification( 0, null, System.currentTimeMillis() );
        note.flags |= Notification.FLAG_NO_CLEAR;
        startForeground( 0, note );
        /*
        Notification.Builder mBuilder =
                new Notification.Builder(this)
                .setSmallIcon(android.R.drawable.ic_dialog_info)
                .setContentTitle("test title")
                .setContentText("test content")
                .setAutoCancel(true)
                .setSound(RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION));


        startForeground(1, mBuilder.getNotification());*/
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.i(TAG, "Received start id " + startId + ": " + intent);
        mId = startId;

        new Thread(new Runnable() {
            public void run() {

                timer.scheduleAtFixedRate(new TimerTask() {
                    public void run() {
                        showNotification();
                    }
                }, 0, 60000); 

            }
        }).start();

        return START_STICKY;
    }

    @Override
    public void onDestroy() {
        Log.i(TAG, "onDestroy");
        mNM.cancel(NOTIFICATION);
    }


    /**
     * Show a notification while this service is running.
     */
    private void showNotification() {

        NotificationCompat.Builder mBuilder =
                new NotificationCompat.Builder(this)
                .setSmallIcon(android.R.drawable.ic_dialog_info)
                .setContentTitle(getString(fr.mrbmx.R.string.notification_title))
                .setContentText(getString(fr.mrbmx.R.string.notification_text))
                .setAutoCancel(true)
                .setSound(RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION));
        // Creates an explicit intent for an Activity in your app
        Intent resultIntent = new Intent(this, MainActivity.class);

        // The stack builder object will contain an artificial back stack for the
        // started Activity.
        // This ensures that navigating backward from the Activity leads out of
        // your application to the Home screen.
        TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);
        // Adds the back stack for the Intent (but not the Intent itself)
        stackBuilder.addParentStack(MainActivity.class);
        // Adds the Intent that starts the Activity to the top of the stack
        stackBuilder.addNextIntent(resultIntent);
        PendingIntent resultPendingIntent =
                stackBuilder.getPendingIntent(
                    0,
                    PendingIntent.FLAG_UPDATE_CURRENT
                );
        mBuilder.setContentIntent(resultPendingIntent);
        NotificationManager mNotificationManager =
            (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
        // mId allows you to update the notification later on.
        mNotificationManager.notify(mId, mBuilder.build());

    }

}