I'm trying to develop a Geofence App for Android, that barely have to notify me when enter/exit/dwell in/from/into a Geofence.
Despite all questions and answers I red, I'm still not able to figure out my problem.
I think something is wrong with my PendinIntent and/or IntentService.
Here what I've done so far.
MainActivity.java
package it.coppola.geofencedetecttest1;
import android.app.Dialog;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.location.Location;
import android.location.LocationManager;
import android.os.Bundle;
import android.support.v4.app.DialogFragment;
import android.support.v4.content.LocalBroadcastManager;
import android.support.v7.app.ActionBarActivity;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.widget.TextView;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GooglePlayServicesUtil;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.common.api.GoogleApiClient.ConnectionCallbacks;
import com.google.android.gms.common.api.GoogleApiClient.OnConnectionFailedListener;
import com.google.android.gms.location.Geofence;
import com.google.android.gms.location.GeofencingRequest;
import com.google.android.gms.location.LocationServices;
public class MainActivity extends ActionBarActivity implements
ConnectionCallbacks,OnConnectionFailedListener{
private GoogleApiClient mGoogleApiClient;
private GeofenceSampleReceiver mGeofenceReceiver;
private IntentFilter filter;
private Location mCurrentLocation;
private PendingIntent mPendingIntent;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mGoogleApiClient=new GoogleApiClient.Builder(this)
.addApi(LocationServices.API)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.build();
filter=new IntentFilter();
filter.addAction("it.coppola.geofencedetecttest1.ACTION_GEOFENCES_ERROR");
filter.addAction("it.coppola.geofencedetecttest1.ACTION_GEOFENCES_SUCCESS");
mGeofenceReceiver=new GeofenceSampleReceiver();
LocalBroadcastManager.getInstance(this).registerReceiver(mGeofenceReceiver, filter);
}
#Override
protected void onResume(){
super.onResume();
LocalBroadcastManager.getInstance(this).registerReceiver(mGeofenceReceiver, filter);
}
#Override
protected void onPause(){
super.onPause();
LocalBroadcastManager.getInstance(this).unregisterReceiver(mGeofenceReceiver);
}
#Override
protected void onStop(){
super.onStop();
LocalBroadcastManager.getInstance(this).unregisterReceiver(mGeofenceReceiver);
}
#Override
protected void onDestroy(){
super.onDestroy();
}
public void onConnectToLocation(View v){
//stuff that happens when i press a button. Here is mGoogleApiClient.connect()
}
public void onConnected(Bundle connectionHint){
mCurrentLocation= LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
if (mCurrentLocation != null){
TextView lan=(TextView)findViewById(R.id.txtLan);
lan.setText(String.valueOf(mCurrentLocation.getLatitude()));
TextView lon=(TextView)findViewById(R.id.txtLong);
lon.setText(String.valueOf(mCurrentLocation.getLongitude()));
Geofence mGeofence1=new Geofence.Builder()
.setRequestId("Geofence1")
.setCircularRegion(mCurrentLocation.getLatitude(), mCurrentLocation.getLongitude(), 5)
.setTransitionTypes(Geofence.GEOFENCE_TRANSITION_ENTER|Geofence.GEOFENCE_TRANSITION_EXIT|Geofence.GEOFENCE_TRANSITION_DWELL)
.setExpirationDuration(Geofence.NEVER_EXPIRE)
.setLoiteringDelay(1000)
.build();
mPendingIntent=requestPendingIntent();
GeofencingRequest mGeofenceRequest=new GeofencingRequest.Builder()
.addGeofence(mGeofence1)
.build();
LocationServices.GeofencingApi.addGeofences(mGoogleApiClient, mGeofenceRequest, mPendingIntent);
}
else {
}
}
/**
* Define a Broadcast receiver that receives updates from connection listeners and
* the geofence transition service.
*/
public class GeofenceSampleReceiver extends BroadcastReceiver {
/*
* Define the required method for broadcast receivers
* This method is invoked when a broadcast Intent triggers the receiver
*/
#Override
public void onReceive(Context context, Intent intent) {
// Check the action code and determine what to do
String action = intent.getAction();
Log.d("miotag","ho ricevuto questo intent: "+action);
if (TextUtils.equals(action, "it.coppola.geofencedetecttest1.ACTION_GEOFENCES_ERROR")){
Log.d("miotag","ho ricevuto un errore dal Location Service");
}
else if (TextUtils.equals(action, "it.coppola.geofencedetecttest1.ACTION_GEOFENCES_SUCCESS")){
Log.d("miotag","intent ricevuto: OK");
}
}
}
private PendingIntent requestPendingIntent(){
if (null != mPendingIntent){
return mPendingIntent;
} else {
Intent intent=new Intent(this, GeofenceReceiverSample.class);
return PendingIntent.getService(
this,
0,
intent,
PendingIntent.FLAG_UPDATE_CURRENT);
}
}
public void stopIt(View v){
LocationServices.GeofencingApi.removeGeofences(mGoogleApiClient, mPendingIntent);
Log.d("miotag","geofence rimossa");
mGoogleApiClient.disconnect();
}
}
I've omitted some line of code not of interest.
here is my IntentService
package it.coppola.geofencedetecttest1;
import java.util.List;
import android.app.IntentService;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.support.v4.app.NotificationCompat;
import com.google.android.gms.location.Geofence;
import com.google.android.gms.location.GeofencingEvent;
public class GeofenceReceiverSample extends IntentService{
public GeofenceReceiverSample(){
super("GeofenceReceiverSample");
}
#Override
protected void onHandleIntent(Intent intent) {
GeofencingEvent geoEvent=GeofencingEvent.fromIntent(intent);
if (geoEvent.hasError()) {
//todo error process
} else {
int transitionType = geoEvent.getGeofenceTransition();
if (transitionType == Geofence.GEOFENCE_TRANSITION_ENTER ||
transitionType == Geofence.GEOFENCE_TRANSITION_EXIT) {
List<Geofence> triggerList = geoEvent.getTriggeringGeofences();
for (Geofence geofence : triggerList) {
generateNotification(geofence.getRequestId(), "address you defined");
}
}
}
}
private void generateNotification(String locationId, String address) {
long when = System.currentTimeMillis();
Intent notifyIntent = new Intent(this, MainActivity.class);
notifyIntent.putExtra("id", locationId);
notifyIntent.putExtra("address", address);
notifyIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notifyIntent, PendingIntent.FLAG_UPDATE_CURRENT);
NotificationCompat.Builder builder =
new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.ic_launcher)
.setContentTitle(locationId)
.setContentText(address)
.setContentIntent(pendingIntent)
.setAutoCancel(true)
.setDefaults(Notification.DEFAULT_SOUND)
.setWhen(when);
NotificationManager notificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify((int) when, builder.build());
}
}
I've just pasted this IntentService from enter link description here, with few change.
Right now, I want to focus on IntentService and its handler: so at the moment I'm not asking for Broadcast Receiver that will be trigged from IntentService after the notification. This is why in my MainActivity there isn't any BroadcastReceiver class declared
My AndroidManifest
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="it.coppola.geofencedetecttest1"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="11"
android:targetSdkVersion="21" />
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<!--
<uses-permission android:name="android.permission.ACCESS_MOCK_LOCATION" />
-->
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity
android:name="it.coppola.geofencedetecttest1.MainActivity"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service android:name=".GeofenceReceiverSample"
android:exported="false">
</service>
<receiver android:name="it.coppola.geofencedetecttest1.GeofenceSampleReceiver"
android:exported="false">
<intent-filter >
<action android:name="it.coppola.geofencedetecttest1.ACTION_RECEIVE_GEOFENCE"/>
</intent-filter>
</receiver>
<meta-data
android:name="com.google.android.gms.version"
android:value="#integer/google_play_services_version" />
</application>
</manifest>
Few more notes:
I really don't know why, but a couple of time the app actually works: my IntentService was fired up from Google Play Service intent and execute a previous version of the code. Weird enough, when I launchede again the same app without any change in the code, IntentService wasn't fired up.
I'm developing with my tablet/smartphone as emulator device: I tried to walk around but no luck at all.
Any help is highly appreciate.
Thanks.
Following the answer provided by ianhanniballake, I've done more tests with radius that space between 20-30-40 meters, and I found out that all works as intended. As he said, my problems was about the radius settings too small for GPS to recognize its own position.
Sincerely thanks.
Related
We have a requirement to show an acknoldgement screen after user share some texts on Messaging apps such as Whatsapp, Telegram, SMS etc..
We have been using the react-native-share library for this and it works fine on non Huawei devices. However, Huawei devices doesn't return success/failure when user share hence the app gives issues on Huawei devices.
Upon checking the react-native-share library internal codes, it seems the BroadcastReceiver onReceive method does not get triggered when user choose and app on HuaweiChooser.
I created the following sample code to simulate this and on Non-Huawei devices this code's onReceive method get triggered but not in Huawei devices.
Appreciate any help regarding this.
This is the Sample code
MainActivity.java
import androidx.appcompat.app.AppCompatActivity;
import android.content.Intent;
import android.content.IntentSender;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button shareButton = findViewById(R.id.button);
shareButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent chooser;
IntentSender intentSender = MyReceiver.getIntentSender(getApplicationContext());
Intent sendIntent = new Intent();
sendIntent.setAction(Intent.ACTION_SEND);
sendIntent.putExtra(Intent.EXTRA_TEXT, "This is my text to send.");
sendIntent.setType("text/plain");
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP_MR1) {
chooser = Intent.createChooser(sendIntent,"Sharing Rocks",intentSender);
chooser.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
}else{
chooser = Intent.createChooser(sendIntent,"Sharing Rocks");
}
startActivityForResult(chooser, 1234);
}
});
}
}
Receiver.Java
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.IntentSender;
import android.widget.Toast;
public class MyReceiver extends BroadcastReceiver {
private static MyReceiver myReceiver;
private static final String EXTRA_RECEIVER_TOKEN = "receiver_token";
public static IntentSender getIntentSender(Context context){
String intentAction = context.getPackageName()+"_ACTION";
myReceiver = new MyReceiver();
context.registerReceiver(myReceiver, new IntentFilter(intentAction));
Intent intent = new Intent(intentAction);
intent.setPackage(context.getPackageName());
intent.putExtra(EXTRA_RECEIVER_TOKEN,myReceiver.hashCode());
PendingIntent callback = PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
return callback.getIntentSender();
}
#Override
public void onReceive(Context context, Intent intent) {
System.out.println("//// Inside onReceive");
ComponentName target = intent.getParcelableExtra(Intent.EXTRA_CHOSEN_COMPONENT);
System.out.println("//// target : " + target);
}
}
Manifest File
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.lk.infinitx.huaweisharetest">
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="#style/Theme.HuaweiShareTest">
<receiver
android:name=".MyReceiver"
android:enabled="true"
android:exported="true"></receiver>
<activity
android:name=".MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
I change chooser title with "null" and my problem solved.
val chooser = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP_MR1) {
Intent.createChooser(sendIntent, null, pendingIntent.intentSender)
} else {
Intent.createChooser(sendIntent, null)
}
I am working on an app in react native. I am searching for a code when my app is in the background or has killed. I want a service like notifcationListnerService which invokes the app again. want a similar service that is always running and when a user copies something it will show a push notification to the user like that you have copied something.
Here is what I have tried but these are too complex to understand because these are in java.
Android ClipBoard Manager
Android ClipBoard With Example
This question from StackOverflow also does not have any answer
A solution for GitHub but too complex
one thing I didn't need #react-native-community/clipboard or something like this. the thing that I need is to show push notification on copying something for any app installed of the device.
So Finally searching for two days finally I have implemented what I want. I am showing a toast, not a notification(will implement it later). I am sharing my code but still, I have a problem when my application restart its service for clipboard manager the service is running as I see it in the logcat. Here is my code.
ClipboardMonitorService.java
package com.wm;
import android.app.Service;
import android.content.ClipData;
import android.content.ClipboardManager;
import android.content.Intent;
import android.os.Environment;
import android.os.IBinder;
import android.text.TextUtils;
import android.util.Log;
import android.widget.Toast;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.Date;
public class ClipboardMonitorService extends Service {
private static final String TAG = "ClipboardManager";
private static final String FILENAME = "clipboard-history.txt";
private File mHistoryFile;
private ExecutorService mThreadPool = Executors.newSingleThreadExecutor();
private ClipboardManager mClipboardManager;
#Override
public void onCreate() {
super.onCreate();
Log.e("service is running","service is running");
// TODO: Show an ongoing notification when this service is running.
mHistoryFile = new File(getExternalFilesDir(null), FILENAME);
mClipboardManager =
(ClipboardManager) getSystemService(CLIPBOARD_SERVICE);
mClipboardManager.addPrimaryClipChangedListener(
mOnPrimaryClipChangedListener);
}
#Override
public void onDestroy() {
super.onDestroy();
if (mClipboardManager != null) {
mClipboardManager.removePrimaryClipChangedListener(
mOnPrimaryClipChangedListener);
}
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
private boolean isExternalStorageWritable() {
String state = Environment.getExternalStorageState();
if (Environment.MEDIA_MOUNTED.equals(state)) {
return true;
}
return false;
}
private ClipboardManager.OnPrimaryClipChangedListener mOnPrimaryClipChangedListener =
new ClipboardManager.OnPrimaryClipChangedListener() {
#Override
public void onPrimaryClipChanged() {
Log.d(TAG, "onPrimaryClipChanged");
ClipData clip = mClipboardManager.getPrimaryClip();
mThreadPool.execute(new WriteHistoryRunnable(clip.getItemAt(0).getText()));
Log.e("Copied Text","hahah"+clip.getItemAt(0).getText());
Toast.makeText(getApplicationContext(),"My App toast",Toast.LENGTH_SHORT).show();
}
};
private class WriteHistoryRunnable implements Runnable {
private final Date mNow;
private final CharSequence mTextToWrite;
public WriteHistoryRunnable(CharSequence text) {
mNow = new Date(System.currentTimeMillis());
mTextToWrite = text;
}
#Override
public void run() {
if (TextUtils.isEmpty(mTextToWrite)) {
// Don't write empty text to the file
return;
}
if (isExternalStorageWritable()) {
try {
Log.i(TAG, "Writing new clip to history:");
Log.i(TAG, mTextToWrite.toString());
BufferedWriter writer =
new BufferedWriter(new FileWriter(mHistoryFile, true));
writer.write(String.format("[%s]: ", mNow.toString()));
writer.write(mTextToWrite.toString());
writer.newLine();
writer.close();
} catch (IOException e) {
Log.w(TAG, String.format("Failed to open file %s for writing!",
mHistoryFile.getAbsoluteFile()));
}
} else {
Log.w(TAG, "External storage is not writable!");
}
}
}
}
This is used for when the app is closed or the device is restarted then it will start the service again.
BootUpRecever.java
package com.wm;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
public class BootUpReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
if(intent.getAction() == Intent.ACTION_BOOT_COMPLETED){
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
//log("Starting the service in >=26 Mode from a BroadcastReceiver")
context.startForegroundService(new Intent(context, ClipboardMonitorService.class));
return;
}
//log("Starting the service in < 26 Mode from a BroadcastReceiver")
context.startService(new Intent(context, ClipboardMonitorService.class));
}
}
}
to start the activity as the app start
MainActivity.java
package com.wm;
import android.content.Intent;
import android.os.Bundle;
import com.facebook.react.ReactActivity;
public class MainActivity extends ReactActivity {
#Override
protected String getMainComponentName() {
return "wm";
}
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
// TODO: Show the contents of the clipboard history.
startService(new Intent(this, ClipboardMonitorService.class));
}
}
Here are the permissions and to start the service
AndroidManifest.xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.wm">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
<uses-permission android:name="android.permission.READ_CONTACTS" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<application
android:name=".MainApplication"
android:label="#string/app_name"
android:icon="#mipmap/ic_launcher"
android:roundIcon="#mipmap/ic_launcher_round"
android:allowBackup="true"
android:theme="#style/AppTheme">
<activity
android:name=".MainActivity"
android:label="#string/app_name"
android:configChanges="keyboard|keyboardHidden|orientation|screenSize|uiMode"
android:launchMode="singleTask"
android:windowSoftInputMode="adjustResize">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name="com.facebook.react.devsupport.DevSettingsActivity" />
<service
android:name=".ClipboardMonitorService"
android:label="Clipboard Monitor"
android:exported="false"/>
<receiver
android:name=".BootUpReceiver"
android:enabled="true"
android:permission="android.permission.RECEIVE_BOOT_COMPLETED">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>
</application>
</manifest>
I am not receiving push notification for my app. I have included the manifest files, the MainActivity file, the MyFireBaseMessagingService file and the build.gradle file and the googl-services.json. I really am stumped on what the issue could be. I go to Firebase composer to write message but nothing is received. I can hard code values in strings file and I receive a notification but I wanted something more dynamic. That is why I am trying to figure out how to send push notifications from FCM but I seem to be missing something or inputting something incorrectly.
MainAcitivity file
package com.example.testaaedapp;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.app.NotificationCompat;
import androidx.core.app.NotificationManagerCompat;
import androidx.core.content.ContextCompat;
import android.Manifest;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.TaskStackBuilder;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Parcelable;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.Toast;
import com.google.android.gms.tasks.OnCompleteListener;
import com.google.android.gms.tasks.Task;
import com.google.firebase.iid.FirebaseInstanceId;
import com.google.firebase.iid.InstanceIdResult;
import java.net.URI;
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private ImageButton logoButton;
private ImageView blueButton, greenButton, orangeButton, yellowButton, redButton, darkBlueButton;
public Button callButton;
private final String CHANNEL_ID = "Alerts";
private final int notificationId = 001;
private static final String TAG = "MainActivity";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
logoButton = findViewById(R.id.imageButton);
logoButton.setOnClickListener(this);
blueButton = findViewById(R.id.bluepuzzlepiece);
blueButton.setOnClickListener(this);
redButton = findViewById(R.id.redpuzzlepiece);
redButton.setOnClickListener(this);
greenButton = findViewById(R.id.greenpuzzlepiece);
greenButton.setOnClickListener(this);
orangeButton = findViewById(R.id.orangepuzzlepiece);
orangeButton.setOnClickListener(this);
yellowButton = findViewById(R.id.yellowpuzzlepiece);
yellowButton.setOnClickListener(this);
darkBlueButton = findViewById(R.id.darkbluepuzzlepiece);
darkBlueButton.setOnClickListener(this);
callButton = findViewById(R.id.button);
callButton.setOnClickListener(this);
displayNotification();
// Get token
// [START retrieve_current_token]
FirebaseInstanceId.getInstance().getInstanceId()
.addOnCompleteListener(new OnCompleteListener<InstanceIdResult>() {
#Override
public void onComplete(#NonNull Task<InstanceIdResult> task) {
if (!task.isSuccessful()) {
Log.w(TAG, "getInstanceId failed", task.getException());
return;
}
// Get new Instance ID token
String token = task.getResult().getToken();
// Log and toast
String msg = getString(R.string.msg_token_fmt, token);
Log.d(TAG, msg);
Toast.makeText(MainActivity.this, msg, Toast.LENGTH_SHORT).show();
}
});
// [END retrieve_current_token]
}
int requestCode = 0;
public void onClick(View view) {
if (view.getId() == R.id.button && ActivityCompat.checkSelfPermission(MainActivity.this,
Manifest.permission.CALL_PHONE) != PackageManager.PERMISSION_GRANTED) {
Log.d("STATE", "Call Button DOES NOT WORK");
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CALL_PHONE}, requestCode);
return;
} else if (view.getId() == R.id.button && ActivityCompat.checkSelfPermission(MainActivity.this,
Manifest.permission.CALL_PHONE) == PackageManager.PERMISSION_GRANTED) {
// else if (view.getId() == R.id.button && ActivityCompat.checkSelfPermission(MainActivity.this,
// Manifest.permission.CALL_PHONE) == PackageManager.PERMISSION_GRANTED) {
Log.d("STATE", "Call Button DOES WORK");
Intent callIntent = new Intent(Intent.ACTION_CALL);
callIntent.setData(Uri.parse("tel:480-240-9255"));
startActivity(callIntent);
} else {
switch (view.getId()) {
case R.id.imageButton:
setContentView(R.layout.activity_main);
break;
case R.id.bluepuzzlepiece:
break;
case R.id.redpuzzlepiece:
Intent blogIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("https://www.aaed.org/blog"));
startActivity(blogIntent);
break;
case R.id.greenpuzzlepiece:
Intent videoIntent = new Intent(Intent.ACTION_VIEW);
videoIntent.setData(Uri.parse("https://www.youtube.com/channel/UCUwPShLvnCOTeQILvAtneOw"));
startActivity(videoIntent);
break;
case R.id.yellowpuzzlepiece:
Intent secondActivity = new Intent(this, SecondActivity.class);
startActivity(secondActivity);
break;
case R.id.orangepuzzlepiece:
Intent webIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("https://www.aaed.org"));
startActivity(webIntent);
break;
case R.id.darkbluepuzzlepiece:
Intent schoolIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("https://www.aaed.org/online-course-content"));
startActivity(schoolIntent);
}
}
}
public void displayNotification () {
createNotificationChannel();
NotificationCompat.Builder builder = new NotificationCompat.Builder(this, CHANNEL_ID)
.setSmallIcon(R.drawable.ic_puzzlepieces)
.setContentTitle("Test Message")
.setContentText("This is text")
.setPriority(NotificationCompat.PRIORITY_HIGH)
.setStyle(new NotificationCompat.BigTextStyle()
.bigText(getString((R.string.another_string))));
NotificationManagerCompat notificationManager = NotificationManagerCompat.from(this);
// notificationId is a unique int for each notification that you must define
notificationManager.notify(notificationId, builder.build());
}
public void createNotificationChannel() {
// Create the NotificationChannel, but only on API 26+ because
// the NotificationChannel class is new and not in the support library
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
CharSequence name = getString(R.string.channel_name);
String description = getString(R.string.channel_description);
int importance = NotificationManager.IMPORTANCE_DEFAULT;
NotificationChannel channel = new NotificationChannel(CHANNEL_ID, name, importance);
channel.setDescription(description);
/
/ Register the channel with the system; you can't change the importance
// or other notification behaviors after this
NotificationManager notificationManager = getSystemService(NotificationManager.class);
notificationManager.createNotificationChannel(channel);
}
}
#Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == requestCode)
{
if(grantResults.length>0 && grantResults[0] == PackageManager.PERMISSION_GRANTED)
{
Intent callIntent = new Intent(Intent.ACTION_CALL);
callIntent.setData(Uri.parse("tel:480-240-9255"));
startActivity(callIntent);
}
}
MyFirebaseMessagingService file
package com.example.testaaedapp;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.media.RingtoneManager;
import android.net.Uri;
import android.os.Build;
import android.util.Log;
import androidx.core.app.NotificationCompat;
import com.example.testaaedapp.MainActivity;
import com.example.testaaedapp.R;
import com.google.firebase.messaging.FirebaseMessagingService;
public class MyFirebaseMessagingService extends FirebaseMessagingService {
private static final String TAG = "MyFirebaseMsgService";
// [START on_new_token]
/**
* Called if InstanceID token is updated. This may occur if the security of
* the previous token had been compromised. Note that this is called when the InstanceID token
* is initially generated so this is where you would retrieve the token.
*/
#Override
public void onNewToken(String token) {
Log.d(TAG, "Refreshed token: " + token);
// If you want to send messages to this application instance or
// manage this apps subscriptions on the server side, send the
// Instance ID token to your app server.
sendRegistrationToServer(token);
}
// [END on_new_token]
Manifest File
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.testaaedapp">
<!--
The ACCESS_COARSE/FINE_LOCATION permissions are not required to use
Google Maps Android API v2, but you must specify either coarse or fine
location permissions for the 'MyLocation' functionality.
-->
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity
android:name=".MapsActivity"
android:label="#string/title_activity_maps"></activity>
<meta-data
android:name="com.google.firebase.messaging.default_notification_channel_id"
android:value="AAED" />
<meta-data
android:name="com.google.firebase.messaging.default_notification_icon"
android:resource="#drawable/ic_puzzlepieces" />
<meta-data
android:name="com.google.firebase.messaging.default_notification_color"
android:resource="#color/colorAccent" />
<activity
android:name=".MainActivity"
android:label="Autism Academy"
>
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".SecondActivity"
android:label="Locations"></activity>
<meta-data
android:name="com.google.android.geo.API_KEY"
android:value="#string/google_maps_key" />
<!-- [START firebase_service] -->
<service
android:name=".MyFirebaseMessagingService"
android:exported="false"
android:enabled="true">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
<!-- [END firebase_service] -->
</application>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.CALL_PHONE"></uses-permission>
</manifest>
I've had a similar issue. I've tried everything - in my opinion the main reason is that all the services are, sooner or later, being killed by the system. The only way is to make sure to deliver the notification to the system tray not to the application. To do that you need to use Data message notifications.
There are 2 types of FCM notifications: Notification message and Data message.
Data messages are delivered to system tray and are always display - even if service is not running.
Notification message looks like:
{
"message":{
"token":"bk3RNwTe3H0:CI2k_HHwgIpoDKCIZvvDMExUdFQ3P1...",
"notification":{
"title":"Portugal vs. Denmark",
"body":"great match!"
}
}
}
and triggers method OnMessageReceaved() of FirebaseMessagingService. Many devices (especially Huawei and Xiaomi) try to do everything to kill background services to prevent battery drain. So the FirebaseMessagingService isn't the best way to handle notifications.
Second type is Data message:
{
"message":{
"token":"bk3RNwTe3H0:CI2k_HHwgIpoDKCIZvvDMExUdFQ3P1...",
"data":{
"Nick" : "Mario",
"body" : "great match!",
"Room" : "PortugalVSDenmark"
}
}
}
This type is handled by the system tray, so you don't need any of service running to get the notification. Its much more convenient method, but as far i know, it can't be achieved with the console.
You would probably need server API to send Data message.
Read this for more details.
I just started with Java and Android coding. I wrote an application for a scientific study in my university. The app is for a local exhibition of a museum. I have different locations in my town, each location with its own exhibit.
Now I made an activity for each of the locations, so the user can see some useful information of the sample. Now I want to combine the app with iBeacons, I bought 6 beacons from Estimote.
I want the app to give the user a notification with some text like: "You are in front of object XY. Tap to see more information." After tapping on the notification the user should open the specific activity which I created. I also want the app to search for beacons in the background, so if the user comes close to a location, he/she gets automatically a notification after a few seconds.
I already wrote some code but I don't know how to approach further. The application does nothing right now.
I did an extra class for the iBeacon stuff, in my MainActivity I have a menu in which the user can select a new activity, which is called "List Of Places". Then s/he can select the specific activity for each of the locations.
So here I have my beacon class:
package com.example.walter.him;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.app.Application;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.TaskStackBuilder;
import android.support.v4.app.NotificationCompat;
import org.altbeacon.beacon.BeaconConsumer;
import org.altbeacon.beacon.BeaconManager;
import org.altbeacon.beacon.BeaconParser;
import org.altbeacon.beacon.Identifier;
import org.altbeacon.beacon.Region;
import org.altbeacon.beacon.powersave.BackgroundPowerSaver;
import org.altbeacon.beacon.startup.RegionBootstrap;
import org.altbeacon.beacon.startup.BootstrapNotifier;
import java.util.Arrays;
import java.util.List;
public class BeaconMain extends Application implements BootstrapNotifier
{
private static final String TAG = "AndroidProximityReferenceApplication";
private RegionBootstrap regionBootstrap;
private BackgroundPowerSaver backgroundPowerSaver;
private boolean haveDetectedBeaconsSinceBoot = false;
private andreasplatz monitoringActivity = null;
private hagentor monitoringActivity2 = null;
public void onCreate(Bundle savedInstanceState)
{
super.onCreate();
BeaconManager beaconManager = org.altbeacon.beacon.BeaconManager.getInstanceForApplication(this);
beaconManager.getBeaconParsers().add(new BeaconParser().setBeaconLayout("m:2-3=0215,i:4-19,i:20-21,i:22-23,p:24-24"));
beaconManager.bind((BeaconConsumer) this);
Region museumLocation1 = new Region("museumLocation1", Identifier.parse("B9407F30-F5F8-466E-AFF9-25556B57FE6D"), Identifier.parse("56170"), Identifier.parse("42307"));
Region museumLocation2 = new Region("museumLocation2", Identifier.parse("B9407F30-F5F8-466E-AFF9-25556B57FE6D"), Identifier.parse("55787"), Identifier.parse("12089"));
List regionList = Arrays.asList(new Region[]{museumLocation1, museumLocation2});
regionBootstrap = new RegionBootstrap(this, regionList);
backgroundPowerSaver = new BackgroundPowerSaver(this);
}
public void didEnterRegion(Region region) {
if (region.getUniqueId().equals("museumLocation1")) {
Intent intent = new Intent(this, andreasplatz.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
this.startActivity(intent);
}
if (region.getUniqueId().equals("museumLocation2")) {
Intent intent = new Intent(this, hagentor.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
this.startActivity(intent);
}
haveDetectedBeaconsSinceBoot = true;
}
#Override
public void didExitRegion(Region region) {
}
#Override
public void didDetermineStateForRegion(int i, Region region) {
}
private void sendNotification() {
NotificationCompat.Builder builder =
new NotificationCompat.Builder(this)
.setContentTitle("Beacon Reference Application")
.setContentText("An beacon is nearby.")
.setSmallIcon(R.drawable.ic_launcher);
TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);
stackBuilder.addNextIntent(new Intent(this, andreasplatz.class));
PendingIntent resultPendingIntent =
stackBuilder.getPendingIntent(
0,
PendingIntent.FLAG_UPDATE_CURRENT
);
builder.setContentIntent(resultPendingIntent);
NotificationManager notificationManager =
(NotificationManager) this.getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(1, builder.build());
}
public void setMonitoringActivity(andreasplatz activity) {
this.monitoringActivity = activity;
}
}
The activity "andreasplatz" would be an exemplary location. The activity "hagentor" has the same code in it. So here is the code for it:
package com.example.walter.him;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.os.Bundle;
import org.altbeacon.beacon.BeaconManager;
public class andreasplatz extends Activity {
protected static final String TAG = "MonitoringActivity";
private BeaconManager beaconManager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_andreasplatz);
verifyBluetooth();
}
private void verifyBluetooth() {
try {
if (!BeaconManager.getInstanceForApplication(this).checkAvailability()) {
final AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("Bluetooth not enabled");
builder.setMessage("Please enable bluetooth in settings and restart this application.");
builder.setPositiveButton(android.R.string.ok, null);
builder.setOnDismissListener(new DialogInterface.OnDismissListener() {
#Override
public void onDismiss(DialogInterface dialog) {
finish();
System.exit(0);
}
});
builder.show();
}
}
catch (RuntimeException e) {
final AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("Bluetooth LE not available");
builder.setMessage("Sorry, this device does not support Bluetooth LE.");
builder.setPositiveButton(android.R.string.ok, null);
builder.setOnDismissListener(new DialogInterface.OnDismissListener() {
#Override
public void onDismiss(DialogInterface dialog) {
finish();
System.exit(0);
}
});
builder.show();
}
}
}
What should I add or change, to do the app what I want? Here s an extract of my Manifest.xml - may be I did something wrong in it:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
android:versionCode="1"
android:versionName="1.0"
package="com.example.walter.him" >
<uses-sdk
android:minSdkVersion="18"
android:targetSdkVersion="18" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme"
android:launchMode="singleInstance" >
<activity
android:name=".MainActivity"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
A few tips:
Since you are using the RegionBootstrap you do not need to make a call to bind to the beaconManager. Remove this line:
beaconManager.bind((BeaconConsumer) this);
Add debug lines to the top of your BeaconMain class' onCreate and didEnterRegion methods like this:
// put this at the top of onCreate
Log.d(TAG, "onCreate called");
// put this at the top of didEnterRegion
Log.d(TAG, "didEnterRegion called with: "+region..getUniqueId());
Make sure your beacons are transmitting those identifiers. Use an off the shelf beacon detector app like Locate when your beacons are turned on and make sure you see the same identifiers:
B9407F30-F5F8-466E-AFF9-25556B57FE6D 56170 42307
B9407F30-F5F8-466E-AFF9-25556B57FE6D 55787 12089
Once you have done the above, turn off your beacons, kill your app from the task switcher, re-launch your app, and turn on the beacons.
Watch the LogCat output and look for debug lines telling you if onCreate and didEnterRegion are called.
I have an app that before worked fine but recently won't run.
Before it only had offline features, the most complex would be the local notification - but I need to add a GCM functionality to it. I searched for answers but it's so difficult to understand.
I tried to copy the code of a tutorial I've seen. I learned that I need a thing called GCMRegistrar but I don't know where to get it. Then I tested my app, there were errors of course because I don't have the gcmregistrar.
What I did is I enclosed the code in a comment block and ran the app again. That's when my app won't run anymore. After a few days of this mishap, I decided to create another app where I would put all the offline feature of my app. after that copying and pasting, I tried to run my the new app but it also won't run.
I've searched for ways to fix it and found a few fixes. Those fix works for other apps but won't work for my new app.
Here's my MainActivity.java, this one has the local notification
package com.example.mypower_build101;
import android.app.Activity;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
import android.media.RingtoneManager;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.Toast;
public class MainActivity extends Activity {
Button addDevice, showDevice, showDialog;
String[] arrContentTxt;
final Context ctx = this;
int notifCount;
int x = 0;
Handler notifLauncher, notifStopper;
String contentTxt;
Resources res = getResources();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
addDevice = (Button)findViewById(R.id.btnAddDevice);
showDevice = (Button)findViewById(R.id.btnShowDevice);
showDialog = (Button)findViewById(R.id.btnShowDialog);
arrContentTxt = res.getStringArray(R.array.notifContentText);
//contentTxt = arrContentTxt[1];
showDialog.setOnClickListener(new OnClickListener(){
#Override
public void onClick(View v) {
/*DialogFragment diag = new SwitchCheckChange();
diag.show(getFragmentManager(), "cbo Click");*/
showNotif();
}
});
useNotifLauncher();
useNotifStopper();
}
public void useNotifLauncher(){
notifLauncher = new Handler();
notifLauncher.postDelayed(runNotif, 50000);
}
public Runnable runNotif = new Runnable(){
#Override
public void run() {
showNotif();
notifLauncher.postDelayed(runNotif, 50000);
}
};
public void useNotifStopper(){
notifStopper = new Handler();
notifStopper.postDelayed(stopNotif, 40000);
}
public Runnable stopNotif = new Runnable(){
#Override
public void run() {
cancelNotification(x);
notifStopper.postDelayed(stopNotif, 40000);
}
};
public void addClick(View v){
Intent i = new Intent(this, AddDeviceForm.class);
startActivity(i);
}
public void showClick(View v){
Toast.makeText(getBaseContext(), "Please wait...", Toast.LENGTH_LONG).show();
Intent i = new Intent(this, ListViewForm.class);
startActivity(i);
}
public void showNotif(){
Uri notifSound = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
Intent i = new Intent(MainActivity.this, NotifReceiver.class);
PendingIntent pi = PendingIntent.getActivity(MainActivity.this, 0, i, 0);
//String[] notifTitle = R.array.notifTitle;
Notification notif = new Notification.Builder(this)
.setContentTitle("MyPower Reminder")
.setContentText("Unplug unused appliances and chargers")
//.setContentText(contentTxt)
.setSmallIcon(R.drawable.ic_launcher)
.setContentIntent(pi)
.setSound(notifSound)
.addAction(0, "View Full Reminder", pi)
.build();
NotificationManager notifMgr = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
notifMgr.notify(0, notif);
}
public void cancelNotification(int notificationId){
if (Context.NOTIFICATION_SERVICE!=null) {
String ns = Context.NOTIFICATION_SERVICE;
NotificationManager nMgr = (NotificationManager) getApplicationContext().getSystemService(ns);
nMgr.cancel(notificationId);
}
}
}
here's my androidmanifest
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.mypower_build101"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="16"
android:targetSdkVersion="17" />
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity
android:name=".MainActivity"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".AddDeviceForm"
android:label="#string/title_activity_add_device_form" >
</activity>
<activity
android:name=".ListViewForm"
android:label="#string/title_activity_list_view_form" >
</activity>
<activity
android:name=".NotifReceiver"
android:label="#string/title_activity_notif_receiver" >
</activity>
</application>
</manifest>
I'm not putting everything here because it would be to lengthy and I think the problems might be at the MainActivity or the android manifest.
If you could teach me how use the gcm thing that would be very, very, much appreciated.
Hi guys for some reason my post have an error so please use and look at this document. here's the document link
https://www.dropbox.com/s/tc2j2a2pan53r96/Ricky%20Manalo%20LogCat%20Log.docx?dl=0