How to pause onCreate until boot completed? - java

I host widgets in my app and it seems, that if i start my app before booting of the device is completed, widgets cannot be created properly. Widgets then seem to be not loaded completely or not initialized/updated correctly. For instance: BatteryBotIndicator-Widget, which shows the battery status in percentage, shows a value of "XX" instead of some number like "70%". If i then restart my app and try to recreate the widget with:
AppWidgetProviderInfo appWidgetInfo = mAppWidgetManager.getAppWidgetInfo(appWidgetId);
it gives me null for appWidgetInfo (i fetch appWidgetId from SQLite database). And widget cannot be recreated.
It is kind of difficult to debug the real cause in this situation to find out what is exactly causing this (Starting Debugger at the right time). I assume the AppWidgetManager is not ready yet or something.
What i can say for sure: If i wait until i receive the broadcast-event BOOT_COMPLETED all widgets are created properly.
So how can i pause the execution of onCreate until booting is completed?
I can think of putting the thread to sleep in a while loop until the BroadcastReceiver (BOOT_COMPLETED) is setting a bool-variable in application-data to true. But i dont want to wait for this event always at starting of my app, as you can imagine ;)

if i start my app before booting of the device is completed, widgets cannot be created properly.
please explain more what exactly do you mean when you say - "not properly" . this might be relevant to understand if you're widget really depends on something related to the boot.
I can think of putting the thread to sleep in a while loop until the BroadcastReceiver (BOOT_COMPLETED) is setting a bool-variable in application-data to true
very bad idea.. also from performances and design reasons
instead, why not simply register to boot complete broadcast from the manifest, and when you recevice it - simply send the relevant broadcast to update your widget? AppWidgetProvider is already extends BroadcastReceiver, so you can simply add it intent filter for boot complete broadcast.
this is how to add intent filter to boot complete:
<receiver android:name="MyWidgetProvider" >
<intent-filter >
<action android:name="android.appwidget.action.APPWIDGET_UPDATE"/>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
<meta-data
...
</receiver>
and this is how to react to it from the widget provider implementation:
#Override
public void onReceive(Context context, Intent intent) {
if(intent.getAction().equals("android.intent.action.BOOT_COMPLETED")){
doTheUpdateHereExactlyLikeHowYouUpdateItFromAnywhereElse();
} else {
super.onReceive(context,intent);
}
}
for more information - follow this tutorial :https://laaptu.wordpress.com/2013/08/12/android-update-app-widget-with-listview-after-phone-reboot/

Related

Android Studio - getting PreciseCallState of phone calls

I'm trying to build an Android app in Android Studio to detect the precise call state of outgoing calls. I'm new to Java, and I'm going around in circles with a few problems.
The basic calls states are working fine for me per this youtube guide https://www.youtube.com/watch?v=rlzfcqDlovg. That tutorial uses "TelephonyManager.EXTRA_STATE" in its main class and the "android.intent.action.PHONE_STATE" receiver in the AndroidManifest. It successfully detects when an outgoing call is placed and ended, but NOT when it actually starts ringing/is answered/etc.
I'm trying to get the PreciseCallState of outgoing calls using a couple of StackOverFlow guides like this one How to Use PreciseCallState and other similar discussions, but I'm stuck with a few points:
The basic receiver in AndroidManifest worked fine listening to "android.intent.action.PHONE_STATE". But my precise receiver, listening to "android.intent.action.PRECISE_CALL_STATE" doesn't fire at all, when a call is placed, answered, ended etc.
Even if my receiver DID fire when the PRECISE_CALL_STATE changed, Android Studio doesn't recognize "TelephonyManager.EXTRA_FOREGROUND_CALL_STATE", and won't let me build the app when I try to use this line. I've tried using several "Hidden API bypass" scripts like this one https://github.com/LSPosed/AndroidHiddenApiBypass, but with no luck - I'm unsure how exactly to use this, as the instructions on these type of resources aren't clear to me. All I can figure out is to include their dependencies and "import" the package, not how to actually use it in my script.
Other points:
I know that Google introduced restrictopms on non-standard packages (including reflection) in API level 28 (refer https://developer.android.com/guide/app-compatibility/restrictions-non-sdk-interfaces, so I've tried using API/SDK versions 25 through 32, all with no luck. My current attempt is using SDK version 30.
I've installed my app as a system app using Magisk Systemizer, per other Stackoverflow suggestions for using PreciseCallState, but this didn't fix my issues.
The app doesn't ask for the "READ_PRECISE_PHONE_STATE" permission at all, either when it's installed as a system app or a regular app. I'm not sure if this is okay, but I imagine I'm missing something.
I'd appreciate any help on these 2 issues, I've been trying to research and figure this out for a solid week now!
My code:
AndroidManifest:
<uses-permission android:name="android.permission.READ_PRECISE_PHONE_STATE" />
<application...
...
<receiver android:name=".CallReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<!-- (unused) <action android:name="android.intent.action.PHONE_STATE" />-->
<action android:name="android.intent.action.PRECISE_CALL_STATE" />
<!-- (unused) <action android:name="android.intent.action.NEW_OUTGOING_CALL" />-->
</intent-filter>
</receiver>
</application>
MainActivity:
if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_PRECISE_PHONE_STATE)
!= PackageManager.PERMISSION_GRANTED){
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.READ_PRECISE_PHONE_STATE},1);
}
CallReceiver:
public class CallReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
String myString = "new PreciseCallState detected...";
Toast.makeText(context, myString, Toast.LENGTH_LONG).show();
//String myPreciseCallState = intent.getIntExtra(TelephonyManager.EXTRA_FOREGROUND_CALL_STATE, -2);
//Toast.makeText(context, myString + myPreciseCallState, Toast.LENGTH_LONG).show();
// (unused) //String basicCallState = intent.getStringExtra(TelephonyManager.EXTRA_STATE);
}
}

my app doesn't send any notifications when it's not running (killed)

I have a reminder app that sends a notification according to the time of the item in the listview, the problem is that whenever my phone is rebooted or the app is killed, the app doesn't send any notification.
Note: The app is offline and local, it doesn't use internet connection, I don't use FCM or and online services for this app.
Thank you so much for your time.
Update:
I'm using a thread that searches for data in the local database, If there are any changes in time in the database compared to the current time, the notification should show, but the notification only shows when the app is running, but when the app is killed it doesn't show.
The app needs to run on android 5+,
You can use Broadcast receiver in order to be notified when Boot Completes. And again start the required services of your app.
For reference, have a look here.
This is because when you are killing the app, the onDestroy method gets called. When it's killed, you app is not doing anything. For this you would need a broadcast receiver.
How to implement broadcast receiver?
Create a java class named TimeBradcastReceiver.java.
Paste this code in the class
public class TimeBradcastReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
String dateString = Calendar.getInstance().get(Calendar.HOUR) + ":" + Calendar.getInstance().get(Calendar.MINUTE);
String hourString = Calendar.getInstance().get(Calendar.HOUR);
String minutesString = Calendar.getInstance().get(Calendar.MINUTE;
Log.d("MyBradcastReceiver","i have recieved - " + dateString);
}
}
Once you have implemented this code, you need to add this to you manifest inside the application tag.
<receiver android:name="com.chatverse.free.TimeBroadcastReceiver"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.TIME_TICK"/>
</intent-filter>
</receiver>
Add this code to your activity which opens the first.
IntentFilter mTime = new IntentFilter(Intent.ACTION_TIME_TICK);
registerReceiver(new TimeBradcastReceiver(), mTime);
Now you can do the comparison of the dates and hours and show the notification.
Note - This receiver will update only when a minute has changed.

Check time every minute by broadcast receiver

I want to check the time every minute to make alarm app but when I but this in receiver
<action android:name="android.intent.ACTION_TIME_CHANGED"/>
<action android:name="android.intent.ACTION_TIME_TICK"/>
<action android:name="android.intent.action.TIME_TICK"/>
and put this in broadcast receiver
#Override
public void onReceive(Context context, Intent intent)
{
Toast.makeText(context,"changed",Toast.LENGTH_LONG)
.show();
}
My app don't work or do any thing
I searched more and more but nothing was useful I hope someone help me
From the way you wrote <action android:name="android.intent.ACTION_TIME_CHANGED"/>, it appears that you're trying to register your BroadcastReceiver in the Manifest.xml.
However, I'll quote this straight from the documentation:
ACTION_TIME_TICK
Broadcast Action: The current time has changed. Sent every minute. You cannot receive this through components declared in manifests, only by explicitly registering for it with Context.registerReceiver().
--https://developer.android.com/reference/android/content/Intent.html#ACTION_TIME_TICK
You can only receive this broadcast by registering the BroadcastReceiver through the registerReceiver() method in either something like your Activity or Service.
However, I do want to mention that you should avoid using this broadcast if your intention is to create an Alarm app.
Constantly fetching the time every minute can become quite battery draining, especially if the alarm takes a while to ring.
Instead, you should consider scheduling your alarm through services like JobScheduler or AlarmManager.

Can't reinstall crashed Sony SmartWatch Control

I hope this is not to generic but I am developing an app for the Sony SmartWatch. When ever I make a mistake like allowing a null pointer exception. I can not get my app to restart. It's like it stays in the crashed state forever. To make the problem worse I also stop receiving messages via Logcat pertaining the app. When I uninstall and reinstall the app It's not listed in the SmartWatch app on the phone. Like it won't register. This is difficult to trouble shoot since I don't get any Log messages at this point. The only thing I can do is uninstall the app. Restart my phone. Then reinstall the app. At that point it's back to normal and I can start writing code again. So that brings me to my questions.
Is there a better way to re-register a control?
Will this happen to end users? If the app crashes will they need to uninstall, reboot and install to recover?
Some Detail (names have been changed to protect the inocent):
I have created a Broadcast Reciever and in my mainfest set it to listen for these broadcasts.
<receiver android:name=".MyExtensionReceiver" >
<intent-filter>
<!-- Receiver intents -->
<action android:name="com.sonyericsson.extras.liveware.aef.registration.EXTENSION_REGISTER_REQUEST" />
<action android:name="com.sonyericsson.extras.liveware.aef.registration.ACCESSORY_CONNECTION" />
<!-- Control intents -->
<action android:name="com.sonyericsson.extras.aef.control.START" />
<action android:name="com.sonyericsson.extras.aef.control.STOP" />
<action android:name="com.sonyericsson.extras.aef.control.PAUSE" />
<action android:name="com.sonyericsson.extras.aef.control.RESUME" />
<action android:name="com.sonyericsson.extras.aef.control.ERROR" />
<action android:name="com.sonyericsson.extras.aef.control.TOUCH_EVENT" />
<action android:name="com.sonyericsson.extras.aef.control.SWIPE_EVENT" />
</intent-filter>
Code for MyExtensionReceiver:
public class MyExtensionReceiver extends BroadcastReceiver {
public MyExtensionReceiver() {
super();
Log.d("mytag", "MyExtensionReceiver Loaded");
Dbg.setLogTag("mytag");
}
#Override
public void onReceive(Context context, Intent intent) {
Log.d("mytag", "onReceive: " + intent.getAction());
intent.setClass(context, MyExtensionReceiver.class);
context.startService(intent);
}
}
Even if my app is crashing I should still get a log message when onReceive is called. It's like the EXTENSION_REGISTER_REQUEST broadcast never gets sent. I just keep uninstalling rebooting and reinstalling over and over. Eventually the app gets found by the SmartConnect App.
It doesn't seem to have anything to do with the BroadcastReceiver. Without using one, I'm having the same annoying problem. I need to restart the phone in order to get things running normal again, as neither disabling/enabling the app helps a bit, nor killing the SmartWatch phone app (as I see no other way to restart it).
I would also appreciate some help from Sony on this matter.
Just came across this issue, giving some grey!! To work around this issue, just create a new intent using string and launch that with context.
Intent intent = new Intent("MY.PACKAGE.NAME.MyExtensionReceiver");
context.startService(intent);

Android, Opening app only if it is closed through intent action

I am working on a phonegap application, with some native pieces.
So far I have notifications running natively, to make sure javascript and phonegap is not required at all. The problem I am having however, is when the notification is clicked I'd like to open the app, or otherwise just bring the app to the front.
How do I do this? I tried setting the main activity in the intent, but it restarts my application every time.
Intent notificationIntent = new Intent(context, main.app.class);
notificationIntent.putExtra(NOTIF_RESPOND, runThis);
notificationIntent.setAction(Intent.ACTION_VIEW);
notificationIntent = notificationIntent.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
Actually in Android there is almost no such thing as "restarting application". Basically the Application - is a bundle of all your services/activities/providers etc. It's either running or not.
If user starts a new Activity - system will check, if application is running - it will create this activity inside the application. If no - will create new Application instance.
So I think you mean that if you set intent for your Main activity - another instance of Activity is launching, am I right?
If so - take a look at the following flag for activity, you should try to set in in the Manifest(or whatever in PhoneGap, sorry). http://developer.android.com/guide/topics/manifest/activity-element.html#lmode
<activity android:name=".YourActivity"
android:launchMode="singleTask"
...
This flag will tell the system not to create a new Activity each type it will be needed, but to reuse already-existing one. Be careful, you should properly implement onNewIntent method in this case to handle this "relaunches", and I'm not 100% sure that it's implemented in PhoneGap.
Good luck

Categories