Is it possible to NOT show the popup notification of OneSignal and instead create one programmatically?
Ok so after some research i found it out and is pretty straightforward.
here is the link to the offical doc on how to do it.
OneSignal Android Customizations
There are few step to achieve it:
1- Create a NotificationExtenderServiceClass
public class NotificationExtenderBareBonesExample extends NotificationExtenderService {
#Override
protected boolean onNotificationProcessing(OSNotificationReceivedResult receivedResult) {
// Read properties from result.
// Return true to stop the notification from displaying.
return true;
}
}
As you can see it's pretty clear, turning read to true will stop showing notifications.
But what the docs doesn't says is that FCM will stop working and instead the notifications will pass here.
2 - add the service to Manifest
<service
android:name=".NotificationExtenderBareBonesExample"
android:permission="android.permission.BIND_JOB_SERVICE"
android:exported="false">
<intent-filter>
<action android:name="com.onesignal.NotificationExtender" />
</intent-filter>
</service>
That's it.
Now, adding your logic inside NotificationExtender you will be able to freely manage your notifications.
Related
I am making a VOIP call app. When a call comes in, it should open the app, even if the app is closed or never opened. We also need the call notifications to come in from a server.
I know apps like WhatsApp and Facebook Messenger do this, but how?
We are using a design similar to follows: Build a Calling App
We have tried using Firebase Cloud Messaging as recommended by Android documentation, and while there is moderate success, it does not work when the app is closed.
We are considering using a Sync Adapter or WorkManager next, but it takes quite a bit of time to prototype, and I'd prefer to ask if anyone has any success or if there are existing plugins for this.
As I'm aware, there are also going to be restrictions on Android 10. It says to use time-sensitive notifications, but these will still need to be triggered from a server somehow.
In your calling activity add this code. It will turn your screen on.
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) {
this.setTurnScreenOn(true);
} else {
final Window window = getWindow();
window.addFlags(WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON);
}
and in your activity manifest, define intent-filter as CALL
<activity
android:name=".activities.CallActivity"
android:label="#string/app_name"
android:launchMode="singleTop"
android:screenOrientation="portrait"
android:windowSoftInputMode="adjustPan|stateHidden">
<intent-filter>
<action android:name="android.intent.action.CALL" />
</intent-filter>
</activity>
When you receive notification from Firebase in onMessageReceived(RemoteMessage remoteMessage), open your activity
openActivity(CallActivity.class);
public void openActivity(Class<?> tClass) {
Intent i = new Intent(this, tClass);
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(i);
}
So, I followed the official guide here https://developer.android.com/training/auto/start/index.html to create a very basic Android Auto Audio App. For the moment it does nothing, other then declaring what needs to be declared in the manifest and implementing empty onGetRoot() and onLoadChildren().
Problem is, that it is not being recognized by the Android Auto app.
Any idea where to get a working example? What could be wrong?
Manifest:
<service
android:name=".MyService"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name=
"android.media.browse.MediaBrowserService"/>
</intent-filter>
</service>
automotive_app_desc.xml:
<automotiveApp>
<uses name="media" />
</automotiveApp>
service:
public class MyService extends MediaBrowserServiceCompat {
public static final String MEDIA_ID_ROOT = "__ROOT__";
#Override
public BrowserRoot onGetRoot(String clientPackageName, int clientUid,
Bundle rootHints) {
//TODO: check if the client is allow access
return new BrowserRoot(MEDIA_ID_ROOT, null);
}
#Override
public void onLoadChildren(final String parentMediaId,
final Result<List<MediaBrowserCompat.MediaItem>> result) {
// Assume for example that the music catalog is already loaded/cached.
List<MediaBrowserCompat.MediaItem> mediaItems = new ArrayList<>();
// Check if this is the root menu:
if (MEDIA_ID_ROOT.equals(parentMediaId)) {
// build the MediaItem objects for the top level,
// and put them in the mediaItems list
} else {
// examine the passed parentMediaId to see which submenu we're at,
// and put the children of that menu in the mediaItems list
}
result.sendResult(mediaItems);
}
You have to go to Android Auto settings, tap many times on the Version entry (the last one) to unlock Developer settings. Then tap on Developer settings menu item and enable Unknown sources. Restart Android Auto and if your app it's ok it will be listed. Worked for me
I didn't see this included in your snippet from the manifest, but double check that this line is also there.
<application>
...
<meta-data android:name="com.google.android.gms.car.application"
android:resource="#xml/automotive_app_desc"/>
...
</application>
I created a sample app matching everything you have (plus the line above), and it appears in Android Auto on the mobile device, as well as the Desktop Head Unit.
I want to create an android app which will "scan" other applications'layouts and find out if there are buttons etc.
Some apps, like whatsapp, doesn't allow third parts to move into the app, so I though that using accessibility could be the solution.
Now the problem is that I've never used Accessibility, so can someone of you can please show me how to "scan" an app's layout to find buttons?
Thanks a lot
What you're looking for is an Accessibility Service. Configuring an accessibility service is somewhat complicated. I have set up a repository of accessibility boilerplate code that sets up an AccessibilityService that logs the node heirarchy to LogCat, and has the default project settings activity set up as it's settings activity. Here are some of the highlights, as I dislike just posting github repos as answers. Note that I use a lot of my own libraries. CLog is a logging library and AndroidAccessibilityUtils wraps node infos with some common utility functions. You can find references to the dependencies in the build.gradle file on the github repo at the bottom. Here are some code highlights.
Your manifest.xml file is going to be significantly different from an Activity, and should contain an entry like this in your Application element:
<application .... >
...
<service
android:name="com.moba11y.basicaccessibilityservice.BasicAccessibilityService"
android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE" >
<intent-filter>
<action android:name="android.accessibilityservice.AccessibilityService" />
</intent-filter>
<meta-data
android:name="android.accessibilityservice"
android:resource="#xml/service_config" />
</service>
...
</application>
First you need to create a subclass of Accessibility Service:
public class BasicAccessibilityService extends AccessibilityService {
static {
CLog.initialize(BasicAccessibilityService.class.getSimpleName(), BuildConfig.DEBUG);
}
#Override
public void onAccessibilityEvent(AccessibilityEvent event) {
CLog.d(event.toString());
switch (event.getEventType()) {
//On Gesture events print out the entire view heirarchy!
case AccessibilityEvent.TYPE_GESTURE_DETECTION_START:
CLog.d(A11yNodeInfo.wrap(getRootInActiveWindow()).toViewHeirarchy());
default: {
//If the event has a source, let's print it out separately.
if (event.getSource() != null) {
CLog.d(A11yNodeInfo.wrap(event.getSource()).toViewHeirarchy());
}
}
}
}
#Override
public void onInterrupt() {
CLog.e("Service Interrupted: Have never actually had this happen.");
}
}
That is the bulk of the highlights. You also should have a "service_config" XML with properties, as is referenced in the changes to the Manifest XML file. More details, and a reasonable starer point can be found in the open source repo on GitHub.
https://github.com/chriscm2006/Android-Accessibility-Service-Boilerplate
I am facing a problem in override the On Click Behavior in Appboy deeplink
Please find the following data
1- Register Appboy in BaseActivity which is the parent activity for all Application Activities
#Override
protected void onResume() {
AppboyInAppMessageManager.getInstance().registerInAppMessageManager(this);
Appboy.getInstance(this).requestInAppMessageRefresh();
}
#Override
protected void onPause() {
AppboyInAppMessageManager.getInstance().unregisterInAppMessageManager(this);
}
2- Add the receivers in Manifest File as following
<receiver android:name="com.forsale.forsale.appboy.AppboyGcmReceiver"
android:permission="com.google.android.c2dm.permission.SEND" >
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
<action android:name="com.google.android.c2dm.intent.REGISTRATION" />
<category android:name="com.forsale.forsale" />
</intent-filter>
</receiver>
<receiver
android:name="com.forsale.forsale.appboy.AppBoyOpenReceiver"
android:exported="false" >
<intent-filter>
<action android:name="com.forsale.forsale.intent.APPBOY_PUSH_RECEIVED" />
<action android:name="com.forsale.forsale.intent.APPBOY_NOTIFICATION_OPENED" />
</intent-filter>
</receiver>
Know I can send in app message using app boy dashboard, and receive the message, but when I click the message it open appboy web activity with the link
I need to override this behaviour to be able to get the link that I sent in In app message and parse some parameters from it and direct the use to an activity inside my app
I have tried the following
remove default app boy web activity from manifest file /// the app crash
implement the IInAppMessageManagerListener /// the app stop receiving any messages
Please note that the application call the onReceive method when trying to register appboy and print the log (action = REGISTRATION, RegId = "..."), but it never lo any other actions like RECEIVE, or OPEN
public void onReceive(Context context, Intent intent) {
AppboyLogger.i("AMIRA", String.format("Amira %s", intent.toString()));
String action = intent.getAction();
AppboyLogger.i("AMIRA", String.format("Amira %s", action));
Bundle bundle = intent.getExtras();
for (String key : bundle.keySet()) {
Object value = bundle.get(key);
AppboyLogger.i("AMIRA", String.format("Amira %s", key + ":" + value.toString()));
}
}
The root of the problem is that we differentiate deep links and http links based on schema of the URI, so http (and some other schemes) links are detected as web links, and other formats are seen as deep links (see https://github.com/Appboy/appboy-android-sdk/blob/master/android-sdk-ui/src/com/appboy/ui/actions/ActionFactory.java).
We’ll consider how to instrument things for the use case you have, but in the meantime there’s a couple of ways you could solve the issue:
1) Create a deep link that is not also an http link. Everything should work if your link instead looks like, for example, forsale://mylink?a=b&2=3....etc.
2) Set a custom in-app message manager listener: https://documentation.appboy.com/Android/#in-app-message-customization. You can see an example of how we do this in our Droidboy sample app. In your case, you’d want to return defaults for everything but onInAppMessageButtonClicked and onInAppMessageClicked where you’d want to handle the link yourself if it’s of the format of your deep link. Your ticket indicates you’ve tried this, but I’d suggest starting with "the default one we create in the AppboyInAppMessageManager.java (#L608) in the Android SDK - and then just modifying the *clicked methods.
3) Download our UI code and modify the source. You could optionally download the Appboy Android SDK and modify the ActionFactory to handle your deep link in the way you want. Though, at the point you are going to do something like this, solution #2 is likely going to be a nicer one to implement and maintain.
Please let us know if one of these solutions works for you and if you have any other comments/questions.
Thanks,
Waciuma
Here's the use case: I want to create a statistics tool that lists all incoming push messages on a given phone, their message text, when they arrived and their source. clarification: I need 100% access to the data as I'm creating my own presentation tool for private use. It's not to be a consumer app.
I'm thinking I can achieve this by creating an app that somehow listens to all incoming intents of type com.google.android.c2dm.intent.RECEIVE and then analyzing the contents of those. Now I believe that is not possible with the security and intent model of stock Android. But is there anyway around this either with a stock rooted phone, or do I even have to go further and fork and modify AOSP?
Other options I can think of is to monitor the visual notification center itself, if that has an API (which I doubt).
Any suggestions are welcome. I am not intimidated by difficult tasks. Yet my knowledge is limited to Java Android coding - I know little of AOSP or the NDK, but I'd be willing to learn if this is the path I must take.
(Sorry if this is a very broad question, I'll accept the answer that gives me the easiest path to a solution)
So it turns out it wasn't all that difficult. You need an app with minSdkVersion=18 and then you can implement a NotificationListenerService which listens for created or deleted notifications, or you can poll for the currently visible.
Caveat: You need explicit persmission from the user to read notifications other than your own.
Basically what you do is 1. Extend the NotificationListenerInterface and override the onNotificationPosted like this:
#Override
public void onNotificationPosted(StatusBarNotification notif) {
Bundle extras = notif.getNotification().extras;
String packageName = notif.getPackageName();
if (extras != null) {
String title = "" + extras.getCharSequence(Notification.EXTRA_TITLE);
String description = "" + extras.getCharSequence(Notification.EXTRA_TEXT);
// Do whatever you want to do with the data
}
}
In addition you need to register the service in the manifest:
<application>
<!-- (...) -->
<service android:name=".YourListenerClassName"
android:label="#string/app_name" android:permission="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE">
<intent-filter>
<action android:name="android.service.notification.NotificationListenerService" />
</intent-filter>
</service>
</application>