2016-09-29 10 views
9

Muszę wydrukować wszystkie przychodzące wiadomości e-mail o 9 rano każdego ranka. Oto, co próbowałem.Android: Jak sprawdzić wiadomość e-mail w określonym czasie za pomocą aplikacji AlarmManager?

Część e-mail działa poprawnie. Jestem w stanie połączyć się z pocztą e-mail i wydrukować je wszystkie. Problem pojawia się po wprowadzeniu Menedżera alarmów. Kiedy go uruchomię, nic się nie dzieje. To po prostu wisi

MainActivity.java

import android.annotation.TargetApi; 
import android.app.Activity; 
import android.app.AlarmManager; 
import android.app.PendingIntent; 
import android.app.job.JobInfo; 
import android.app.job.JobScheduler; 
import android.content.ComponentName; 
import android.content.Context; 
import android.content.Intent; 
import android.os.Build; 
import android.support.v7.app.AppCompatActivity; 
import android.os.Bundle; 
import android.util.Log; 
import android.view.View; 
import android.widget.Toast; 
import java.util.Calendar; 
import java.util.GregorianCalendar; 
import java.util.Properties; 
import javax.mail.*; 

public class MainActivity extends Activity { 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_main); 
    } 

    @TargetApi(Build.VERSION_CODES.LOLLIPOP) 
    public void checkEmail(View view) { 
     Log.d("test", "accessing gmail"); 

     Calendar cur_cal = new GregorianCalendar(); 
     cur_cal.setTimeInMillis(System.currentTimeMillis());//set the current time and date for this calendar 

     Calendar cal = new GregorianCalendar(); 
     cal.add(Calendar.DAY_OF_YEAR, cur_cal.get(Calendar.DAY_OF_YEAR)); 
     cal.set(Calendar.HOUR_OF_DAY, 9); 
     cal.set(Calendar.MINUTE, 0); 
     cal.set(Calendar.SECOND, cur_cal.get(Calendar.SECOND)); 
     cal.set(Calendar.MILLISECOND, cur_cal.get(Calendar.MILLISECOND)); 
     cal.set(Calendar.DATE, cur_cal.get(Calendar.DATE)); 
     cal.set(Calendar.MONTH, cur_cal.get(Calendar.MONTH)); 


     // create an Intent 
     Intent intentAlarm = new Intent(this, AlarmReceiver.class); 
     PendingIntent pi = PendingIntent.getService(this, 0, intentAlarm, 0); 

     // create the object 
     AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE); 

     //set the alarm for 9 AM 
     alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), 1000 * 5, pi); 

     Toast.makeText(this, "Alarm Scheduled for 9 AM", Toast.LENGTH_LONG).show(); 

    } 


} 

activity_main.xml

<?xml version="1.0" encoding="utf-8"?> 
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    xmlns:tools="http://schemas.android.com/tools" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    android:paddingBottom="@dimen/activity_vertical_margin" 
    android:paddingLeft="@dimen/activity_horizontal_margin" 
    android:paddingRight="@dimen/activity_horizontal_margin" 
    android:paddingTop="@dimen/activity_vertical_margin" 
    tools:context="com.example.admin.myapplication.MainActivity"> 

    <TextView 
     android:layout_width="wrap_content" 
     android:textSize="24sp" 
     android:layout_height="wrap_content" 
     android:text="Email Checker" 
     android:id="@+id/textView2" /> 

    <Button 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:text="New Button" 
     android:id="@+id/button" 
     android:layout_alignParentBottom="true" 
     android:layout_centerHorizontal="true" 
     android:layout_marginBottom="152dp" 
     android:onClick="checkEmail"/> 


</RelativeLayout> 

AlarmReceiver.java (aktualizacja klasa)

import android.content.BroadcastReceiver; 
import android.content.Context; 
import android.content.Intent; 
import android.telephony.SmsManager; 
import android.util.Log; 
import android.widget.Toast; 



public class AlarmReceiver extends BroadcastReceiver 
{ 
    @Override 
    public void onReceive(Context context, Intent intent) 
    { 
     Intent i = new Intent(context, AsyncTaskActvity.class); 
    i.putExtra("foo", "bar"); 
    context.startService(i); 
     Log.d("test", "async"); 
     Toast.makeText(context, "Alarm Triggered", Toast.LENGTH_LONG).show(); 
    } 

} 

AsyncTaskActvity.java

package com.example.admin.myapplication; 

import android.os.AsyncTask; 
import android.util.Log; 
import java.util.Properties; 
import javax.mail.Folder; 
import javax.mail.Message; 
import javax.mail.Session; 
import javax.mail.Store; 

public class AsyncTaskActvity extends AsyncTask { 


    @Override 
    protected Object doInBackground(Object[] params) { 

     computerUp(); 

     return null; 


    } 

    protected boolean computerUp() { 



     try { 

      Properties props = java.lang.System.getProperties(); 
      props.setProperty("mail.store.protocol", "imaps"); 
      Session session = Session.getDefaultInstance(props, null); 
      Store store = session.getStore("imaps"); 
      store.connect("imap.gmail.com", "[email protected]", "mypassword"); 
      Session s = Session.getInstance(props); 


      Message[] msgs; 


      Folder inbox = store.getFolder("Inbox"); 
      inbox.open(Folder.READ_ONLY); 
      msgs = inbox.getMessages(); 

      for (int i = 0; i < msgs.length; i++) { 
       msgs[i].getSubject(); 
       Log.d("test", msgs[i].getSubject()); 
      } 

     } catch (Exception e) { 
      Log.e(e.getClass().getName(), e.getMessage(), e); 
     } 

     return true; 
    } 


} 

Kiedy uruchamiam go, nic się nie dzieje. Co ja robię źle?

+0

proszę, przeczytaj moją odpowiedź. Masz wiele błędów. – Vyacheslav

Odpowiedz

5

Przede wszystkim, jeśli chcesz uruchomić jakiś kod wewnątrz urządzenia z systemem Android musisz użyć tego:

  1. AlarmManager który uruchamia BroadcastReceiver
  2. użyć WakeupBroadcastReceiver, aby obudzić urządzenie.
  3. Podczas uruchamiania kodu używaj stanu pobudki urządzenia z Androidem.
  4. Nie zapomnij naładować baterii po ponownym uruchomieniu urządzenia.
  5. MASZ PROBLEM PRZY URUCHOMIENIU ASYNCTASK !!!
  6. Masz nieprawidłową implementację alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), 1000 * 5, pi);. ten ciąg oznacza: "wykonaj mój kod co 5 sekund. Uruchom teraz!". To nie jest czas 9AM;)

Więc spróbuj tego:

  1. Aby naładować AlarmManager w określonym czasie:
Intent intent = new Intent(BRWakeup.INTENT_FILTER) ; 

     PendingIntent pi = PendingIntent.getBroadcast(ctx, intentalarm, intent, PendingIntent.FLAG_CANCEL_CURRENT); 
     int currentapiVersion = android.os.Build.VERSION.SDK_INT; 
     if (currentapiVersion < android.os.Build.VERSION_CODES.KITKAT){ 
      am.set(wakeup?AlarmManager.RTC_WAKEUP:AlarmManager.RTC, nexttime, pi); 
     } else if (currentapiVersion >= android.os.Build.VERSION_CODES.LOLLIPOP) 
      if (currentapiVersion < android.os.Build.VERSION_CODES.M) { 
       am.setExact(AlarmManager.RTC_WAKEUP, nexttime, pi); 
      } else { 
        am.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, nexttime, pi); 
      } 
     } 

gdzie ctx - prąd Context klasa (klasa macierzysta dla Activity i Service). Na przykład w klasie Activity jest to getContext() lub getActivity(). nexttime - czas na odbiór odbiornika.Na przykład: long nexttime = System.getCurrentTimeMillis();, AlarmManager am = (AlarmManager) ctx.getSystemService(Activity.ALARM_SERVICE);, intentalarm - to unikalny numer, który wykrywa to wydarzenie uruchomieniowe w przyszłości. Może to być dowolna liczba, ale stała w aplikacji. Na przykład, final int intentalarm = 22344;

  1. Aby uruchomić usługę z BroadcastReceiver:
public class BRWakeup extends WakefulBroadcastReceiver { 
    public static final String INTENT_FILTER = "com.example.BRWakeup"; 
    @Override 
    public void onReceive(Context ctx, Intent intent) { 
     // TODO Auto-generated method stub 
     OWakeLocker.acquire(ctx, 0); 
     ComponentName comp = new ComponentName(ctx.getPackageName(), 
       SService.class.getName()); 
     startWakefulService(ctx, intent.setComponent(comp)); 
    } 

} 
  1. OWakeLocker jest moja własna klasa która przechowuje wszystkie uruchomione usługi, aby uratować ich życie.
public class OWakeLocker { 
    private static PowerManager.WakeLock[] wakeLocks = new PowerManager.WakeLock[1];//Services count 

    @SuppressWarnings("deprecation") 
    public static void acquire(Context ctx, int index) { 
     WakeLock wakeLock = wakeLocks[index]; 
     if (wakeLock != null) wakeLock.release(); 

     PowerManager pm = (PowerManager) ctx.getSystemService(Context.POWER_SERVICE); 
      wakeLock = pm.newWakeLock(PowerManager.FULL_WAKE_LOCK | 
        PowerManager.ACQUIRE_CAUSES_WAKEUP | 
        PowerManager.ON_AFTER_RELEASE, _.APPNAME + Integer.toString(index)); 
     if (wakeLock != null && wakeLock.isHeld()){ 
      wakeLock.acquire(); 
     } 
    } 

    public static void release(int index) { 
     WakeLock wakeLock = wakeLocks[index]; 
     if (wakeLock != null) 
      wakeLock.release(); 
      wakeLock = null; 
    } 
} 
  1. skorzystać z tej usługi, aby wykonać swój kod:
public class SService extends Service { 

@Override 
    public void onCreate() { 
     OWakeLocker.acquire(this, 0); 
     super.onCreate(); 
} 
@Override 
    public void onDestroy() { 
     super.onDestroy(); 
     OWakeLocker.release(_.indexNOTS_TAT); 
    } 
@Override 
    public int onStartCommand(Intent intent, int flags, int startId) { 
     //your code to start AsyncTask 

AsyncTaskActvity atask = new AsyncTaskActvity(); 
    atsk.execute(); 
} 
} 
  1. Aby obliczyć dobry czas 9AM musisz użyć tego kodu: czas i dat e tego kalendarza
 Calendar cal = Calendar.getInstance(); 
boolean iftoday = cal.get(Calendar.HOUR_OF_DAY) < 9; 

//to set the time as exact 
     cal.set(Calendar.HOUR_OF_DAY, 9); 
     cal.set(Calendar.MINUTE, 0); 
     cal.set(Calendar.SECOND, 0); 
     cal.set(Calendar.MILLISECOND, 0); 

     if (!iftoday) { 
      cal.add(Calendar.DATE, 1); 
     } 
     long nexttime = cal.getTimeInMillis();//this is the correct next time. 
  1. Zastosowanie setExactAndAllowWhileIdle zamiast setRepeating.... I naładować AlarmManager na SService.onDestroy() metody przy użyciu tego samego kodu, jak w Activity

  2. Edytuj AndroidManifest.xml

<receiver android:name="com.example.BRWakeup" 
      android:exported="false"> 
      <intent-filter> 
       <action android:name="com.example.BRWakeup"/> 
      </intent-filter> 
     </receiver> 
<service android:name="com.example.SService"></service> 
+0

Dziękuję. Czy mógłbyś opublikować pełny kod dla tych zmiennych: 'am'.'intentalarm', nexttime,' ctx' thery nie są nigdzie inicjowane. Skąd oni pochodzą z – john

+0

Mam zaktualizowany mój post – Vyacheslav

3

Skorzystaj z usługi Intent-Service z odbiornikiem Broadcast.

Obserwuj poniżej linku z przykładu:

Background Service

public class MyAlarmReceiver extends BroadcastReceiver { 
    public static final int REQUEST_CODE = 12345; 
    public static final String ACTION = "com.codepath.example.servicesdemo.alarm"; 
// Triggered by the Alarm periodically (starts the service to run task) 
    @Override 
    public void onReceive(Context context, Intent intent) { 
    Intent i = new Intent(context, MyTestService.class); 
    i.putExtra("foo", "bar"); 
    context.startService(i); 
    } 
} 
+0

Dziękuję. też tego próbowałem. 'Intent i = new Intent (kontekst, AsyncTaskActvity.class); i.putExtra ("foo", "bar"); context.startService (i); 'Nadal ten sam wynik. Nic się nie dzieje – john

+0

proszę zaktualizować swoje pytanie ze zmianami w kodzie, więc będę mógł sprawdzić, również dostarczyć kod manifestu –

+0

Zaktualizowałem AlarmReceiver.java **, ale nadal nie działa ** – john

3

Przede wszystkim zmienić swój kod w metodzie checkEmail() do:

@TargetApi(Build.VERSION_CODES.LOLLIPOP) 
public void checkEmail(View view) { 
    Log.d("test", "accessing gmail"); 
    //set the current time and date for this calendar 
    Calendar cal = new GregorianCalendar(); 
    cal.add(Calendar.DAY_OF_YEAR, 1); 
    cal.set(Calendar.HOUR_OF_DAY, 9); 
    cal.set(Calendar.MINUTE, 0); 

    // create an Intent 
    Intent intentAlarm = new Intent(this, AlarmReceiver.class); 
    PendingIntent pi = PendingIntent.getBroadcast(this, 0, intentAlarm, 0); 

    // create the object 
    AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE); 

    //set the alarm for 9 AM 
    alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), AlarmManager.INTERVAL_DAY, pi); 

    Toast.makeText(this, "Alarm Scheduled for 9 AM", Toast.LENGTH_LONG).show(); 
} 

W AlarmReceiver.java klasy (upewnij się, że ten odbiornik już zarejestrowany w oczywisty z akcji niestandardowej w intent-filter tag):

@Override 
public void onReceive(Context context, Intent intent) { 
    new AsyncTaskActvity().execute(); 
    Log.d("test", "async"); 
    Toast.makeText(context, "Alarm Triggered", Toast.LENGTH_LONG).show(); 
} 

Głównym problemem dlaczego masz błąd jest, to nazywa startService() do klasy, które nie rozciągają Service , tj. AsyncTaskActvity. Musisz znaleźć różnicę między Service i AsyncTask.

Powiązane problemy