i was trying the NotificationListener to get the coming notifications. Two days ago my class was an activity and everything works fine. The service started and the notification came up in my view with the title, icon and the description of it. Yesterday i implemented the new Navigation View, so, i changed the activity to fragment. After that the notification not showing up. The service starts but if i try to debug the Broadcastreceiver (that is inside the fragment) doesn't work. If i try to create some log inside it they not works. I suppose that the Broadcastreceiver not starts at this point! This is the Broadcastreceiver
/**
* Broadcast receiver notifications
***/
private BroadcastReceiver onNotice= new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
final String pack = intent.getStringExtra("package");
String title = intent.getStringExtra("title");
String text = intent.getStringExtra("text");
if(!pack.equals("") || !title.equals("") || !text.equals("")) {
notificationLayout.setVisibility(View.VISIBLE);
notificationTitle.setText(title);
notificationDescription.setText(text);
try {
icon = getActivity().getPackageManager().getApplicationIcon(pack);
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
notificationImage.setImageDrawable(icon);
} else {
notificationLayout.setVisibility(View.INVISIBLE);
}
}
};
and in my onResume() method of the fragment i wrote this:
LocalBroadcastManager.getInstance(getActivity()).registerReceiver(onNotice, new IntentFilter("Msg"));
I don't know if the change of the class type is the reason of this issue but it's the only change i made.
Related
I have an Unity app, that has Android plugin that can launch other applications that installed on my smartphone. Here My Java class:
public class LaunchOtherApp extends Activity
{
public static Activity mainActivity;
protected static final String LOGTAG = "MyApp";
private Activity currentActivity;
private Intent i;
private static final LaunchOtherApp ourInstance = new LaunchOtherApp();
public static LaunchOtherApp getInstance() {
return ourInstance;
}
public LaunchOtherApp(){
Log.i(LOGTAG,"Created LaunchOtherApp");
}
public void Launch( final String pack)
{
mainActivity.runOnUiThread(new Runnable() {
#Override
public void run() {
Intent intent = new Intent();
intent.setPackage(pack);
currentActivity = UnityPlayer.currentActivity;
Context context = currentActivity.getApplicationContext();
PackageManager pm = context.getPackageManager();
List<ResolveInfo> resolveInfos = pm.queryIntentActivities(intent, 0);
Collections.sort(resolveInfos, new ResolveInfo.DisplayNameComparator(pm));
if (resolveInfos.size() > 0)
{
try
{
ResolveInfo launchable = resolveInfos.get(0);
ActivityInfo activity = launchable.activityInfo;
ComponentName name = new ComponentName(activity.applicationInfo.packageName, activity.name);
i = new Intent(Intent.ACTION_MAIN);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
i.setComponent(name);
context.startActivity(i);
}
catch (SecurityException e)
{
intent = getPackageManager().getLaunchIntentForPackage(pack);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
intent.addCategory(Intent.CATEGORY_LAUNCHER);
startActivity(intent);
}
}
}
});
}
#Override
public void onBackPressed() {
finish();
}
Launch - it is method that starting when I click on button in my Unity app... pack variable - it is variable that my Java method receive, and in this variable instantiate Application id. For Example I launched Youtube from my app, and when I pressing Back on my phone, I want to close Youtube, and back to my Unity app... I think I must use onBackPressed method that start when I press Back, but what I must write in this method?
finish(); doesn't help me(( Please, help... Thank you in advance!
Actually, YouTube app is a separate app (might be installed) and you cannot modify that app's behavior. On your button press, Launch method is called and assume YouTube app has started. With the intent:
If you use Intent.FLAG_ACTIVITY_NEW_TASK
YouTube app will start in a new task than yours and pressing back will not return to your app.
If you do not use Intent.FLAG_ACTIVITY_NEW_TASK
The new intent (here YouTube) will be launched in the task of calling activity (your app/game) by default and calling activity will go background. So, pressing back will again return to your app/game as you desired. Because back button press always pops from the backstack of the current task.
So, in the try block of your Launch method, removing the following line should help.
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
For more information about task and back stack, here is the official doc.
Edit
I missed that you have used application context. But, you have to launch from your calling activity context, otherwise you must use this flag. So, I have modified your Launch method and put it here, just replace your Launch method with following:
/* Method to launch an app with its package name */
public void Launch( final String pack)
{
mainActivity.runOnUiThread(new Runnable() {
#Override
public void run() {
// Using activity context instead of application context
currentActivity = UnityPlayer.currentActivity;
Context context = currentActivity;
PackageManager pm = context.getPackageManager();
// Similar code to launch from package name
Intent intent = pm.getLaunchIntentForPackage(pack);
if (intent == null) {
// The activity cannot be found or the package name cannot be recognized
// Show some message or do something
Toast.makeText(context, "Cannot launch...", Toast.LENGTH_SHORT).show();
} else {
context.startActivity(intent);
}
}
});
}
How can I open Main Activity if user taps on push notification sent from OpenSignal. I wanted to override the default behaviour which was causing some issue when App was active. I added following line as per the doc
<meta-data android:name="com.onesignal.NotificationOpened.DEFAULT" android:value="DISABLE" />
Now if app is closed, how can i open MainActivity, and let it execute NotificationOpenedHandler.
Thank you.
If you still always want your launcher / main Activity to open / resume when tapping on a OneSignal notification add the following code to your Activity intead.
private static boolean activityStarted;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if ( activityStarted
&& getIntent() != null
&& (getIntent().getFlags() & Intent.FLAG_ACTIVITY_REORDER_TO_FRONT) != 0) {
finish();
return;
}
activityStarted = true;
}
See Resume last Activity when opening a Notification instructions for more details.
If you need to do something more custom keep the manifest entry you noted above and add a OneSignal NotificationOpenedHandler to OneSignal.startInit in your Application class.
import com.onesignal.OneSignal;
public class YourAppClass extends Application {
#Override
public void onCreate() {
super.onCreate();
OneSignal.startInit(this)
.setNotificationOpenedHandler(new ExampleNotificationOpenedHandler())
.init();
}
// This fires when a notification is opened by tapping on it or one is received while the app is running.
private class ExampleNotificationOpenedHandler implements NotificationOpenedHandler {
#Override
public void notificationOpened(String message, JSONObject additionalData, boolean isActive) {
// The following can be used to open an Activity of your choice.
/*
Intent intent = new Intent(getApplication(), YourActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT | Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
*/
// Follow the instructions in the link below to prevent the launcher Activity from starting.
// https://documentation.onesignal.com/docs/android-notification-customizations#changing-the-open-action-of-a-notification
}
}
See 4. Add Optional NotificationOpenedHandler for more details on this callback.
I'm using gcm for chat, and I have an onMessageReceived() method that receives the messages, saves them in the database, and sends a notification to the user.
When the app is running (or paused - running in the background), this is how I store the messages in the database:
private DBHelper mDbHelper;
mDbHelper = new DBHelper(MainApplication.getAppContext());
SQLiteDatabase db = mDbHelper.getWritableDatabase();
The method getAppContext() is a static method in my main activity which returns the context.
This all works. I receive a message, save it successfully, and get a notification (when app is running, or in the background).
Problem is when the app is closed. I can't use MainApplication.getAppContext();, because there's no context when the app is closed.
Maybe I should pass the context in some other way?
UPDATE
Eventually I saved messages on server if the app was closed, and when user opens it I fetch'em from server, delete them from there, and save them on user's device. (like a queue pop operation...)
Let me know if there's a better method
see accepted answer...
OK so 1 year later I needed this again and I found the answer:
Turns out there's a static method in SQLiteOpenHelper which opens the database without context: openDatabase().
So replace this:
mDbHelper = new DBHelper(MainApplication.getContext());
db = mDbHelper.getWritableDatabase();
with this:
db = SQLiteDatabase.openDatabase("path/to/database.db", null, OPEN_READWRITE);
The static method openDatabase() doesn't need a context so we can call it even when the app is closed.
Create a class which extends Service and do your database operations in onStartCommand() method. Also start the service in onMessageReceived.
For your need you can make use of broadcast receiver.
first, create a broadcast receiver like below,
public class UpdateReceiver extends BroadcastReceiver {
protected UpdateListener listener;
public UpdateReceiver(UpdateListener listener) {
this.listener = listener;
}
#Override
public void onReceive(Context context, Intent intent) {
if (intent == null || intent.getExtras() == null) {
return;
}
if (intent.getBooleanExtra("message", false)) {
listener.onMessage(intent.getStringExtra("messageText"));
}
}
public interface UpdateListener {
public void onMessage(String message);
}
}
then make your MainActivity implement this receiver, like
public class MainActivity implements UpdateReceiver.UpdateListener
and you need to register your broadcast receiver, then you can override onMessage method in your MainActivity and you can receive your message there.
so your main activity will look like,
public class MainActivity implements UpdateReceiver.UpdateListener {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
UpdateReceiver chatMessageReceiver = new UpdateReceiver (this);
registerReceiver(chatMessageReceiver, new IntentFilter("messagereceived"));
}
#Override
protected void onMessage( String message) {
//do your DB Operations
}
}
in your onMessageReceived method, call this broadcast receiver like,
Intent intent = new Intent();
intent.setAction("messagereceived");
intent.putExtra("message", true);
intent.putExtra("messageText", "your message")
getApplicationContext().sendBroadcast(intent);
I have a java Class that extends Plugin (PhoneGap), but when inside this class, i call another class that extends Activity, it just doesn't work !. i mean, it seems like it doesn't get called. To confirm this, i have change my second class, this time, not extending from Activity and it works fine. i need teh second one to extends from Activity because i am using this two utilities (getFileStreamPath and openFileOutput) to create a file
File filepath = getFileStreamPath("filename.CPCL"); and openFileOutput
FileOutputStream os = this.openFileOutput(fileName, Context.MODE_PRIVATE);
I have an app with a class which extends a custom Service that calls another class which extends Activity.
First I instantiate the Activity. In the onCreate of your Plugin class use:
// get a handle on your Application
Application app = getApplication();
Intent intent = new Intent(getApplicationContext(), YourActivity.class);
app.startActivity(intent);
This will start your Activity and call the standard Lifecycle events.
The way I handle continued communication with the running Activity is by using a Handler to send a broadcast from your plugin which the Activity picks up in its receiver. In the onCreate of your plugin:
mHandler.post(new Runnable() {
#Override
public void run() {
Log.d(TAG, "Call the Activity");
Intent intent = new Intent(YourActivity.CALL_FROM_PLUGIN);
intent.putExtra("request", <<Any extras you might want to send through>>);
sendBroadcast(intent);
}
});
In the Activity I declare the variable:
public static final String CALL_FROM_PLUGIN= "CALL_FROM_PLUGIN";
then in onCreate() I added the following;
IntentFilter filter = new IntentFilter();
filter.addAction(CALL_FROM_PLUGIN);
registerReceiver(mBroadcastReceiver, filter);
and then implemented a BroadcastReceiver:
BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
Log.d(TAG, "BroadcastReceiver.onReceive()");
if (CALL_FROM_PLUGIN.equals(action)) {
Log.d(TAG, "Received call from Plugin");
// DO YOUR STUFF HERE
}
}
};
Someone else might be able to point out why this is necessary from a framework point of view, but this is the way I understand that Activities should be called. I hope this applies to your plugin class the way it does with my service class!
I'm android beginner so please be easy on me. I'm doing some "exercises" and i'm writing simple app which will tell RSSI strength of home wifi network. Getting that number is pretty easy, but updating it and showing that on screen it's a little more complicated as i thought.
First this is my onCreate Activity. In this activity i'm launching another android component - Service. Because the code will run in background (i know i could use thread or something else, but this is for "practice" sake, and i have a few ideas what to do with this app, while running service and not interacting with UI )
public class MainActivity extends Activity {
TextView wifi_check;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
referenceViews();
startService(new Intent(this, CheckingWifiService.class));
//wifi_check.setText(""+getIntent().getExtras().getInt("RSSI"));
}
private void referenceViews() {
wifi_check = (TextView) findViewById(R.id.wifiCheck_TV);
}
}
Because my code will run every second or so, i will use TimerTask for this purpose. And here is my TimerTask class, which includes run() method, and code for executing inside
public class TimerTsk extends TimerTask {
Context act;
WifiManager wifiMan;
WifiInfo info;
Bundle sendInfo;
Intent intent;
int rssi;
public TimerTsk(Context context) {
act = context;
}
#Override
public void run() {
intent = new Intent();
sendInfo = new Bundle();
wifiMan = (WifiManager) act.getSystemService(Activity.WIFI_SERVICE);
info = wifiMan.getConnectionInfo();
rssi = info.getRssi();
Log.d("WORKED", "RUNNING SUCESSFULLY");
// i want to send info to my activity
sendInfo.putInt("RSSI", rssi);
intent.putExtras(sendInfo);
}
}
From this class , i want to send result of RSSI to my activity and then update a text. But when i call this code below, on activity i always get NullPointerException.
wifi_check.setText(""+getIntent().getExtras().getInt("RSSI"));
To be honest i had hard time figuring out which part of code is throwing an exepction. And i found that more exactly, this part of code is throwing an exepction.
getInt("RSSI")
Overall i see that service is running, because in my LOGCAT i see a message that i create with Log.d in TimerTsk class.
Any ideas why is this happening?
Here is my service class:
public class CheckingWifiService extends Service{
int rssi;
Timer time;
TimerTsk ttsk;
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
time = new Timer();
time.schedule(new TimerTsk(getApplicationContext()), 500);
return START_STICKY;
}
}
Here is my LogCat:
I see a common mistake. Don't do this:
sendInfo.putInt("RSSI", rssi);
intent.putExtras(sendInfo); // This adds a Bundle to your existing Bundle!
You are creating an Intent, with a Bundle of extras, with a Bundle that holds rssi. Leave out this unnecessary Bundle:
intent.putExtras("RSSI", rssi);
Now in your next Activity you can use:
getIntent().getIntExtra("RSSI", 0);
However you should always check to make sure there aren't any surprise null variables:
Intent in = getIntent();
if(in != null) {
int rssi = in.getIntExtra("RSSI", -1);
if(rssi < 0)
wifi_check.setText(""+rssi);
else
wifi_check.setText("Unknown");
}
is your activity starting? I don't see any call to startActivity(). In any case as mentioned by Sam you just need to call putExtra for your intent. don't forget to call
is your activity starting? I don't see any call to startActivity(). In any case as mentioned by Sam you just need to call putExtra for your intent. don't forget to call
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
you need to put this flag when start activies from background