HMS Awareness Kit - Single AwarenessBarrier Instance - Multiple day codes or time period - huawei-mobile-services

We wanted to use single Awareness Barrier instance for multiple day code or time period. But couldn't find the param for passing in the methods , duringTimePeriod(), duringPeriodOfWeek(), inSunriseOrSunsetPeriod()

By seeing your use-case, you can use or(AwarenessBarrier awarenessBarrier) method of AwarenessBarrier class:
https://developer.huawei.com/consumer/en/doc/development/HMSCore-References-V5/awareness-barrier-awarenessbarrier-0000001050164120-V5
String timeBarrierLabel = "period of day barrier";
BarrierUpdateRequest.Builder builder = new BarrierUpdateRequest.Builder();
AwarenessBarrier periodOfWeekBarrier1 = TimeBarrier.duringPeriodOfWeek(TimeBarrier.WEDNESDAY_CODE,TimeZone.getDefault(), 9 * oneHourMilliSecond, 20 * oneHourMilliSecond);
AwarenessBarrier periodOfWeekBarrier2 = TimeBarrier.duringPeriodOfWeek(TimeBarrier.WEDNESDAY_CODE||,TimeZone.getDefault(), 9 * oneHourMilliSecond, 20 * oneHourMilliSecond);
BarrierUpdateRequest request = builder.
addBarrier(timeBarrierLabel, AwarenessBarrier.or(periodOfWeekBarrier1,periodOfWeekBarrier2) ,).build();

You can set TimeBarrier per time requirement and add, for example
#Override
public void onClick(View v) {
long oneHourMilliSecond = 60 * 60 * 1000L;
switch (v.getId()) {
case R.id.add_timeBarrier_inSunriseOrSunsetPeriod:
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
return;
}
AwarenessBarrier sunsetBarrier = TimeBarrier.inSunriseOrSunsetPeriod(TimeBarrier.SUNSET_CODE,
-oneHourMilliSecond, oneHourMilliSecond);
Utils.addBarrier(this, IN_SUNRISE_OR_SUNSET_PERIOD_BARRIER_LABEL,
sunsetBarrier, mPendingIntent);
break;
case R.id.add_timeBarrier_duringPeriodOfDay:
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
return;
}
AwarenessBarrier periodOfDayBarrier = TimeBarrier.duringPeriodOfDay(TimeZone.getDefault(),
11 * oneHourMilliSecond, 12 * oneHourMilliSecond);
Utils.addBarrier(this, DURING_PERIOD_OF_DAT_BARRIER_LABEL, periodOfDayBarrier,
mPendingIntent);
break;
case R.id.add_timeBarrier_duringTimePeriod:
long currentTimeStamp = System.currentTimeMillis();
long tenSecondsMillis = 10 * 1000L;
AwarenessBarrier timePeriodBarrier = TimeBarrier.duringTimePeriod(currentTimeStamp,
currentTimeStamp + tenSecondsMillis);
Utils.addBarrier(this, DURING_TIME_PERIOD_BARRIER_LABEL,
timePeriodBarrier, mPendingIntent);
break;
case R.id.add_timeBarrier_duringPeriodOfWeek:
AwarenessBarrier periodOfWeekBarrier = TimeBarrier.duringPeriodOfWeek(TimeBarrier.MONDAY_CODE,
TimeZone.getDefault(), 9 * oneHourMilliSecond, 10 * oneHourMilliSecond);
Utils.addBarrier(this, DURING_PERIOD_OF_WEEK_BARRIER_LABEL,
periodOfWeekBarrier, mPendingIntent);
break;
case R.id.add_timeBarrier_inTimeCategory:
AwarenessBarrier inTimeCategoryBarrier = TimeBarrier.inTimeCategory(TimeBarrier.TIME_CATEGORY_WEEKEND);
Utils.addBarrier(this, IN_TIME_CATEGORY_LABEL, inTimeCategoryBarrier, mPendingIntent);
break;
case R.id.delete_barrier:
Utils.deleteBarrier(this, mPendingIntent);
break;
default:
break;
}
public static void addBarrier(Context context, final String label, AwarenessBarrier barrier, PendingIntent pendingIntent) {
BarrierUpdateRequest.Builder builder = new BarrierUpdateRequest.Builder();
// When the status of the registered barrier changes, pendingIntent is triggered.
// label is used to uniquely identify the barrier. You can query a barrier by label and delete it.
BarrierUpdateRequest request = builder.addBarrier(label, barrier, pendingIntent).build();
Awareness.getBarrierClient(context).updateBarriers(request)
.addOnSuccessListener(new OnSuccessListener<Void>() {
#Override
public void onSuccess(Void aVoid) {
showToast(context, "add barrier success");
}
})
.addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(Exception e) {
showToast(context, "add barrier failed");
Log.e(TAG, "add barrier failed", e);
}
});
}
Please refer Link for the sample code.

Related

Loading delay exceeded warning - Programmer Instrument - Unity

I'm getting an warning that says ": Loading delay exceeded, sound may play at incorrect time" whenever I try to use the example code from FMOD for Programmer Instrument
I thought maybe I need to wait for the FMOD.Sound openState == READY, but that doesn't seem to have worked. Am I missing something? Here's my code:
public static void PlayDialogue(string key, Action callback = null)
{
// Create Instance
FMOD.Studio.EventInstance dialogueInstance = FMODUnity.RuntimeManager.CreateInstance(instance.dialogueEvent);
// Pin the key string in memory and pass a pointer through the user data
GCHandle stringHandle = GCHandle.Alloc(key, GCHandleType.Pinned);
dialogueInstance.setUserData(GCHandle.ToIntPtr(stringHandle));
dialogueInstance.setCallback(instance.dialogueCallback);
}
[AOT.MonoPInvokeCallback(typeof(FMOD.Studio.EVENT_CALLBACK))]
static FMOD.RESULT DialogueCallback(FMOD.Studio.EVENT_CALLBACK_TYPE type, IntPtr instancePtr, IntPtr parameterPtr)
{
// Get Instance
FMOD.Studio.EventInstance instance = new FMOD.Studio.EventInstance(instancePtr);
// Retrieve the user data
IntPtr stringPtr;
instance.getUserData(out stringPtr);
// Get the string object
GCHandle stringHandle = GCHandle.FromIntPtr(stringPtr);
String key = stringHandle.Target as String;
switch (type)
{
case FMOD.Studio.EVENT_CALLBACK_TYPE.CREATE_PROGRAMMER_SOUND:
{
FMOD.MODE soundMode = FMOD.MODE.LOOP_NORMAL
| FMOD.MODE.CREATECOMPRESSEDSAMPLE
| FMOD.MODE.NONBLOCKING;
FMOD.Studio.PROGRAMMER_SOUND_PROPERTIES programmerSoundProperties =
(FMOD.Studio.PROGRAMMER_SOUND_PROPERTIES)Marshal.PtrToStructure(
parameterPtr, typeof(FMOD.Studio.PROGRAMMER_SOUND_PROPERTIES));
FMOD.Sound dialogueSound;
if (key.Contains("."))
{
// Load Sound by Given Path
FMOD.RESULT soundResult = FMODUnity.RuntimeManager.CoreSystem.createSound(
Application.streamingAssetsPath + "/" + key, soundMode, out dialogueSound);
if (soundResult == FMOD.RESULT.OK)
{
programmerSoundProperties.sound = dialogueSound.handle;
programmerSoundProperties.subsoundIndex = -1;
Marshal.StructureToPtr(programmerSoundProperties, parameterPtr, false);
// Wait To Play
WaitForLoadThenPlay(instancePtr, parameterPtr);
}
}
else
{
// Load Sound Path
FMOD.Studio.SOUND_INFO dialogueSoundInfo;
FMOD.RESULT keyResult = FMODUnity.RuntimeManager.StudioSystem.getSoundInfo(key, out dialogueSoundInfo);
if (keyResult != FMOD.RESULT.OK) break;
// Load Sound
FMOD.RESULT soundResult = FMODUnity.RuntimeManager.CoreSystem.createSound(
dialogueSoundInfo.name_or_data, soundMode | dialogueSoundInfo.mode, ref dialogueSoundInfo.exinfo, out dialogueSound);
if (soundResult == FMOD.RESULT.OK)
{
programmerSoundProperties.sound = dialogueSound.handle;
programmerSoundProperties.subsoundIndex = dialogueSoundInfo.subsoundindex;
Marshal.StructureToPtr(programmerSoundProperties, parameterPtr, false);
// Wait To Play
WaitForLoadThenPlay(instancePtr, parameterPtr);
}
}
break;
}
case FMOD.Studio.EVENT_CALLBACK_TYPE.DESTROY_PROGRAMMER_SOUND:
{
FMOD.Studio.PROGRAMMER_SOUND_PROPERTIES parameter =
(FMOD.Studio.PROGRAMMER_SOUND_PROPERTIES)Marshal.PtrToStructure(
parameterPtr, typeof(FMOD.Studio.PROGRAMMER_SOUND_PROPERTIES));
FMOD.Sound sound = new FMOD.Sound(parameter.sound);
sound.release();
break;
}
case FMOD.Studio.EVENT_CALLBACK_TYPE.DESTROYED:
{
// Now the event has been destroyed, unpin the string memory so it can be garbage collected
stringHandle.Free();
break;
}
}
return FMOD.RESULT.OK;
}
private static void WaitForLoadThenPlay(IntPtr instancePtr, IntPtr parameterPtr)
=> instance.StartCoroutine(instance.WaitForLoadThenPlayRoutine(instancePtr, parameterPtr));
private IEnumerator WaitForLoadThenPlayRoutine(IntPtr instancePtr, IntPtr parameterPtr)
{
// Get Instance
FMOD.Studio.EventInstance instance = new FMOD.Studio.EventInstance(instancePtr);
// Grab Sound Reference
FMOD.Studio.PROGRAMMER_SOUND_PROPERTIES parameter =
(FMOD.Studio.PROGRAMMER_SOUND_PROPERTIES)Marshal.PtrToStructure(
parameterPtr, typeof(FMOD.Studio.PROGRAMMER_SOUND_PROPERTIES));
FMOD.Sound sound = new FMOD.Sound(parameter.sound);
// Wait for Load
FMOD.OPENSTATE state = FMOD.OPENSTATE.BUFFERING;
uint percentbuffered;
bool starving;
bool diskbusy;
while (state != FMOD.OPENSTATE.READY)
{
yield return null;
sound.getOpenState(out state, out percentbuffered, out starving, out diskbusy);
}
instance.start();
instance.release();
}
Here's what I ended up doing. I don't know if it makes sense or not, but it does get rid of the warnings. I really wish they'd fix the documentation. The example script doesn't work properly.
public static void PlayDialogue(string key, Action callback = null) => instance.StartCoroutine(PlayDialogueRoutine(key, callback));
public static IEnumerator PlayDialogueRoutine(string key, Action callback = null)
{
// Check if Already Playing
if (instance.activeDialogue.ContainsKey(key))
{
Debug.LogError("Tried to play already playing dialogue");
callback?.Invoke();
yield break;
}
// Load Sound Path
FMOD.Studio.SOUND_INFO dialogueSoundInfo;
FMOD.RESULT keyResult = FMODUnity.RuntimeManager.StudioSystem.getSoundInfo(key, out dialogueSoundInfo);
if (keyResult != FMOD.RESULT.OK)
{
Debug.LogError("Couldn't find dialogue with key: " + key);
callback?.Invoke();
yield break;
}
// Load Sound
FMOD.Sound dialogueSound;
FMOD.MODE soundMode = FMOD.MODE.LOOP_NORMAL
| FMOD.MODE.CREATECOMPRESSEDSAMPLE
| FMOD.MODE.NONBLOCKING;
FMOD.RESULT soundResult = FMODUnity.RuntimeManager.CoreSystem.createSound(
dialogueSoundInfo.name_or_data, soundMode | dialogueSoundInfo.mode,
ref dialogueSoundInfo.exinfo, out dialogueSound);
if (soundResult != FMOD.RESULT.OK)
{
Debug.LogError("Couldn't load sound: " + key);
callback?.Invoke();
yield break;
}
// Wait to Load
int maxFrameWait = 120;
FMOD.OPENSTATE openstate = FMOD.OPENSTATE.BUFFERING;
uint percentbuffered;
bool starving;
bool diskbusy;
while (openstate != FMOD.OPENSTATE.READY)
{
yield return null;
dialogueSound.getOpenState(out openstate, out percentbuffered, out starving, out diskbusy);
if (--maxFrameWait <= 0)
{
dialogueSound.release();
Debug.LogError("Failed to load dialogue sound " + key);
yield break;
}
}
// Create Instance
FMOD.Studio.EventInstance dialogueInstance = FMODUnity.RuntimeManager.CreateInstance(instance.dialogueEvent);
// Store Reference (and remove in play stopped callback)
instance.activeDialogue[key] = dialogueInstance;
// Pin Memory
FMODDialogueParameterWrapper soundWrapper = new FMODDialogueParameterWrapper(dialogueSound, dialogueSoundInfo, () =>
{
instance.activeDialogue.Remove(key);
callback?.Invoke();
});
GCHandle soundWrapperHandle = GCHandle.Alloc(soundWrapper, GCHandleType.Pinned);
dialogueInstance.setUserData(GCHandle.ToIntPtr(soundWrapperHandle));
// Set Callback
dialogueInstance.setCallback(instance.dialogueCallback,
FMOD.Studio.EVENT_CALLBACK_TYPE.CREATE_PROGRAMMER_SOUND
| FMOD.Studio.EVENT_CALLBACK_TYPE.CREATE_PROGRAMMER_SOUND
| FMOD.Studio.EVENT_CALLBACK_TYPE.DESTROYED
| FMOD.Studio.EVENT_CALLBACK_TYPE.STOPPED);
// Play One Shot
dialogueInstance.start();
dialogueInstance.release();
}
[AOT.MonoPInvokeCallback(typeof(FMOD.Studio.EVENT_CALLBACK))]
static FMOD.RESULT DialogueCallback(FMOD.Studio.EVENT_CALLBACK_TYPE type, IntPtr instancePtr, IntPtr parameterPtr)
{
// Get Instance
FMOD.Studio.EventInstance instance = new FMOD.Studio.EventInstance(instancePtr);
// Retrieve the user data FMODDialogueParameterWrapper
IntPtr dialogueParameterWrapperPtr;
FMOD.RESULT result = instance.getUserData(out dialogueParameterWrapperPtr);
if (result != FMOD.RESULT.OK)
{
Debug.LogError("Failed to fetch user data for dialogue callback: " + result);
}
else if (dialogueParameterWrapperPtr != IntPtr.Zero)
{
GCHandle dialogueParameterWrapperHandle = GCHandle.FromIntPtr(dialogueParameterWrapperPtr);
FMODDialogueParameterWrapper dialogueParameterWrapper =
(FMODDialogueParameterWrapper)dialogueParameterWrapperHandle.Target;
switch (type)
{
case FMOD.Studio.EVENT_CALLBACK_TYPE.CREATE_PROGRAMMER_SOUND:
{
FMOD.Studio.PROGRAMMER_SOUND_PROPERTIES programmerSoundProperties =
(FMOD.Studio.PROGRAMMER_SOUND_PROPERTIES)Marshal.PtrToStructure(
parameterPtr, typeof(FMOD.Studio.PROGRAMMER_SOUND_PROPERTIES));
programmerSoundProperties.sound = dialogueParameterWrapper.sound.handle;
programmerSoundProperties.subsoundIndex = dialogueParameterWrapper.soundInfo.subsoundindex;
Marshal.StructureToPtr(programmerSoundProperties, parameterPtr, false);
break;
}
case FMOD.Studio.EVENT_CALLBACK_TYPE.DESTROY_PROGRAMMER_SOUND:
{
FMOD.Studio.PROGRAMMER_SOUND_PROPERTIES parameter =
(FMOD.Studio.PROGRAMMER_SOUND_PROPERTIES)Marshal.PtrToStructure(
parameterPtr, typeof(FMOD.Studio.PROGRAMMER_SOUND_PROPERTIES));
FMOD.Sound sound = new FMOD.Sound(parameter.sound);
sound.release();
break;
}
case FMOD.Studio.EVENT_CALLBACK_TYPE.DESTROYED:
{
// Now the event has been destroyed, unpin the string memory so it can be garbage collected
Debug.Log("Freeing");
dialogueParameterWrapperHandle.Free();
break;
}
case FMOD.Studio.EVENT_CALLBACK_TYPE.STOPPED:
{
dialogueParameterWrapper.onStopCallback?.Invoke();
break;
}
}
}
return FMOD.RESULT.OK;
}
[StructLayout(LayoutKind.Sequential)]
class FMODDialogueParameterWrapper
{
public FMOD.Sound sound;
public FMOD.Studio.SOUND_INFO soundInfo;
public Action onStopCallback;
public FMODDialogueParameterWrapper(FMOD.Sound sound, FMOD.Studio.SOUND_INFO soundInfo, Action onStopCallback)
{
this.sound = sound;
this.soundInfo = soundInfo;
this.onStopCallback = onStopCallback;
}
}

Alarm is not triggering when app is killed

I am facing a issue while adding a alarmManager.
Basicly I'm trying to add a alarm on specific time and it's working fine whether app is in background or in foreground. but the issue is that it's not going to trigger when app is removed from background or app is killed.
I want to trigger alarm whether app is running or not (issue faced when app is closed).
I'm little bit desperate.
Here is my Code :
public class AlarmReciver extends BroadcastReceiver {
public AlarmReciver(){
super();
}
#Override
public void onReceive(Context context, Intent intent) {
Log.d("called","called");
Toast.makeText(context, "Alarm received!", Toast.LENGTH_LONG).show();
//This will send a notification message and show notification in notification tray
/* ComponentName comp = new ComponentName(context.getPackageName(),
AlarmNotificationService.class.getName());
startWakefulService(context, (intent.setComponent(comp)));*/
try {
ManageDatabase manageDatabase = new ManageDatabase();
// manageDatabase.setupdatabase(context);
// For our recurring task, we'll just display a message
// Toast.makeText(context, "Alarm received!", Toast.LENGTH_LONG).show();
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
String today_date=String.valueOf(calendar.get(Calendar.DAY_OF_MONTH))+"/"+String.valueOf((calendar.get(Calendar.MONTH)+1))+"/"+String.valueOf(calendar.get(Calendar.YEAR));
today_date= datetimeformat.getdate(today_date);
String id = intent.getStringExtra("id").toString();
String pid = intent.getStringExtra("pid").toString();
manageDatabase.cancelallreminders_without_update(context);
manageDatabase.setallactivatedalarm(context);
manageDatabase.addtodaysidlist(id,today_date,context);
// Enable a receiver
/* ComponentName receiver = new ComponentName(context, AlarmReciver.class);
PackageManager pm = context.getPackageManager();
pm.setComponentEnabledSetting(receiver,
PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
PackageManager.DONT_KILL_APP);*/
Intent service1 = new Intent(context, Show_Reminder.class);
service1.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
service1.putExtra("id", id);
service1.putExtra("pid", pid);
context.startActivity(service1);
Toast.makeText(context,"alarm is triggered...", Toast.LENGTH_LONG).show();
Log.d("alarm is","triggered");
}catch (Exception e)
{
Log.e("error",e.toString());
e.printStackTrace();
}
}
}
Manifest file :
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<receiver android:name="com.pragma.healthopediaplus.Medicine_reminder.Utils.Reminders.AlarmReciver"
android:exported="false"
android:process=":remote">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.PACKAGE_RESTARTED" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.LOCKED_BOOT_COMPLETED" />
</intent-filter>
</receiver>
set alarm from database.java
public void setallactivatedalarm(Context context) {
db= context.openOrCreateDatabase("Reminder"+ SharedPreference.getvalue("username",context)+".db",Context.MODE_PRIVATE,null);
Cursor c1 = db.rawQuery("select * from reminderdata",null);
Log.d("Set all activate alarm","inside");
while (c1.moveToNext())
{
if(c1.getString(6).equals("active"))
{
Date date_type=new Date();
SimpleDateFormat format = new SimpleDateFormat("dd/MM/yyyy");
try {
Gson gson = new Gson();
ArrayList<Info> infodata = gson.fromJson(c1.getString(2), new TypeToken<ArrayList<Info>>() {
}.getType());
// Log.d("reminder", " setReminder " + c1.getString(1) + " " + c1.getString(3) + " " + c1.getString(5) + " " + infodata + " " + Integer.parseInt(c1.getString(4)) + " " + context + " " + Integer.parseInt(c1.getString(0)));
String alltime[]=infodata.get(7).getValue().split(",");
String maxtime= datetimeformat.gettimehhmm(alltime[0]);
String weekday;
for(int i=1;i<alltime.length;i++)
{
SimpleDateFormat sdf = new SimpleDateFormat("HH:mm");
Date inTime = sdf.parse(maxtime);
Date outTime = sdf.parse(datetimeformat.gettimehhmm(alltime[i]));
if(outTime.compareTo(inTime) > 0){
maxtime= datetimeformat.gettimehhmm(alltime[i]);
}
}
String timedata=maxtime;
String timearray[]=timedata.split(":");
date_type = format.parse(c1.getString(3));
Calendar newtime = Calendar.getInstance();
newtime.setTime(date_type);
newtime.set(Calendar.MINUTE,Integer.parseInt(timearray[1]));
newtime.set(Calendar.SECOND,00);
newtime.set(Calendar.HOUR_OF_DAY,Integer.parseInt(timearray[0]));
Calendar currenttime=Calendar.getInstance();
if(newtime.getTimeInMillis()<=currenttime.getTimeInMillis())
{
/* flag 1 for everyday 2 for month 3 for everyyear 4 onetime*/
if(c1.getString(4).equals("1"))
{
newtime.add(Calendar.DATE, 1);
}
else if(c1.getString(4).equals("2"))
{
newtime.add(Calendar.MONTH, 1);
}
else if(c1.getString(4).equals("3"))
{
newtime.add(Calendar.YEAR, 1);
}
else if(c1.getString(4).equals("5"))
{
int weekdayint = 0;
int dayOfWeek=newtime.get(Calendar.DAY_OF_WEEK);
String weekDay = null;
if (Calendar.MONDAY == dayOfWeek) {
weekdayint=Calendar.MONDAY;
weekDay = context.getString(R.string.Monday);
} else if (Calendar.TUESDAY == dayOfWeek) {
weekdayint=Calendar.TUESDAY;
weekDay = context.getString(R.string.Tuesday);
} else if (Calendar.WEDNESDAY == dayOfWeek) {
weekdayint=Calendar.WEDNESDAY;
weekDay = context.getString(R.string.Wednesday);
} else if (Calendar.THURSDAY == dayOfWeek) {
weekdayint=Calendar.THURSDAY;
weekDay = context.getString(R.string.Thursday);
} else if (Calendar.FRIDAY == dayOfWeek) {
weekdayint=Calendar.FRIDAY;
weekDay = context.getString(R.string.Friday);
} else if (Calendar.SATURDAY == dayOfWeek) {
weekdayint=Calendar.SATURDAY;
weekDay = context.getString(R.string.Saturday);
} else if (Calendar.SUNDAY == dayOfWeek) {
weekdayint=Calendar.SUNDAY;
weekDay = context.getString(R.string.Sunday);
}
weekday=infodata.get(9).getValue();
String day[]=weekday.split(",");
String next="";
int nxtday = 0;
int addday;
int count[]={1,2,3,4,5,6,7,1,2,3,4,5,6,7};
String getweek[]={"",context.getString(R.string.Sunday),context.getString(R.string.Monday),context.getString(R.string.Tuesday)
,context.getString(R.string.Wednesday), context.getString(R.string.Thursday),
context.getString(R.string.Friday),context.getString(R.string.Saturday)};
for(int i=weekdayint;i<weekdayint+7;i++)
{
int c=count[i];
if (Arrays.asList(day).contains(getweek[c])) {
next=getweek[c];
nxtday=c;
break;
}
}
if(nxtday>weekdayint)
{
addday=nxtday-weekdayint;
}else
{
addday=nxtday-weekdayint+7;
}
newtime.add(Calendar.DATE, addday);
}
int thisYear = newtime.get(Calendar.YEAR);
int thisMonth = newtime.get(Calendar.MONTH);
int thisDay = newtime.get(Calendar.DAY_OF_MONTH);
String newdate=thisDay+"/"+(thisMonth+1)+"/"+thisYear;
newdate=datetimeformat.getdate(newdate);
db.execSQL("update reminderdata set duedate='"+newdate+"'where id='"+c1.getString(0)+"'");
}
} catch (Exception e) {
// TODO Auto-generated catch block
Log.d("error",e.toString());
}
Gson gson = new Gson();
ArrayList<Info> infodata = gson.fromJson(c1.getString(2), new TypeToken<ArrayList<Info>>() {
}.getType());
// Log.d("reminder", " setReminder "+c1.getString(1)+" "+c1.getString(3)+" "+ c1.getString(5)+" "+ infodata+" "+Integer.parseInt(c1.getString(4))+" "+ context+" "+Integer.parseInt(c1.getString(0)));
String alltime[]=infodata.get(7).getValue().split(",");
Log.d("all time",infodata.get(7).getValue());
Log.d("all time length",alltime.length+"");
String pid[]=getPidsfromrid(Integer.parseInt(c1.getString(0)),context).split(",");
for(int i=0;i<alltime.length;i++)
{Log.d("pids",pid[i]);
Log.d("set reminder called",alltime[i]);
setReminder( c1.getString(3), context,
Integer.parseInt(c1.getString(0)),alltime[i],Integer.parseInt(pid[i]));
}
}
}
db.close();
}
public boolean setReminder(String date,Context context,int id,String time,int pid) {
Intent myIntent = new Intent(context, AlarmReciver.class);
myIntent.putExtra("id",String.valueOf(id));
myIntent.putExtra("pid",String.valueOf(pid));
AlarmManager alarmManager = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, myIntent,
0);
Date date_type=new Date();
SimpleDateFormat format = new SimpleDateFormat("dd/MM/yyyy");
try
{
date_type = format.parse(date);
} catch (Exception e) {
e.printStackTrace();
}
String timedata= datetimeformat.gettimehhmm(time);
String timearray[]=timedata.split(":");
Calendar calendar = Calendar.getInstance();
calendar.setTime(date_type);
calendar.set(Calendar.MINUTE,Integer.parseInt(timearray[1]));
calendar.set(Calendar.SECOND, 0);
calendar.set(Calendar.HOUR_OF_DAY,Integer.parseInt(timearray[0]));
Calendar current = Calendar.getInstance();
Log.d("set reminder inside",time);
if(calendar.compareTo(current) <= 0){
calendar.add(Calendar.DATE, 1);
Log.d("set reminder inside ","not set alarm"+time);
// Toast.makeText(context,"Invalid Date/Time",Toast.LENGTH_LONG).show();
} else{
Log.d("set reminder inside ","set alarm"+time);
Log.d("set reminder inside",time);
alarmManager.set(AlarmManager.RTC, calendar.getTimeInMillis(),
pendingIntent);
/* int SDK_INT = Build.VERSION.SDK_INT;
if (SDK_INT < Build.VERSION_CODES.KITKAT)
alarmManager.set(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), pendingIntent);
else if (Build.VERSION_CODES.KITKAT <= SDK_INT && SDK_INT < Build.VERSION_CODES.M)
alarmManager.setExact(AlarmManager.RTC_WAKEUP,
calendar.getTimeInMillis(), pendingIntent);
else if (SDK_INT >= Build.VERSION_CODES.M) {
alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP,
calendar.getTimeInMillis(), pendingIntent);
}
*/
/*if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
alarmManager.setExact(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis()+2000, pendingIntent);
}else {
alarmManager.set(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis()+2000, pendingIntent);
}*/
}
try {
//Thread.sleep(2000);
} catch (Exception e) {
e.printStackTrace();
}
return true;
}
Closing the app closes all the Alarms as well. What you need instead is to set up Alarms from a Background Service instead.
You can reuse almost all of your existing code, and will have to create an additional class (preferably in new file) for the service. You'll also have to register the service in the manifest file, and move the code for creating alarm into the service class.
Example for creating a background service is here: https://developer.android.com/training/run-background-service/create-service
Note the background services have some limitations, but they can be set to be active even after REBOOT of the device.
Depending on your use case, you could also look into JobScheduler, that can run periodically and use that to set Alarms (dynamically, or otherwise). If your Alarms don't have to be 'Exact', you can just get the task done in JobScheduler itself, as it's almost as accurate as Alarm Manager. I say this because after Android O, doze mode takes away accuracy of Alarm Manager as well as JobScheduler.

Passing values from android to flutter but not from main activity

i'm implementing a third party android sdk in flutter and i want a message to be passed from android to flutter when sdk starts
i have implemented the sdk using platform channel just need to work on the callback code. In the code there is a function called onChannelJoin i want to send message to flutter when this function is called
Main Activity
public class MainActivity extends FlutterActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
GeneratedPluginRegistrant.registerWith(this);
final String CHANNEL = "samples.flutter.io/screen_record";
new MethodChannel(getFlutterView(), CHANNEL).setMethodCallHandler(
new MethodChannel.MethodCallHandler() {
#Override
public void onMethodCall(MethodCall call, MethodChannel.Result result) {
// TODO
if (call.method.equals("startScreenShare")) {
Intent intent = new Intent(MainActivity.this , HelloAgoraScreenSharingActivity.class);
startActivity(intent);
} else {
result.notImplemented();
}
}
});
}
}
ScreenSharingActivity
public class HelloAgoraScreenSharingActivity extends Activity {
private static final String LOG_TAG = "AgoraScreenSharing";
private static final int PERMISSION_REQ_ID_RECORD_AUDIO = 22;
private ScreenCapture mScreenCapture;
private GLRender mScreenGLRender;
private RtcEngine mRtcEngine;
private boolean mIsLandSpace = false;
private void initModules() {
DisplayMetrics metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);
if (mScreenGLRender == null) {
mScreenGLRender = new GLRender();
}
if (mScreenCapture == null) {
mScreenCapture = new ScreenCapture(getApplicationContext(), mScreenGLRender, metrics.densityDpi);
}
mScreenCapture.mImgTexSrcConnector.connect(new SinkConnector<ImgTexFrame>() {
#Override
public void onFormatChanged(Object obj) {
Log.d(LOG_TAG, "onFormatChanged " + obj.toString());
}
#Override
public void onFrameAvailable(ImgTexFrame frame) {
Log.d(LOG_TAG, "onFrameAvailable " + frame.toString());
if (mRtcEngine == null) {
return;
}
AgoraVideoFrame vf = new AgoraVideoFrame();
vf.format = AgoraVideoFrame.FORMAT_TEXTURE_OES;
vf.timeStamp = frame.pts;
vf.stride = frame.mFormat.mWidth;
vf.height = frame.mFormat.mHeight;
vf.textureID = frame.mTextureId;
vf.syncMode = true;
vf.eglContext14 = mScreenGLRender.getEGLContext();
vf.transform = frame.mTexMatrix;
mRtcEngine.pushExternalVideoFrame(vf);
}
});
mScreenCapture.setOnScreenCaptureListener(new ScreenCapture.OnScreenCaptureListener() {
#Override
public void onStarted() {
Log.d(LOG_TAG, "Screen Record Started");
}
#Override
public void onError(int err) {
Log.d(LOG_TAG, "onError " + err);
switch (err) {
case ScreenCapture.SCREEN_ERROR_SYSTEM_UNSUPPORTED:
break;
case ScreenCapture.SCREEN_ERROR_PERMISSION_DENIED:
break;
}
}
});
WindowManager wm = (WindowManager) getApplicationContext()
.getSystemService(Context.WINDOW_SERVICE);
int screenWidth = wm.getDefaultDisplay().getWidth();
int screenHeight = wm.getDefaultDisplay().getHeight();
if ((mIsLandSpace && screenWidth < screenHeight) ||
(!mIsLandSpace) && screenWidth > screenHeight) {
screenWidth = wm.getDefaultDisplay().getHeight();
screenHeight = wm.getDefaultDisplay().getWidth();
}
setOffscreenPreview(screenWidth, screenHeight);
if (mRtcEngine == null) {
try {
mRtcEngine = RtcEngine.create(getApplicationContext(), "Agora_id", new IRtcEngineEventHandler() {
#Override
public void onJoinChannelSuccess(String channel, int uid, int elapsed) {
Log.d(LOG_TAG, "onJoinChannelSuccess " + channel + " " + elapsed);
}
#Override
public void onWarning(int warn) {
Log.d(LOG_TAG, "onWarning " + warn);
}
#Override
public void onError(int err) {
Log.d(LOG_TAG, "onError " + err);
}
#Override
public void onAudioRouteChanged(int routing) {
Log.d(LOG_TAG, "onAudioRouteChanged " + routing);
}
});
} catch (Exception e) {
Log.e(LOG_TAG, Log.getStackTraceString(e));
throw new RuntimeException("NEED TO check rtc sdk init fatal error\n" + Log.getStackTraceString(e));
}
mRtcEngine.setChannelProfile(Constants.CHANNEL_PROFILE_LIVE_BROADCASTING);
mRtcEngine.enableVideo();
if (mRtcEngine.isTextureEncodeSupported()) {
mRtcEngine.setExternalVideoSource(true, true, true);
} else {
throw new RuntimeException("Can not work on device do not supporting texture" + mRtcEngine.isTextureEncodeSupported());
}
mRtcEngine.setVideoProfile(Constants.VIDEO_PROFILE_360P, true);
mRtcEngine.setClientRole(Constants.CLIENT_ROLE_BROADCASTER);
}
}
private void deInitModules() {
RtcEngine.destroy();
mRtcEngine = null;
if (mScreenCapture != null) {
mScreenCapture.release();
mScreenCapture = null;
}
if (mScreenGLRender != null) {
mScreenGLRender.quit();
mScreenGLRender = null;
}
}
/**
* Set offscreen preview.
*
* #param width offscreen width
* #param height offscreen height
* #throws IllegalArgumentException
*/
public void setOffscreenPreview(int width, int height) throws IllegalArgumentException {
if (width <= 0 || height <= 0) {
throw new IllegalArgumentException("Invalid offscreen resolution");
}
mScreenGLRender.init(width, height);
}
private void startCapture() {
mScreenCapture.start();
}
private void stopCapture() {
mScreenCapture.stop();
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_hello_agora_screen_sharing);
}
public void onLiveSharingScreenClicked(View view) {
Button button = (Button) view;
boolean selected = button.isSelected();
button.setSelected(!selected);
if (button.isSelected()) {
initModules();
startCapture();
String channel = "ss_test" + System.currentTimeMillis();
channel = "ss_test";
button.setText("stop");
mRtcEngine.muteAllRemoteAudioStreams(true);
mRtcEngine.muteAllRemoteVideoStreams(true);
mRtcEngine.joinChannel(null, channel, "", 0);
} else {
button.setText("start");
mRtcEngine.leaveChannel();
stopCapture();
}
}
#Override
protected void onDestroy() {
super.onDestroy();
deInitModules();
}
}
Dart Code
const platform = const MethodChannel('samples.flutter.io/screen_record');
try {
final int result = await platform.invokeMethod('startScreenShare');
} on PlatformException catch (e) {}
setState(() {
});

Rx.NET batching by condition, min and max timer

I'm doing batching of messages in stream want to do it by 3 conditions:
if batcher can't add incoming message (for whatever internal logic of batcher)
if there were messages and then no messages within X seconds (basically what throttle does)
if there is continious stream of messages more often then every X seconds, then after Y seconds still close batch (cap on throttle)
I need to be able to change X and Y seconds in runtime without losing current batch (doesn't matter if it is closed immediately on config change or by closing conditions).
Condition function and batch process function should not run in parallel threads.
I'm using Rx-Main 2.2.5.
So far I came up with solution below and it seems to work, but I think there may be much simpler solution with reactive extensions?
Also with this solution capTimer doesn't restart if closing condition is "batcher can't add this message".
Extension:
public static class ObservableExtensions
{
public static IDisposable ConditionalCappedThrottle<T>(this IObservable<T> observable,
int throttleInSeconds,
int capTimeInSeconds,
Func<T, bool> conditionFunc,
Action capOrThrottleAction,
Action<T, Exception> onException,
T fakeInstance = default(T))
{
Subject<T> buffer = new Subject<T>();
var capTimerObservable = new Subject<long>();
var throttleTimerObservable = observable.Throttle(TimeSpan.FromSeconds(throttleInSeconds)).Select(c => 1L);
IDisposable maxBufferTimer = null;
var bufferTicks = observable
.Do(c =>
{
if (maxBufferTimer == null)
maxBufferTimer = Observable.Timer(TimeSpan.FromSeconds(capTimeInSeconds))
.Subscribe(x => capTimerObservable.OnNext(1));
})
.Buffer(() => Observable.Amb(
capTimerObservable
.Do(c => Console.WriteLine($"{DateTime.Now:mm:ss.fff} cap time tick closing buffer")),
throttleTimerObservable
.Do(c => Console.WriteLine($"{DateTime.Now:mm:ss.fff} throttle time tick closing buffer"))
))
.Do(c =>
{
maxBufferTimer?.Dispose();
maxBufferTimer = null;
})
.Where(changes => changes.Any())
.Subscribe(dataChanges =>
{
buffer.OnNext(fakeInstance);
});
var observableSubscriber = observable.Merge(buffer)
.Subscribe(subject =>
{
try
{
if (!subject.Equals(fakeInstance)) {
if (conditionFunc(subject))
return;
Console.WriteLine($"{DateTime.Now:mm:ss.fff} condition false closing buffer");
maxBufferTimer?.Dispose();
}
capOrThrottleAction();
if (!subject.Equals(fakeInstance))
conditionFunc(subject);
}
catch (Exception ex)
{
onException(subject, ex);
}
});
return new CompositeDisposable(maxBufferTimer, observableSubscriber);
}
}
And usage:
class Program
{
static void Main(string[] args)
{
messagesObs = new Subject<Message>();
new Thread(() =>
{
while (true)
{
Thread.Sleep(random.Next(3) * 1000);
(messagesObs as Subject<Message>).OnNext(new Message());
}
}).Start();
while (true)
{
throttleTime = random.Next(8) + 2;
maxThrottleTime = random.Next(10) + 20;
Console.WriteLine($"{DateTime.Now:mm:ss.fff} resubscribing with {throttleTime} - {maxThrottleTime}");
Subscribe();
Thread.Sleep((random.Next(10) + 60) * 1000);
}
}
static Random random = new Random();
static int throttleTime = 3;
static int maxThrottleTime = 10;
static IDisposable messagesSub;
static IObservable<Message> messagesObs;
static void Subscribe()
{
messagesSub?.Dispose();
BatchProcess();
messagesSub = messagesObs.ConditionalCappedThrottle(
throttleTime,
maxThrottleTime,
TryAddToBatch,
BatchProcess,
(msg, ex) => { },
new FakeMessage());
}
static bool TryAddToBatch(Message msg)
{
if (random.Next(100) > 85)
{
Console.WriteLine($"{DateTime.Now:mm:ss.fff} can't add to batch");
return false;
}
else
{
Console.WriteLine($"{DateTime.Now:mm:ss.fff} added to batch");
return true;
}
}
static void BatchProcess()
{
Console.WriteLine($"{DateTime.Now:mm:ss.fff} Processing");
Thread.Sleep(2000);
Console.WriteLine($"{DateTime.Now:mm:ss.fff} Done Processing");
}
}
public class Message { }
public class FakeMessage : Message { }
Tests I want to work:
public class Test
{
static Subject<Base> sub = new Subject<Base>();
static int maxTime = 19;
static int throttleTime = 6;
// Batcher.Process must be always waited before calling any next Batcher.Add
static void MaxTime()
{
// foreach on next Batcher.Add must be called
sub.OnNext(new A());
Thread.Sleep(6 * 1000 - 100);
sub.OnNext(new A());
Thread.Sleep(6 * 1000 - 100);
sub.OnNext(new A());
Thread.Sleep(6 * 1000 - 100);
// Process must be called after 19 seconds = maxTime
}
static void Throttle()
{
// foreach on next Batcher.Add must be called
sub.OnNext(new A());
Thread.Sleep(6 * 1000 - 100);
sub.OnNext(new A());
Thread.Sleep(6 * 1000 - 100);
// Process must be called after 5.9+5.9+6 seconds = throttleTime
}
static void Condition()
{
// foreach on next Batcher.Add must be called
sub.OnNext(new A());
Thread.Sleep(6 * 1000 - 100);
sub.OnNext(new B());
// Process must be called because Batcher.Add will return false
// Batcher.Add(B) must be called after Process
}
static void MaxTimeOrThorttleNotTickingRandomly()
{
sub.OnNext(new A());
// Process called by throttle condition in 6 seconds
Thread.Sleep(1000 * 100);
// Process is not called for remaining 94 seconds
sub.OnNext(new A());
// Process called by throttle condition in 6 seconds
}
static void Resub()
{
sub.OnNext(new A());
sub.OnNext(new A());
sub.OnNext(new A());
sub.OnNext(new A());
sub.OnNext(new A());
maxTime = 15;
throttleTime = 3;
// Process is called
// Resubs with new timinig conditions
sub.OnNext(new A());
// Process called by throttle condition in 3 seconds
}
}
public class Batcher
{
private Type batchingType;
public bool Add(Base element)
{
if (batchingType == null || element.GetType() == batchingType)
{
batchingType = element.GetType();
return true;
}
return false;
}
public void Process()
{
batchingType = null;
}
}
public class Base{}
public class A : Base { }
public class B : Base { }

contacts insert ,app died ,no save state

this is log:
08-28 13:50:47.648: A/libc(1010): ### ABORTING: INVALID HEAP ADDRESS IN dlfree addr=0x2a26bc90
08-28 13:50:47.648: A/libc(1010): Fatal signal 11 (SIGSEGV) at 0xdeadbaad (code=1), thread 1020 (FinalizerDaemon)
08-28 13:50:48.698: W/ActivityManager(149): Scheduling restart of crashed service com.android.KnowingLife/.PushNotification.NotificationService in 5000ms
08-28 13:50:48.698: W/ActivityManager(149): Force removing ActivityRecord{412a2c70 com.android.KnowingLife/.PhoneSynActivity}: app died, no saved state
08-28 13:50:48.807: W/GpsLocationProvider(149): Unneeded remove listener for uid 1000
08-28 13:50:49.257: E/Trace(1064): error opening trace file: No such file or directory (2)
08-28 13:50:50.017: W/GpsLocationProvider(149): Duplicate add listener for uid 10044
08-28 13:50:52.827: W/InputMethodManagerService(149): Got RemoteException sending setActive(false) notification to pid 1010 uid 10044
I run it in my emulator( version 4.1),and I am bulk inserting contacts to local .It works well usual,but I got 600 more contacts to
insert to local ,it doesn't work when insert to about 6%.I don't know
how to show it to you ,this is my code ,look this, you will see the
problem,thank
/**
* insert
*/
class InsertContactsTask extends AsyncTask<Void, Integer, Integer> {
String detail;
public InsertContactsTask(String detail) {
this.detail = detail;
}
#SuppressWarnings("deprecation")
#Override
protected void onPreExecute() {
super.onPreExecute();
showDialog(PROGRESS_DIALOG);
}
#Override
protected Integer doInBackground(Void... params) {
String[] itemRecord = detail.split(ParseData.getInstance()
.getRecordSplitFalg(), -1);
int count = itemRecord.length;
wait_Dialog.setMax(count);
ArrayList<ContentProviderOperation> contentOper = null;
contentOper = new ArrayList<ContentProviderOperation>();
for (int i = 0; i < itemRecord.length; i++) {
int rawContactInsertIndex = contentOper.size();
String[] item = null;
try {
item = itemRecord[i].split(ParseData.getInstance()
.getFiledSplitFlag(), -1);
contentOper.add(ContentProviderOperation
.newInsert(RawContacts.CONTENT_URI)
.withValue(RawContacts.ACCOUNT_TYPE, null)
.withValue(RawContacts.ACCOUNT_NAME, null).build());
contentOper.add(ContentProviderOperation
.newInsert(ContactsContract.Data.CONTENT_URI)
.withValueBackReference(Data.RAW_CONTACT_ID,
rawContactInsertIndex)
.withValue(Data.MIMETYPE,
StructuredName.CONTENT_ITEM_TYPE)
.withValue(StructuredName.DISPLAY_NAME, item[0])
.build());
for (int j = 1; j < item.length; j++) {
if (item[j].startsWith("1")) {
String phoneType = item[j].substring(1, 2);
int iType;
String label = null;
if (phoneType.compareToIgnoreCase("a") >= 0)
iType = phoneType.compareToIgnoreCase("a") + 10;
else
iType = Integer.parseInt(phoneType);
if (iType == 0)
label = item[j + 1];
contentOper
.add(ContentProviderOperation
.newInsert(
android.provider.ContactsContract.Data.CONTENT_URI)
.withValueBackReference(
Data.RAW_CONTACT_ID,
rawContactInsertIndex)
.withValue(Data.MIMETYPE,
Phone.CONTENT_ITEM_TYPE)
.withValue(Phone.NUMBER,
item[j].substring(2))
// "data1"
.withValue(Phone.TYPE, iType)
.withValue(Phone.LABEL, label)
.build());
if (iType == 0)
j++;
} else {
String emailType = item[j].substring(1, 2);
int iEmailType = Integer.parseInt(emailType);
String emailLabel = null;
if (iEmailType == 0)
emailLabel = item[j + 1];
contentOper
.add(ContentProviderOperation
.newInsert(
android.provider.ContactsContract.Data.CONTENT_URI)
.withValueBackReference(
Data.RAW_CONTACT_ID,
rawContactInsertIndex)
.withValue(Data.MIMETYPE,
Email.CONTENT_ITEM_TYPE)
.withValue(Email.DATA,
item[j].substring(2))
.withValue(Email.TYPE, iEmailType)
.withValue(Email.LABEL, emailLabel)
.build());
if (iEmailType == 0)
j++;
}
}
int iUpdate = i + 1;
if (iUpdate % 20 == 0 || iUpdate == itemRecord.length) {
try {
#SuppressWarnings("unused")
ContentProviderResult[] results = PhoneSynActivity.this
.getContentResolver().applyBatch(
ContactsContract.AUTHORITY,
contentOper);
contentOper.clear();
} catch (RemoteException e) {
e.printStackTrace();
} catch (OperationApplicationException e) {
e.printStackTrace();
} catch (Exception ex) {
ex.printStackTrace();
}
publishProgress(i);
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
return count;
}
#Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
wait_Dialog.setProgress(values[0]);
}
#Override
protected void onPostExecute(Integer count) {
super.onPostExecute(count);
wait_Dialog.dismiss();
txt_count.setText( count+ "");
Toast.makeText(PhoneSynActivity.this,
R.string.string_download_suc, Toast.LENGTH_LONG).show();
}
}