簡體   English   中英

如何使用警報管理器調用擴展服務的類?

[英]How to call a class which extends service using alarm manager?

我正在嘗試為通知創建服務,該服務將在啟動設備(設備已開機)2分鍾后啟動並會檢查通知。

也將每2分鍾調用一次。 基本上,我試圖在必要時向用戶顯示通知。

我在清單中編寫了以下代碼:

 <?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.newsapp"
android:versionCode="1"
android:versionName="1.0" 
android:installLocation="internalOnly">
 <uses-sdk
    android:minSdkVersion="8"
    android:targetSdkVersion="17" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<!-- For notifications /\ -->
<application
    android:allowBackup="true"
    android:icon="@drawable/logo"
    android:label="@string/app_name"
    android:theme="@style/AppTheme" >

    <receiver android:name="com.example.newsapp.MainActivity$MyReciever"
        android:enabled="true"
        android:exported="true">
<!--            android:label="MyReciever"> -->
    <intent-filter>
        <action android:name="android.intent.action.BOOT_COMPLETED" />
        <action android:name="android.intent.action.QUICKBOOT_POWERON" />
        <!-- for HTC devices /\ -->
    </intent-filter>
</receiver>

    <activity
        android:name="com.example.newsapp.MainActivity"
        android:label="@string/app_name"
        android:launchMode="singleInstance"
        android:configChanges="keyboard|keyboardHidden|orientation|screenLayout|uiMode|screenSize|smallestScreenSize"
        android:theme="@android:style/Theme.NoTitleBar.Fullscreen" 
         >

        <!-- make full screen up /\ -->
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

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

</manifest>

Java中的這段代碼:

  public static class NotificationService extends Service {

        private WakeLock mWakeLock;
        private Intent mintent;
        /**
         * Simply return null, since our Service will not be communicating with
         * any other components. It just does its work silently.
         */
        @Override
        public IBinder onBind(Intent intent) {
            return null;
        }

        /**
         * This is where we initialize. We call this when onStart/onStartCommand is
         * called by the system. We won't do anything with the intent here, and you
         * probably won't, either.
         */
        private void handleIntent(Intent intent) {
            // obtain the wake lock
            Log.d("NotificationService", "is in handleIntent");
            mintent = intent;
            PowerManager pm = (PowerManager) getSystemService(POWER_SERVICE);
            mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "NewTag");//change the newtag
            mWakeLock.acquire();

            // check the global background data setting
            ConnectivityManager cm = (ConnectivityManager) getSystemService(CONNECTIVITY_SERVICE);
            if (!cm.getBackgroundDataSetting()) {
                stopSelf();
                return;
            }

            // do the actual work, in a separate thread
            new PollTask().execute(null,null,null);
        }

        private class PollTask extends AsyncTask<Object,Object,String> {
            /**
             * This is where YOU do YOUR work. There's nothing for me to write here
             * you have to fill this in. Make your HTTP request(s) or whatever it is
             * you have to do to get your updates in here, because this is run in a
             * separate thread
             */


            protected String  doInBackground(Object... params) {
                // do stuff!
                Log.d("*************************", "is in doInBackground");
                 SoapObject  request = new SoapObject(NAMESPACE, METHOD_NAME2);  
                            String result1="";
                            SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);
                            envelope.setOutputSoapObject(request);
                            envelope.dotNet = true;
                            try 
                            {
                                HttpTransportSE androidHttpTransport = new HttpTransportSE(URL);
                                androidHttpTransport.call(SOAP_ACTION2, envelope);
                                //Object result = (Object)envelope.getResponse(); // when calling a webmethod with parameters                           
                                SoapObject result = (SoapObject)envelope.getResponse(); // when calling a webmethod without parameters
                                if (result!=null)           
                                {
                                    PropertyInfo innerp=new PropertyInfo();
                                    result.getPropertyInfo(0, innerp);
                                    //SoapObject sobj=(SoapObject) result.getProperty(0);
                                    result1= innerp.toString();
                                    return result1;         
                                }
                                    else 
                                    {



                                    }

                            }
                            catch (Exception e)
                            {
                                result1 = e.getMessage();

                                e.printStackTrace();
                                return null;

                            }

                        return null;
            }

            /**
             * In here you should interpret whatever you fetched in doInBackground
             * and push any notifications you need to the status bar, using the
             * NotificationManager. I will not cover this here, go check the docs on
             * NotificationManager.
             *
             * What you HAVE to do is call stopSelf() after you've pushed your
             * notification(s). This will:
             * 1) Kill the service so it doesn't waste precious resources
             * 2) Call onDestroy() which will release the wake lock, so the device
             *    can go to sleep again and save precious battery.
             */
            protected void onPostExecute(String  result) {
                // TODO Auto-generated method stub
                super.onPostExecute(result);
                stopSelf();
                if (result!=null && result.equals("true"))
                {

                    //new doWork2().execute(null,null,null);
                }
                else
                {

                }
            }
        }

        /**
         * This is deprecated, but you have to implement it if you're planning on
         * supporting devices with an API level lower than 5 (Android 2.0).
         */
        @Override
        public void onStart(Intent intent, int startId) {
            handleIntent(intent);
        }

        /**
         * This is called on 2.0+ (API level 5 or higher). Returning
         * START_NOT_STICKY tells the system to not restart the service if it is
         * killed because of poor resource (memory/cpu) conditions.
         */
        @Override
        public int onStartCommand(Intent intent, int flags, int startId) {
            Log.d("NotificationService*************************", "is in onStartCommand");
            handleIntent(intent);
            return START_NOT_STICKY;
        }

        /**
         * In onDestroy() we release our wake lock. This ensures that whenever the
         * Service stops (killed for resources, stopSelf() called, etc.), the wake
         * lock will be released.
         */
        public void onDestroy() {
            super.onDestroy();
            mWakeLock.release();
        }
    }
    public static class MyReciever extends BroadcastReceiver {//remove static later

        @Override
        public void onReceive(Context arg0, Intent arg1) {
            // TODO Auto-generated method stub
            //If this BroadcastReceiver was launched through a <receiver> tag, then the object is no longer alive after returning from this function
            // TODO Auto-generated method stub
            // in our case intent will always be BOOT_COMPLETED, so we can just set
            // the alarm
            // Note that a BroadcastReceiver is *NOT* a Context. Thus, we can't use
            // "this" whenever we need to pass a reference to the current context.
            // Thankfully, Android will supply a valid Context as the first parameter
            target = arg0;
            Log.d("BootReciever", "is in onRecieve");
            SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(arg0);
            int minutes = prefs.getInt("interval",2);//change the 2- is the value to return if this doesn't return a value
            AlarmManager am = (AlarmManager) arg0.getSystemService(Context.ALARM_SERVICE);
            Intent i = new Intent(arg0, NotificationService.class);//or com.example.newsapp.MainActivity.NotificationService.class

           // arg0.startService(i);//lets try this
            PendingIntent pi = PendingIntent.getService(arg0, 0, i, 0);
            am.cancel(pi);//removes any alarm with matching intent
            // by my own convention, minutes <= 0 means notifications are disabled
            if (minutes > 0) {
                am.setInexactRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP,
                    SystemClock.elapsedRealtime() + minutes*60*1000,
                    minutes*60*1000, pi);
                Log.d("BootReciever", "minutes>0");
            }
            Toast.makeText(arg0, "onRecieve", Toast.LENGTH_LONG).show();
        }


    }

現在,調用了onReceive函數,但是我的問題是NotificationService類沒有作為服務啟動,我認為它沒有被調用。 我只想在NotificationService類中調用onStartCommand函數,因此它將調用handleIntent方法,然后將通過調用Web服務方法來檢查通知。

2分鍾過后,現在該啟動NotificationService我得到此日志:

    02-25 11:22:30.927: D/dalvikvm(288): GC_CONCURRENT freed 1967K, 35% free 5820K/8916K, paused 87ms+10ms, total 204ms
02-25 11:22:34.319: E/ThrottleService(288): problem during onPollAlarm: java.lang.IllegalStateException: problem parsing stats: java.io.FileNotFoundException: /proc/net/xt_qtaguid/iface_stat_all: open failed: ENOENT (No such file or directory)
02-25 11:23:13.998: D/ExchangeService(603): Received deviceId from Email app: null
02-25 11:23:13.998: D/ExchangeService(603): !!! deviceId unknown; stopping self and retrying
02-25 11:23:19.067: D/ExchangeService(603): !!! EAS ExchangeService, onCreate
02-25 11:23:19.077: D/ExchangeService(603): !!! EAS ExchangeService, onStartCommand, startingUp = false, running = false
02-25 11:23:19.087: D/ExchangeService(603): !!! EAS ExchangeService, onStartCommand, startingUp = true, running = false
02-25 11:23:19.097: W/ActivityManager(288): Unable to start service Intent { act=com.android.email.ACCOUNT_INTENT } U=0: not found
02-25 11:23:19.097: D/ExchangeService(603): !!! Email application not found; stopping self
02-25 11:23:19.127: E/ActivityThread(603): Service com.android.exchange.ExchangeService has leaked ServiceConnection com.android.emailcommon.service.ServiceProxy$ProxyConnection@40d2b0e0 that was originally bound here
02-25 11:23:19.127: E/ActivityThread(603): android.app.ServiceConnectionLeaked: Service com.android.exchange.ExchangeService has leaked ServiceConnection com.android.emailcommon.service.ServiceProxy$ProxyConnection@40d2b0e0 that was originally bound here
02-25 11:23:19.127: E/ActivityThread(603):  at android.app.LoadedApk$ServiceDispatcher.<init>(LoadedApk.java:969)
02-25 11:23:19.127: E/ActivityThread(603):  at android.app.LoadedApk.getServiceDispatcher(LoadedApk.java:863)
02-25 11:23:19.127: E/ActivityThread(603):  at android.app.ContextImpl.bindService(ContextImpl.java:1418)
02-25 11:23:19.127: E/ActivityThread(603):  at android.app.ContextImpl.bindService(ContextImpl.java:1407)
02-25 11:23:19.127: E/ActivityThread(603):  at android.content.ContextWrapper.bindService(ContextWrapper.java:473)
02-25 11:23:19.127: E/ActivityThread(603):  at com.android.emailcommon.service.ServiceProxy.setTask(ServiceProxy.java:157)
02-25 11:23:19.127: E/ActivityThread(603):  at com.android.emailcommon.service.ServiceProxy.setTask(ServiceProxy.java:145)
02-25 11:23:19.127: E/ActivityThread(603):  at com.android.emailcommon.service.ServiceProxy.test(ServiceProxy.java:191)
02-25 11:23:19.127: E/ActivityThread(603):  at com.android.exchange.ExchangeService$7.run(ExchangeService.java:1850)
02-25 11:23:19.127: E/ActivityThread(603):  at com.android.emailcommon.utility.Utility$2.doInBackground(Utility.java:551)
02-25 11:23:19.127: E/ActivityThread(603):  at android.os.AsyncTask$2.call(AsyncTask.java:287)
02-25 11:23:19.127: E/ActivityThread(603):  at java.util.concurrent.FutureTask.run(FutureTask.java:234)
02-25 11:23:19.127: E/ActivityThread(603):  at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1080)
02-25 11:23:19.127: E/ActivityThread(603):  at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:573)
02-25 11:23:19.127: E/ActivityThread(603):  at java.lang.Thread.run(Thread.java:856)
02-25 11:23:19.127: W/ActivityManager(288): Unable to start service Intent { act=com.android.email.ACCOUNT_INTENT } U=0: not found
02-25 11:23:19.237: E/StrictMode(603): null
02-25 11:23:19.237: E/StrictMode(603): android.app.ServiceConnectionLeaked: Service com.android.exchange.ExchangeService has leaked ServiceConnection com.android.emailcommon.service.ServiceProxy$ProxyConnection@40d2b0e0 that was originally bound here
02-25 11:23:19.237: E/StrictMode(603):  at android.app.LoadedApk$ServiceDispatcher.<init>(LoadedApk.java:969)
02-25 11:23:19.237: E/StrictMode(603):  at android.app.LoadedApk.getServiceDispatcher(LoadedApk.java:863)
02-25 11:23:19.237: E/StrictMode(603):  at android.app.ContextImpl.bindService(ContextImpl.java:1418)
02-25 11:23:19.237: E/StrictMode(603):  at android.app.ContextImpl.bindService(ContextImpl.java:1407)
02-25 11:23:19.237: E/StrictMode(603):  at android.content.ContextWrapper.bindService(ContextWrapper.java:473)
02-25 11:23:19.237: E/StrictMode(603):  at com.android.emailcommon.service.ServiceProxy.setTask(ServiceProxy.java:157)
02-25 11:23:19.237: E/StrictMode(603):  at com.android.emailcommon.service.ServiceProxy.setTask(ServiceProxy.java:145)
02-25 11:23:19.237: E/StrictMode(603):  at com.android.emailcommon.service.ServiceProxy.test(ServiceProxy.java:191)
02-25 11:23:19.237: E/StrictMode(603):  at com.android.exchange.ExchangeService$7.run(ExchangeService.java:1850)
02-25 11:23:19.237: E/StrictMode(603):  at com.android.emailcommon.utility.Utility$2.doInBackground(Utility.java:551)
02-25 11:23:19.237: E/StrictMode(603):  at com.android.emailcommon.utility.Utility$2.doInBackground(Utility.java:549)
02-25 11:23:19.237: E/StrictMode(603):  at android.os.AsyncTask$2.call(AsyncTask.java:287)
02-25 11:23:19.237: E/StrictMode(603):  at java.util.concurrent.FutureTask.run(FutureTask.java:234)
02-25 11:23:19.237: E/StrictMode(603):  at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1080)
02-25 11:23:19.237: E/StrictMode(603):  at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:573)
02-25 11:23:19.237: E/StrictMode(603):  at java.lang.Thread.run(Thread.java:856)
02-25 11:23:19.237: W/ActivityManager(288): Unbind failed: could not find connection for android.os.BinderProxy@40e43db8
02-25 11:23:19.277: D/dalvikvm(603): GC_CONCURRENT freed 358K, 17% free 2448K/2928K, paused 74ms+4ms, total 144ms
02-25 11:23:41.287: W/ActivityManager(288): Unable to start service Intent { flg=0x4 cmp=com.example.newsapp/.MainActivity$NotificationService (has extras) } U=0: not found

有任何想法嗎? 提前致謝。

一個小例子:

這是工作代碼。 它每10分鍾喚醒一次CPU,直到手機關閉。

添加到Manifest.xml:

...
<uses-permission android:name="android.permission.WAKE_LOCK"></uses-permission>
...
<receiver  android:process=":remote" android:name="Alarm"></receiver>
...

碼:

    package YourPackage;
    import android.app.AlarmManager;
    import android.app.PendingIntent;
    import android.content.BroadcastReceiver;
    import android.content.Context;
    import android.content.Intent;
    import android.os.PowerManager;
    import android.widget.Toast;

    public class Alarm extends BroadcastReceiver 
    {    
         @Override
         public void onReceive(Context context, Intent intent) 
         {   
             PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
             PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "");
             wl.acquire();

             // Put here YOUR code.
             Toast.makeText(context, "Alarm !!!!!!!!!!", Toast.LENGTH_LONG).show(); // For example

             wl.release();
         }

     public void SetAlarm(Context context)
     {
         AlarmManager am=(AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
         Intent i = new Intent(context, Alarm.class);
         PendingIntent pi = PendingIntent.getBroadcast(context, 0, i, 0);
         am.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), 1000 * 60 * 10, pi); // Millisec * Second * Minute
     }

     public void CancelAlarm(Context context)
     {
         Intent intent = new Intent(context, Alarm.class);
         PendingIntent sender = PendingIntent.getBroadcast(context, 0, intent, 0);
         AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
         alarmManager.cancel(sender);
     }
 }

從服務設置警報:

package YourPackage;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.os.IBinder;

public class YourService extends Service
{
    Alarm alarm = new Alarm();
    public void onCreate()
    {
        super.onCreate();       
    }

    public void onStart(Context context,Intent intent, int startId)
    {
        alarm.SetAlarm(context);
    }

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

如果要在手機啟動時重復設置鬧鍾:

向Manifest.xml添加權限:

<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"></uses-permission>
...
<receiver android:name=".AutoStart">
    <intent-filter>
        <action android:name="android.intent.action.BOOT_COMPLETED"></action>
    </intent-filter>
</receiver>
...

並創建新類:

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

public class AutoStart extends BroadcastReceiver
{   
    Alarm alarm = new Alarm();
    @Override
    public void onReceive(Context context, Intent intent)
    {   
        if (intent.getAction().equals("android.intent.action.BOOT_COMPLETED"))
        {
            alarm.SetAlarm(context);
        }
    }
}

還要注意:重新啟動電話后,警報將消失,您可能必須實現引導廣播接收器才能使其持續存在。 確保不執行該運行時,您需要在清單中實現它,否則當您的應用程序不在后台運行時,您將不會收到任何廣播。

請考慮以下事實:在引導時資源競爭激烈,因此,如果不啟動服務,則應等待一段時間。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM