如何使用报警管理器调用扩展服务的类?

时间:2014-02-25 11:30:52

标签: java android class service alarmmanager

我正在尝试为通知创建服务,该服务将在启动设备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类没有作为服务启动,我相信它没有被调用。我只想调用onStartCommand类中的NotificationService函数,因此它将调用handleIntent方法&amp;然后它将通过调用Web服务方法来检查通知。

2分钟过后&amp;是时候开始NotificationService我得到这个logcat:

    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

有什么想法吗?提前谢谢。

1 个答案:

答案 0 :(得分:0)

一个小例子:

这是有效的代码。它会每隔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);
        }
    }
}

还有一个注意事项:重新启动手机后会擦除警报,您可能必须实施启动广播接收器才能使其持久化。确保你没有那个运行时,你需要在你的应用程序不在后台的Manifest中实现它,你将不会收到任何广播。

请注意这样一个事实,即在启动时资源是高度争用的,因此您应该等待一段时间而不是解雇服务。