create explicit intent from scratch without creating an ActivityNotFoundException - java

i am still struggling to open up my app to the external world.
At first i let everything be handled by MainActivity, but i have 2 cases (add + del) where a headless mode is better/faster/no flicker etc...
So i made a second entry into my app Manifest:
<activity
android:name=".IntStringSynchro"
android:label="#string/headless"
android:theme="#android:style/Theme.NoDisplay"
>
<intent-filter>
<action android:name="ADD" />
<category android:name="android.intent.category.EMBED" />
</intent-filter>
</activity>
and reading here on Stackoverflow, i first tested it internally, so i added to my main activity a button that starts an intent to call on this activity...
so somewhere in onClick:
else if (p1 == testBut)
{
String tstpathToProject = "AppProjects/IntStringIntentTester/app/src/main/res";
Intent callIt = new Intent(this, IntStringSynchro.class);
callIt.addCategory("android.intent.category.EMBED");
callIt.setAction("ADD");
callIt.putExtra("token", "testtoto");
callIt.putExtra("value", "titi");
callIt.putExtra("value-de", "tata");
callIt.setAction("ADD");
callIt.putExtra("path", tstpathToProject);//relative
Log.d(TAG, "sending intent " + callIt + " " + callIt.getExtras());
try
{
startActivityForResult(callIt, ASK_STRINGMOD);
}
catch (ActivityNotFoundException e)
{
Toast.makeText(this, "no available activity " + callIt, Toast.LENGTH_SHORT).show();
}
}
that worked as avertised, but this won't work, when another app tries to build that intent, since it won't have access to the class files of my app, so i changed the relevant part to
Intent callIt = new Intent();
callIt.setClassName("com.nohkumado.intstringsynchro", "IntStringSynchro");
callIt.setComponent(new ComponentName("com.nohkumado.intstringsynchro", "IntStringSynchro"));
callIt.addCategory("android.intent.category.EMBED");
callIt.setAction("ADD");
etc.
but this now yields an activity not found exception...
i am a bit confused, since there doesn't seem to be a method to set the context, that is present on the local intent call i made before...
the component part is to replace the explicit class instance given in the first type constructor, the setClassName, doubles the setComponent, not, is useless?
since neither work, i am missing something somewhere, but what?
as sayd, the thing is, i want to make this intent call then from another app...

try to change the second parameter of setComponentName constructor
intent.setComponent(new ComponentName("com.package.address","com.package.address.UrActivity"));

Related

Bring Android app back from background programmatically

I'm new to Android coding but I already had played with java.
I want to open or bring my app back once it is in background.
I've been searching around but nothing seems to work.
I have a function of a class that is called every time a notification is received which is CordovaNotificationReceivedHandler and it is instantiated by the OneSignal init as per the code below.
OneSignal.init(this.cordova.getActivity(),
googleProjectNumber,
appId,
new CordovaNotificationOpenedHandler(notifOpenedCallbackContext),
new CordovaNotificationReceivedHandler(notifReceivedCallbackContext)
);
Trying to get my application to be reordered and displayed, even if the user is in another application, I made the following changes:
OneSignal.init(this.cordova.getActivity(),
googleProjectNumber,
appId,
new CordovaNotificationOpenedHandler(notifOpenedCallbackContext),
new CordovaNotificationReceivedHandler(this.cordova.getActivity(), notifReceivedCallbackContext));
In the body of the function that is called when receiving a push notification I added the following code:
Intent it = new Intent("intent.my.action");
it.setComponent(new ComponentName(contextActivy.getPackageName(), MainActivity.class.getName()));
it.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
contextActivy.getApplicationContext().startActivity(it);
this.handleActivityLifecycleHandler();
Como a classe ficou após a modificação:
private class CordovaNotificationReceivedHandler implements NotificationReceivedHandler {
private CallbackContext jsNotificationReceivedCallBack;
private Context contextActivy;
public CordovaNotificationReceivedHandler(Context contextActivy, CallbackContext inCallbackContext) {
jsNotificationReceivedCallBack = inCallbackContext;
this.contextActivy = contextActivy;
}
#Override
public void notificationReceived(OSNotification notification) {
Log.w("Got here","Aqui");
Intent it = new Intent("intent.my.action");
it.setComponent(new ComponentName(contextActivy.getPackageName(), MainActivity.class.getName()));
it.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
contextActivy.getApplicationContext().startActivity(it);
this.handleActivityLifecycleHandler();
try {
CallbackHelper.callbackSuccess(jsNotificationReceivedCallBack, new JSONObject(notification.stringify()));
}
catch (Throwable t) {
t.printStackTrace();
}
}
}
The problem is that the application is not reordered to be applied or opened.
It is important to remember that I am assuming that the application should be open.
You can use this, It work fine.
Intent intent = new Intent("intent.my.action");
intent.setComponent(new ComponentName(this, yourActivity.class));
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.addFlags(Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
startActivity(intent);
Don't Forget Add this in your activity in manifest
<intent-filter>
<action android:name="intent.my.action" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>

How to solve- Onesignal push notification not coming to Android device if the app is not opened for a while?

In my Android application, I am using One Signal push notification service to send push notifications. I have done all the settings according to document as mentioned.
After setting up all these things, I have created one service class of one signal like below-
NotificationExtenderBareBonesExample.java
public class NotificationExtenderBareBonesExample extends NotificationExtenderService {
public static String first_screen;
#Override
protected boolean onNotificationProcessing(OSNotificationReceivedResult receivedResult) {
SharedPreferences.Editor editor = getApplicationContext().getSharedPreferences("NOTIFY_PREF", MODE_PRIVATE).edit();
editor.putString("notify_msg", receivedResult.payload.groupMessage);
editor.putString("notify_key", receivedResult.payload.groupKey);
editor.apply();
first_screen = receivedResult.payload.groupMessage;
return false;
}
}
I have also created another class to handle the received push notification like below-
ExampleNotificationReceivedHandler.java
public class ExampleNotificationReceivedHandler implements OneSignal.NotificationReceivedHandler {
#Override
public void notificationReceived(OSNotification notification) {
JSONObject data = notification.payload.additionalData;
String customKey;
if (data != null) {
customKey = data.optString("customkey", null);
if (customKey != null)
Log.i("OneSignalExample", "customkey set with value: " + customKey);
}
}
}
Then, in my Activity class, I have initialized One Signal like below-
OneSignal.startInit(this)
.inFocusDisplaying(OneSignal.OSInFocusDisplayOption.Notification)
.unsubscribeWhenNotificationsAreDisabled(true)
.setNotificationReceivedHandler(new ExampleNotificationReceivedHandler())
.setNotificationOpenedHandler(new MyNotificationOpenedHandler(this))
.init();
At last in my AndroidManifest file, I have declared the service like below-
<service
android:name="com.rokomari.new_package.notification_check.NotificationExtenderBareBonesExample"
android:exported="false"
android:permission="android.permission.BIND_JOB_SERVICE">
<intent-filter>
<action android:name="com.onesignal.NotificationExtender" />
</intent-filter>
</service>
The push notification was coming, if the app is being used recently, but the problem was still there as it is mentioned in my question. So, I have checked few more solutions and applied in my project like below-
I made my application a system app and added one authentication service with that.
I also added one Broadcast-Receiver class like below-
BootReceiver.java
public class BootReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals("android.intent.action.BOOT_COMPLETED")) {
Intent startServiceIntent = new Intent(context, NotificationExtenderBareBonesExample.class);
context.startService(startServiceIntent);
Intent notificationServiceIntent = new Intent(context, NotificationExtenderBareBonesExample.class);
context.startService(notificationServiceIntent);
}
}
}
And declared this in my AndroidManifest file-
<receiver
android:name="com.rokomari.new_package.notification_check.BootReceiver"
android:enabled="true">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
After doing all these I am still having the same problem.
---- The Problem is -----
When I am using app(opening the app) regaularly the push notification from one signal is coming whether the app is in background or not. But when I am not using the app for a while it's not coming. In addition, for some devices mainly Xiomi the push notification is not coming at all.
After making some changes in Xiomi device like below-
*** Xiaomi - Make sure "Auto-start" property enabled for your app in the settings.**
After changing settings, the push notification came once. But I need a solution programmatically to send push notification to cover all the devices. If it is not possible yet with One Signal, then I like to know how apps like facebook, whatsapp send push notification?

Get Amount of Time change Using Android Broadcast

Its simple Question
I am want to get the Amount of Time change By User using system setting
I am using Broadcast Receiver,from below broadcast Receiver , I only get the notice that time has changed
But how much Changed I don't no .
I want to get the whether the user incremented the time or decremented
And How much Incremented or Decremented ?
is it Possible to get this ?
if yes then how ?
Note : The IntentExtra didnt have any Extra information
<receiver android:name=".Receivers.TimeChangeReceivers">
<intent-filter >
<action android:name="android.intent.action.TIME_SET"></action>
</intent-filter>
</receiver>
My Class
public class TimeChangeReceivers extends BroadcastReceiver {
public static final String TAG= TimeChangeReceivers.class.getSimpleName ();
#Override
public void onReceive(Context context, Intent intent) {
Log.e ( TAG," Time Change!");
}
}
If there is any data that you can get, it will be stored in intent extras. Try to get intent.getExtras(), it will give you Bundle, and then you can get values from it.
When you get your Bundle try bundle.keySet() to get all keys from it, and look for needed info.

Checking in with server in the background in Java-Android

I am trying to write an app that checks in with a server every X seconds.
I was able to make it work, but only when the application is running and active (not sure if it can be minimized, was not able to test it clearly) and the device is not locked. I would like for the checking to continue even if I lock the device or do other things on it.
From my searches, it seems like I should use service, but I was not able to figure out how to implement it with what I am trying to do. Or is there something else that could do this?
What I need to and failed to do is this:
User checks a CheckBox - start the service
Create the service and pass some information to it
Create an instance of my class in the service using the passed information
Call this instance's method every X seconds in a new thread (the method returns true/false)
Listen to ?something and if the method returns true then stop the service and notify user
If the user unchecks the CheckBox, stop the service.
I tried doing this, but I was unable to get any information out of the thread and out of the service. Is there a way to do so?
Starting the service from activity for example and binding it with your app
//make these 2 variables as fields in Activity for example
YourService yourService = null;
//this variable can be used for checking if your activity are binded already or not
boolean mBounded = false;
Intent mIntent = new Intent(this, YourService.class);
startService(mIntent);
bindService(mIntent, mConnection, BIND_AUTO_CREATE);
ServiceConnection mConnection = new ServiceConnection() {
public void onServiceDisconnected(ComponentName name) {
mBounded = false;
yourService = null;
}
public void onServiceConnected(ComponentName name, IBinder service) {
mBounded = true;
YourService.LocalBinder mLocalBinder = (YourService.LocalBinder) service;
yourService= mLocalBinder.getServerInstance();
}
};
Do not forget that you can use methods from Service in Activity only after it is bound to your Activity. In other words it is available only after onServiceConnected is executed.
So you have now service and activity who can communicate with each other.
For example you can call in Activity some public method of your Service, like
if (yourService != null)
yourService.test();
If you want to call your Activity methods in Service you should pass it to Service with simple setter.
If you want to stop Service its kinda easy too:
Intent mIntent = new Intent(this, YourService.class);
stopService(mIntent);
For doing request every X service:
1) You can do infinity separate thread inside Service and do request after delay for X seconds.
2) For checking every X seconds you can use something like AlarmManager.
3) Also its possible to use CountDownTimer inside your Service to do some requests to server.
If you want to create your Service after reboot if CheckBox was set, its easy too. So you should use simple BroadcastReceiver.
First of all you should save your CheckBox setting in SharedPreferences, then run your Service if you need.
public class SimpleReceiver extends WakefulBroadcastReceiver{
#Override
public void onReceive(Context context, Intent intent) {
//run below code if you need, depends on your saved value of Checkbox in SharedPreferences
Intent serviceIntent = new Intent(context, YourService.class);
context.startService(serviceIntent);
}
}
And for sure dont forget to add in AndroidManifest information about your Service and Receiver to be sure it will run automatically after reboot.
<service
android:name=".package.YourService"
android:enabled="true"
android:exported="false"> </service>
<receiver
android:name=".package.SimpleReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
<action adroid:name="android.intent.action.QUICKBOOT_POWERON" />
</intent-filter>
</receiver>

Check if Download Manager downloaded the file

How can I check if file has been downloaded and run its installation? I have a code:
public void downloadUpdate(String url){
DownloadManager.Request request = new DownloadManager.Request(Uri.parse(url));
request.setDescription("Downloading...");
request.setTitle("App Update");
request.allowScanningByMediaScanner();
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
String name = URLUtil.guessFileName(url, null, MimeTypeMap.getFileExtensionFromUrl(url));
request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, name);
DownloadManager manager = (DownloadManager) getSystemService(Context.DOWNLOAD_SERVICE);
manager.enqueue(request);
}
To check whether the download manager downloaded the file, you must implements your BroatcastReceiver.
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (action.equals(DownloadManager.ACTION_DOWNLOAD_COMPLETE)) {
DownloadManager.Query query = new DownloadManager.Query();
query.setFilterById(intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, 0));
DownloadManager manager = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE);
Cursor cursor = manager.query(query);
if (cursor.moveToFirst()) {
if (cursor.getCount() > 0) {
int status = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_STATUS));
if (status == DownloadManager.STATUS_SUCCESSFUL) {
String file = cursor.getString(cursor.getColumnIndex(DownloadManager.COLUMN_LOCAL_FILENAME));
// So something here on success
} else {
int message = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_REASON));
// So something here on failed.
}
}
}
}
}
However, I am not sure whether you can install the APK programmatically. For security reason, I don't think you can. For application update, I think you should use google versioning control. When you re-deploy your app using different version number, the users should able to update automatically (unless user turn off at google play). Hope that this will help.
Update
You do not need to call the method that I mention. You just need to declare your broadcast receiver at your manifest xml file and DownloadManager will call at when download complete. The xml look something like below:
<receiver
android:name=".BroadcastReceiver"
android:enabled="true"
android:exported="true" >
<intent-filter>
<action android:name="android.intent.action.DOWNLOAD_COMPLETE" />
<action android:name="android.intent.action.DOWNLOAD_NOTIFICATION_CLICKED" />
</intent-filter>
</receiver>
This is relatively an easy method. It worked for me:
You need to add the <receiver> tag in the manifest file as follows:
<application>
<receiver
android:name= "com.example.checkDownloadComplete" <!-- add desired full name here -->
android:exported="true" >
<intent-filter>
<action android:name="android.intent.action.DOWNLOAD_COMPLETE" />
</intent-filter>
</receiver>
</application>
This will register a Broadcast Receiver for an event where your download is completed. This will call the onReceive() method in your class as soon as download completes. Remember that you need to extend the BroadcastReceiver class, but not implement it. I declared a boolean variable as a toggle to check completion of download.
Hence, your Java class will be something like:
public static class checkDownloadComplete extends BroadcastReceiver{
public static boolean isDownloadComplete= false;
#Override
public void onReceive(Context context, Intent intent) {
isDownloadComplete = true;
Log.i("Download completed?", String.valueOf(isDownloadComplete));
}
}
To wait until or check whether your download has completed from any other class, use the following simple code in the desired appropriate place:
while(!checkDownloadComplete.isDownloadComplete){
// add necessary code to be executed before completion of download
}
//code after completion of download
But remember that if you need to check it multiple times in your project, then you'll need to reset the value of isDownloadComplete beforehand.

Categories

Resources