Android-Image-Cropper Permission READ/WRITE_EXTERNAL_STORAGE issue - android-imageview

I'm using the library Android-Image-Cropper (which is great!) and there's something I can't quite understand.
I'm using the library for profile picture add/update using camera of from local filesystem (i.e. gallery, file manager).
Although not adding any storage uses-permission to my manifest I'm still able to capture a picture or pick one from the filesystem.
Is it something to do with me not saving the picture and extracting it from the URI directly to my SharedPreferences?
Permission part of Manifest file:
<uses-feature
android:name="android.hardware.bluetooth_le"
android:required="true" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.RECEIVE_SMS" />
<uses-permission android:name="android.permission.READ_SMS" />
<uses-permission android:name="android.permission.SEND_SMS" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.READ_CONTACTS" />
<uses-feature
android:name="android.hardware.camera"
android:required="true" />
An example of use in a Fragment:
#Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.userImage:
CropImage.activity()
.setGuidelines(CropImageView.Guidelines.ON)
.setCropShape(CropImageView.CropShape.OVAL)
.setFixAspectRatio(true)
.setMinCropWindowSize(150,150)
.setScaleType(CropImageView.ScaleType.CENTER)
.start(mActivity, this);
break;
}
}
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
Log.d("AddNewUserFragment", "[onActivityResult]");
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == CropImage.CROP_IMAGE_ACTIVITY_REQUEST_CODE)
{
CropImage.ActivityResult result = CropImage.getActivityResult(data);
if (resultCode == RESULT_OK) {
Uri resultUri = result.getUri();
try {
newProfilePic = mPalPhotoManager.getThumbnail(resultUri);
String encodeUserImage = mPalPhotoManager.encodeImage(newProfilePic);
mPalPhotoManager.saveImageToPreferences(encodeUserImage);
mPalPhotoManager.setUserImage(newProfilePic, mUserImage);
saveImageToServer = true;
} catch (IOException e) {
e.printStackTrace();
}
} else if (resultCode == CropImage.CROP_IMAGE_ACTIVITY_RESULT_ERROR_CODE) {
result.getError().printStackTrace();
saveImageToServer = false;
}
}
}

If anyone encounters this question, there is a thread regarding this exact issue in Libraries' closed issues
here

Related

Apache TomEE external ActiveMQ resource not rolling back in distributed transaction

I am trying to achieve a distributed transaction in Apache TomEE. In words, the flow is:
A message reader (i.e. a message driven bean) reads from a queue (1) and processes one message triggering:
one or more inserts/updates on a database (2)
sending a message to another queue (3)
Operations 1, 2, & 3 are all part of the same XA transaction controlled by TomEE. Therefore, under any circumstances they either all fail or all succeed.
tomee.xml
<?xml version="1.0" encoding="UTF-8"?>
<tomee>
this resource adapter is just necessary to tell tomee to not start internal ActiveMq instance
<Resource id="MyAdapter" type="ActiveMQResourceAdapter">
BrokerXmlConfig
ServerUrl tcp://fakehost:666
</Resource>
<Resource id="jms/MyIncomingConnFactory" type="javax.jms.ConnectionFactory" class-name="org.apache.activemq.ActiveMQXAConnectionFactory">
BrokerURL tcp://externalhost:61616?jms.redeliveryPolicy.maximumRedeliveries=0
</Resource>
<Resource id="jms/MyOutgoingConnFactory" type="javax.jms.ConnectionFactory" class-name="org.apache.activemq.ActiveMQXAConnectionFactory">
BrokerURL tcp://externalhost:61616?jms.redeliveryPolicy.maximumRedeliveries=0
</Resource>
<Resource id="jms/MyOutgoingQueue" class-name="org.apache.activemq.command.ActiveMQQueue">
PhysicalName MY_OUTGOING_QUEUE
</Resource>
<Resource id="jms/MyIncomingQueue" class-name="org.apache.activemq.command.ActiveMQQueue">
PhysicalName MY_INCOMING_QUEUE
</Resource>
<Resource id="jdbc/myDBXAPooled" type="DataSource">
XaDataSource myDBXA
DataSourceCreator dbcp
JtaManaged true
UserName TestUser
Password TestPassword
MaxWait 2000
ValidationQuery SELECT 1
MaxActive 15
</Resource>
<Resource id="myDBXA" type="XADataSource" class-name="com.mysql.jdbc.jdbc2.optional.MysqlXADataSource">
Url jdbc:mysql://localhost:3306/test
User TestUser
Password TestPassword
</Resource>
</tomee>
Springconfig.xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jee="http://www.springframework.org/schema/jee"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.2.xsd
http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-4.2.xsd">
<!-- <jee:jndi-lookup jndi-name="myDBXAPooled" id="myDatasource" resource-ref="true" /> -->
<jee:jndi-lookup jndi-name="jms/MyOutgoingConnFactory" id="myOutgoingConnFactory" resource-ref="true" />
<jee:jndi-lookup jndi-name="jms/MyIncomingConnFactory" id="myIncomingConnFactory" resource-ref="true" />
<jee:jndi-lookup jndi-name="jms/MyOutgoingQueue" id="myOutgoingQueue" resource-ref="true" />
<jee:jndi-lookup jndi-name="jms/MyIncomingQueue" id="myIncomingQueue" resource-ref="true" />
<jee:jndi-lookup jndi-name="jdbc/myDBXAPooled" id="myDatasource" resource-ref="true" />
<tx:jta-transaction-manager/>
<!-- <bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager"/> -->
<!-- the previous two ways of getting the transactionManager seems equivalent and both get Geronimo -->
</beans>
SpringConfig.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jee="http://www.springframework.org/schema/jee"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.2.xsd
http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-4.2.xsd">
<bean id="messageListener" class="com.test.MyListener">
<property name="connectionFactory" ref="myIncomingConnFactory" />
<property name="destination" ref="myIncomingQueue" />
<!-- <property name="sessionTransacted" value="true" /> -->
<property name="concurrentConsumers" value="1" />
<property name="maxConcurrentConsumers" value="6" />
<property name="messageListener" ref="myMessageProcessor" />
<property name="transactionManager" ref="transactionManager" />
<property name="taskExecutor" ref="msgListenersTaskExecutor" />
</bean>
<bean id="myMessageProcessor" class="com.test.MyMessageReceiver">
<property name="forwardConnectionFactory" ref="myOutgoingConnFactory" />
<property name="forwardQueue" ref="myOutgoingQueue" />
<property name="datasource" ref="myDatasource" />
</bean>
<bean id="msgListenersTaskExecutor" class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor"/>
</beans>
MyMessageReceiver.java:
package com.test;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import javax.jms.ConnectionFactory;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.MessageProducer;
import javax.jms.Queue;
import javax.jms.Session;
import javax.jms.TextMessage;
import javax.sql.DataSource;
import org.apache.log4j.Logger;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
public class MyMessageReceiver implements MessageListener {
static Logger log = Logger.getLogger(MyMessageReceiver.class);
private ConnectionFactory forwardConnectionFactory;
private Queue forwardQueue;
private DataSource datasource;
public void setForwardConnectionFactory(ConnectionFactory connFactory) {
forwardConnectionFactory=connFactory;
}
public void setforwardQueue(Queue queue) {
forwardQueue=queue;
}
public void setDatasource(DataSource ds) {
datasource=ds;
}
#Override
#Transactional(propagation=Propagation.REQUIRED)
public void onMessage(Message message) {
log.info("************************************");
MyListener listener = (MyListener)SpringContext.getBean("messageListener");
listener.printInfo();
log.info("************************************");
TextMessage msg = (TextMessage) message;
String text = null;
try {
text = msg.getText();
if (text != null) log.info("MESSAGE RECEIVED: "+ text);
updateDB(text); // function call to update DB
sendMsg(text); // function call to publish messages to queue
System.out.println("****************Rollback");
// Throwing exception to rollback DB, Message should not be
// published and consumed message sent to a DLQ
//(Broker side DLQ configuration already done)
throw new RuntimeException();
//if (text!=null && text.indexOf("rollback")!=-1) throw new RuntimeException("Message content includes the word rollback");
} catch (Exception e) {
log.error("Rolling back the entire XA transaction");
log.error(e.getMessage());
throw new RuntimeException("Rolled back because of "+e.getMessage());
}
}
private void updateDB(String text) throws Exception {
Connection conn = null;
PreparedStatement ps = null;
try {
System.out.println("*******datasource "+datasource);
conn = datasource.getConnection();
System.out.println("*******conn "+conn.getMetaData().getUserName());
if (conn!=null) {
System.out.println("*******conn "+conn.getMetaData().getUserName());
ps = conn.prepareStatement("INSERT INTO MY_TABLE (name) VALUES(?)");
ps.setString(1, text);
ps.executeUpdate();
}
} catch (Exception e) {
throw e;
} finally {
if (ps!=null) {
try {
ps.close();
} catch (SQLException e) {
log.error(e.getMessage());
// do nothing
}
}
if (conn!=null) {
try {
conn.close();
} catch (SQLException e) {
log.error(e.getMessage());
// do nothing
}
}
}
}
private void sendMsg(String msgToBeSent) throws Exception {
javax.jms.Connection conn = null;
Session session = null;
try {
System.out.println("*************forwardConnectionFactory"+forwardConnectionFactory);
conn = forwardConnectionFactory.createConnection();
session = conn.createSession(true, Session.AUTO_ACKNOWLEDGE);
MessageProducer messageProducer = session.createProducer(forwardQueue);
TextMessage msg = session.createTextMessage(msgToBeSent);
messageProducer.send(msg);
} catch (Exception e) {
throw e;
} finally {
if (session != null) {
try {
session.close();
} catch (JMSException e) {
// do nothing
}
}
if (conn != null) {
try {
conn.close();
} catch (JMSException e) {
// do nothing
}
}
}
}
}
MyListener.java:
package com.test;
import javax.transaction.Status;
import javax.transaction.SystemException;
import org.apache.log4j.Logger;
import org.springframework.jms.listener.DefaultMessageListenerContainer;
import org.springframework.transaction.jta.JtaTransactionManager;
public class MyListener extends DefaultMessageListenerContainer {
static Logger log = Logger.getLogger(MyListener.class);
public void printInfo() {
try {
log.info("trans manager="+((JtaTransactionManager)this.getTransactionManager()).getTransactionManager()+","+((JtaTransactionManager)this.getTransactionManager()).getTransactionManager().getStatus()+", this.isSessionTransacted()="+this.isSessionTransacted());
log.info("STATUS_ACTIVE="+Status.STATUS_ACTIVE);
log.info("STATUS_COMMITTEDE="+Status.STATUS_COMMITTED);
log.info("STATUS_COMMITTING="+Status.STATUS_COMMITTING);
log.info("STATUS_MARKED_ROLLBACK="+Status.STATUS_MARKED_ROLLBACK);
log.info("STATUS_NO_TRANSACTION="+Status.STATUS_NO_TRANSACTION);
log.info("STATUS_PREPARED="+Status.STATUS_PREPARED);
log.info("STATUS_PREPARING="+Status.STATUS_PREPARING);
log.info("STATUS_ROLLEDBACK="+Status.STATUS_ROLLEDBACK);
log.info("STATUS_ROLLING_BACK="+Status.STATUS_ROLLING_BACK);
log.info("STATUS_UNKNOWN="+Status.STATUS_UNKNOWN);
} catch (SystemException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void forceRollback() {
try {
((JtaTransactionManager)this.getTransactionManager()).getTransactionManager().setRollbackOnly();
} catch (IllegalStateException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SystemException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
After updating the database and sending the message to the outgoing queue I am purposefully throwing a RuntimeException just to test the transaction rollback of both the database and the message broker.
All three operations are committed in case of success, but it only rolls back the database operation in case of failure, while the two JMS operations are committed anyway.
It could either be:
wrong settings in my tomee.xml (especially queue connection factories) or somewhere else
a bug??
I already spent quite much time fighting with the thing and searching for possible solutions.
It would be great to hear your opinion on this and, once again, advanced apologies if it turns out to be a mistake on my side.
I believe you need to use the ActiveMQ JCA resource adapter to ensure that connections are automatically enlisted into the XA transaction. Try this:
<tomee>
<Resource id="MyJmsResourceAdapter" type="ActiveMQResourceAdapter">
# Do not start the embedded ActiveMQ broker
BrokerXmlConfig =
ServerUrl = tcp://externalhost:61616?jms.redeliveryPolicy.maximumRedeliveries=0
</Resource>
<Resource id="jms/MyIncomingConnFactory" type="javax.jms.ConnectionFactory">
resourceAdapter = MyJmsResourceAdapter
transactionSupport = xa
</Resource>
<Resource id="jms/MyOutgoingConnFactory" type="javax.jms.ConnectionFactory">
resourceAdapter = MyJmsResourceAdapter
transactionSupport = xa
</Resource>
<Resource id="jms/MyOutgoingQueue" type="javax.jms.Queue"/>
<Resource id="jms/MyIncomingQueue" type="javax.jms.Queue"/>
<Resource id="jdbc/myDBXAPooled" type="DataSource">
XaDataSource myDBXA
DataSourceCreator dbcp
JtaManaged true
UserName TestUser
Password TestPassword
MaxWait 2000
ValidationQuery SELECT 1
MaxActive 15
</Resource>
<Resource id="myDBXA" type="XADataSource" class-name="com.mysql.jdbc.jdbc2.optional.MysqlXADataSource">
Url jdbc:mysql://localhost:3306/test
User TestUser
Password TestPassword
</Resource>
</tomee>

place picker closes immediately

my PlacePicker is closing when I open it, it stays open for about 3 seconds, I can see the location and I can move it, but it closes, I already tried everything already activated the api in google console, I changed the key, it does not give any error in logcat and neither in the RUN tab help me!
MY ANDROID MANIFEST
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<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">
<meta-data
android:name="com.google.android.geo.API_KEY"
android:value="AIzaSyCD70mX9tljEfiDiLaCdHEUNMvq40AJDyI"/>
<meta-data
android:name="com.google.android.gms.version"
android:value="#integer/google_play_services_version" />
<activity android:name=".activity.TelefoneActivity" />
<activity android:name=".activity.CadastrarActivity" />
<activity android:name=".activity.MainActivity" />
<activity android:name=".activity.PassageiroActivity" />
<uses-library android:name="org.apache.http.legacy" android:required="false"/>
<meta-data
android:name="com.facebook.sdk.App.Application"
android:value="#string/facebook_app_id" />
<!-- Facebook API Key -->
<meta-data
tools:replace="android:value"
android:name="com.facebook.sdk.ApplicationId"
android:value="#string/facebook_app_id" />
<activity
android:name="com.facebook.CustomTabActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="#string/fb_login_protocol_scheme" />
</intent-filter>
</activity>
<!--
The API key for Google Maps-based APIs is defined as a string resource.
(See the file "res/values/google_maps_api.xml").
Note that the API key is linked to the encryption key used to sign the APK.
You need a different API key for each encryption key, including the release key that is used to
sign the APK for publishing.
You can define the keys for the debug and release targets in src/debug/ and src/release/.
-->
<activity
android:name=".activity.SplashActivity"
android:theme="#style/AppCompat.TelaCheia">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
ACTIVITY WHERE PLACE PICKER IS IMPLEMENTED
import static android.Manifest.permission.ACCESS_FINE_LOCATION;
public class PassageiroActivity extends FragmentActivity implements OnMapReadyCallback, GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener {
int PLACE_PICKER_REQUEST = 1;
private String placeId;
TextView btnChamarMoto;
/**
* Mapa da aplicação
*/
private GoogleMap mMap;
/**
* Responsável por disponibilizar a localização do smartphone
*/
private GoogleApiClient mGoogleApiClient;
/**
* Guarda a ultima posição do smartphone.
*/
private Location mLastLocation;
private TextInputEditText editMeuLocal;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_passageiro);
SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map);
mapFragment.getMapAsync(this);
iniciaComponentes();
placesApi();
btnChamarMoto = (TextView) findViewById(R.id.btnChamarMoto);
if (mGoogleApiClient == null) {
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this) // Interface ConnectionCallbacks
.addOnConnectionFailedListener(this) //Interface OnConnectionFailedListener
.addApi(LocationServices.API) // Vamos a API do LocationServices
.build();
}
}
public void placePiker(View view) {
PlacePicker.IntentBuilder builder = new PlacePicker.IntentBuilder();
try {
try {
startActivityForResult(builder.build(PassageiroActivity.this), PLACE_PICKER_REQUEST);
} catch (GooglePlayServicesNotAvailableException e) {
e.printStackTrace();
}
} catch (GooglePlayServicesRepairableException e) {
e.printStackTrace();
}
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == PLACE_PICKER_REQUEST) {
if (resultCode == RESULT_OK) {
Place place = (Place) PlacePicker.getPlace(PassageiroActivity.this, data);
btnChamarMoto.setText(place.getAddress());
}
}
}
protected void onStart() {
mGoogleApiClient.connect();
super.onStart();
}
protected void onStop() {
mGoogleApiClient.disconnect();
super.onStop();
}
#Override
public void onMapReady(GoogleMap googleMap) {
mMap = googleMap;
}
#Override
public void onConnected(Bundle bundle) {
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
return;
}
mLastLocation = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
if (mLastLocation != null) {
if (mMap != null) {
// Criamos o LatLng através do Location
final LatLng latLng = new LatLng(mLastLocation.getLatitude(), mLastLocation.getLongitude());
// Adicionamos um Marker com a posição...
mMap.addMarker(new MarkerOptions().position(latLng).title("Minha Posição"));
// Um zoom no mapa para a seua posição atual...
mMap.animateCamera(CameraUpdateFactory.newLatLngZoom(latLng, 18));
}
}
}
#Override
public void onConnectionSuspended(int i) {
}
#Override
public void onConnectionFailed(ConnectionResult connectionResult) {
}
//Place Api
private void placesApi() {
Places.initialize(getApplicationContext(), "AIzaSyDxFTRAaJ-FecUs8SZj6MBYwwzD447Nces");
final PlacesClient placesClient = Places.createClient(this);
AutocompleteSupportFragment autocompleteFragment = (AutocompleteSupportFragment)
getSupportFragmentManager().findFragmentById(R.id.autocomplete_fragment);
autocompleteFragment.setPlaceFields(Arrays.asList(Place.Field.ID, Place.Field.NAME));
autocompleteFragment.setOnPlaceSelectedListener(new PlaceSelectionListener() {
#Override
public void onPlaceSelected(Place place) {
//
// Double latitude = place.getLatLng().latitude;
Log.i("Places", "Place: " + place.getName() + ", " + place.getId());
placeId = place.getId();
}
#Override
public void onError(Status status) {
// TODO: Handle the error.
Log.i("errorOccurred", "An error occurred: " + status);
}
});
}
private void meuLocal(PlacesClient placesClient) {
List < Place.Field > placeFields = Arrays.asList(Place.Field.NAME);
FindCurrentPlaceRequest request =
FindCurrentPlaceRequest.builder(placeFields).build();
if (ContextCompat.checkSelfPermission(this, ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
Task < FindCurrentPlaceResponse > placeResponse = placesClient.findCurrentPlace(request);
placeResponse.addOnCompleteListener(task - > {
if (task.isSuccessful()) {
FindCurrentPlaceResponse response = task.getResult();
for (PlaceLikelihood placeLikelihood: response.getPlaceLikelihoods()) {
Log.i("likelihood", String.format("Place '%s' has likelihood: %f",
placeLikelihood.getPlace().getName(),
placeLikelihood.getLikelihood()));
LatLng nome = placeLikelihood.getPlace().getLatLng();
double latitude = nome.latitude;
double longitude = nome.longitude;
Toast.makeText(this, "latitude: " + latitude + "longitude: " + longitude, Toast.LENGTH_SHORT).show();
}
} else {
Exception exception = task.getException();
if (exception instanceof ApiException) {
ApiException apiException = (ApiException) exception;
Log.e("notFound", "Place not found: " + apiException.getStatusCode());
}
}
});
} else {
}
}
private void verificaIdPlaces(PlacesClient placesClient) {
List < Place.Field > placeFields = Arrays.asList(Place.Field.ID, Place.Field.NAME);
FetchPlaceRequest request = FetchPlaceRequest.builder(placeId, placeFields).build();
String nome = request.getPlaceId();
placesClient.fetchPlace(request).addOnSuccessListener((response) - > {
Place place = response.getPlace();
Log.i("PlaceFOund", "Place found: " + place.getName() + "," + place.getLatLng());
}).addOnFailureListener((exception) - > {
if (exception instanceof ApiException) {
ApiException apiException = (ApiException) exception;
int statusCode = apiException.getStatusCode();
// Handle error with given status code.
Log.e("Place not found", "Place not found: " + exception.getMessage());
}
});
}
private void iniciaComponentes() {
btnChamarMoto = findViewById(R.id.btnChamarMoto);
}
Please check your api key
Note there is two api key , one for the debug and the other for the release , so make you sure you are using the right one for the right version

No receiver allowed to receive com.google.android.c2dm.permission.SEND at Gcm.Client.GcmClient.CheckManifest - Xamarin.Forms

I am using GCM to receive push notification in Android. I have below code in Android main activity, which is dependent on Xamarin.Forms project
try
{
//Check to see that GCM is supported and that the manifest has the correct information
GcmClient.CheckDevice(this);
GcmClient.CheckManifest(this);
var registrationId = GcmClient.GetRegistrationId(this);
if (string.IsNullOrEmpty(registrationId))
{
GcmClient.Register(this, GcmBroadcastReceiver.SENDER_IDS);
}
}
catch (Exception e)
{
}
While executing check manifest its throwing below exception:
No receiver allowed to receive com.google.android.c2dm.permission.SEND
at Gcm.Client.GcmClient.CheckManifest
But I have added necessary permission in manifest, below is my manifest:
<uses-sdk android:targetSdkVersion="21" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<permission android:name="com.package.name.permission.C2D_MESSAGE" android:protectionLevel="signature" />
<uses-permission android:name="com.package.name.permission.C2D_MESSAGE" />
<uses-permission android:name="com.google.android.providers.gsf.permission.READ_GSERVICES" />
<application android:label="Mobile.Droid" android:icon="#drawable/icon" android:theme="#android:style/Theme.Holo.Light"></application>
I am having same manifest file in one of my Xamarin.Android project, where its successfully registered with GCM, why here its throwing exception?
What am I missing?
I think that the error is because you don't set the permission of:
com.google.android.c2dm.permission.SEND
Try to set the permissions in your custom BroadcastReceiver class like this:
[BroadcastReceiver(Permission = "com.google.android.c2dm.permission.SEND")]
[IntentFilter(new string[] { "com.google.android.c2dm.intent.RECEIVE" }, Categories = new string[] { "#PACKAGE_NAME#" })]
[IntentFilter(new string[] { "com.google.android.c2dm.intent.REGISTRATION" }, Categories = new string[] { "#PACKAGE_NAME#" })]
[IntentFilter(new string[] { "com.google.android.gcm.intent.RETRY" }, Categories = new string[] { "#PACKAGE_NAME#" })]
public class MyGCMBroadcastReceiver : BroadcastReceiver
{
const string TAG = "PushHandlerBroadcastReceiver";
public override void OnReceive(Context context, Intent intent)
{
MyIntentService.RunIntentInService(context, intent);
SetResult(Result.Ok, null, null);
}
}
I hope it helps

Not able to receive GCM message in my device, even though the server got success message

I got success message as response to web server (localhost) from gcm. But the message is not received by the devices. Please help. Below is the code which I used.
Main Activity
package vitpat.placement;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GooglePlayServicesUtil;
import com.google.android.gms.gcm.GoogleCloudMessaging;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.StrictMode;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager.NameNotFoundException;
import android.util.Log;
import android.view.Menu;
import android.view.View;
import android.widget.ProgressBar;
import android.widget.TextView;
public class MainActivity extends Activity {
private final static int PLAY_SERVICES_RESOLUTION_REQUEST = 9000;
public static final String EXTRA_MESSAGE = "message";
public static final String PROPERTY_REG_ID = "registration_id";
private static final String PROPERTY_APP_VERSION = "appVersion";
TextView textUnderProgressBar;
String SENDER_ID = "794097343372";
final String TAG = "GCMDemo";
TextView mDisplay;
GoogleCloudMessaging gcm;
AtomicInteger msgId = new AtomicInteger();
SharedPreferences prefs;
Context context;
String regid;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (android.os.Build.VERSION.SDK_INT > 9) {
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
}
textUnderProgressBar = (TextView) findViewById(R.id.textView1);
context = getApplicationContext();
//shared preference to check if the application is being run for the first time and the user is yet to be verified
SharedPreferences prefToVerifyUser = getApplicationContext().getSharedPreferences("MyPref", 0); // 0 - for private mode
Boolean isUserVerified = prefToVerifyUser.getBoolean("UserVerified", false);
Log.e("main activity", isUserVerified.toString());
if(isUserVerified == false) {
Intent intent = new Intent(this,Check_User_Authentication.class);
startActivityForResult(intent, 0);
}
else {
//end of shared preference check
ProgressBar progress = (ProgressBar) findViewById(R.id.progressBar1);
progress.setIndeterminate(true);
progress.setVisibility(View.VISIBLE);
// Check device for Play Services APK.
if(CheckForPlayStoreApp()) {
//code
textUnderProgressBar.setText("Contacting Server..");
gcm = GoogleCloudMessaging.getInstance(this);
regid = getRegistrationId(context);
if (regid.isEmpty()) {
registerInBackground();
}
else {
textUnderProgressBar.setText(regid.toString());
/*GcmBroadcastReceiver gcr;
GcmBroadcastReceiver.startWakefulService(getApplicationContext(), getIntent());*/
}
} else {
Log.i(TAG, "No valid Google Play Services APK found.");
}
}
}
/**
* Check the device to make sure it has the Google Play Services APK. If
* it doesn't, display a dialog that allows users to download the APK from
* the Google Play Store or enable it in the device's system settings.
*/
private boolean CheckForPlayStoreApp() {
int resultCode = GooglePlayServicesUtil.isGooglePlayServicesAvailable(this);
if (resultCode != ConnectionResult.SUCCESS) {
if (GooglePlayServicesUtil.isUserRecoverableError(resultCode)) {
GooglePlayServicesUtil.getErrorDialog(resultCode, this,
PLAY_SERVICES_RESOLUTION_REQUEST).show();
} else {
Log.i("CheckForPlayStoreApp", "This device is not supported.");
finish();
}
return true;
}
return true;
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
// You need to do the Play Services APK check here too.
#Override
protected void onResume() {
super.onResume();
CheckForPlayStoreApp();
}
/**
* Gets the current registration ID for application on GCM service.
* <p>
* If result is empty, the app needs to register.
*
* #return registration ID, or empty string if there is no existing
* registration ID.
*/
private String getRegistrationId(Context context) {
final SharedPreferences prefs = getGCMPreferences(context);
String registrationId = prefs.getString(PROPERTY_REG_ID, "");
if (registrationId.isEmpty()) {
Log.i(TAG, "Registration not found.");
return "";
}
// Check if app was updated; if so, it must clear the registration ID
// since the existing regID is not guaranteed to work with the new
// app version.
int registeredVersion = prefs.getInt(PROPERTY_APP_VERSION, Integer.MIN_VALUE);
int currentVersion = getAppVersion(context);
if (registeredVersion != currentVersion) {
Log.i(TAG, "App version changed.");
return "";
}
return registrationId;
}
/**
* #return Application's {#code SharedPreferences}.
*/
private SharedPreferences getGCMPreferences(Context context) {
// This sample app persists the registration ID in shared preferences, but
// how you store the regID in your app is up to you.
return getSharedPreferences(MainActivity.class.getSimpleName(),
Context.MODE_PRIVATE);
}
/**
* #return Application's version code from the {#code PackageManager}.
*/
private static int getAppVersion(Context context) {
try {
PackageInfo packageInfo = context.getPackageManager()
.getPackageInfo(context.getPackageName(), 0);
return packageInfo.versionCode;
} catch (NameNotFoundException e) {
// should never happen
throw new RuntimeException("Could not get package name: " + e);
}
}
/**
* Registers the application with GCM servers asynchronously.
* <p>
* Stores the registration ID and app versionCode in the application's
* shared preferences.
*/
private void registerInBackground() {
Log.e("inside register", "sample0");
new AsyncTask<Void, Void, Void>() {
#Override
protected Void doInBackground(Void... params) {
Log.e("inside register", "sample1");
String msg = "";
try {
if (gcm == null) {
gcm = GoogleCloudMessaging.getInstance(context);
}
regid = gcm.register(SENDER_ID);
Log.e("inside register", regid);
msg = "Device registered, registration ID=" + regid;
// You should send the registration ID to your server over HTTP,
// so it can use GCM/HTTP or CCS to send messages to your app.
// The request to your server should be authenticated if your app
// is using accounts.
sendRegistrationIdToBackend();
// For this demo: we don't need to send it because the device
// will send upstream messages to a server that echo back the
// message using the 'from' address in the message.
// Persist the regID - no need to register again.
storeRegistrationId(context, regid);
} catch (IOException ex) {
msg = "Error :" + ex.getMessage();
// If there is an error, don't just keep trying to register.
// Require the user to click a button again, or perform
// exponential back-off.
}
return null;
}
}.execute(null, null, null);
}
/**
* Sends the registration ID to your server over HTTP, so it can use GCM/HTTP
* or CCS to send messages to your app. Not needed for this demo since the
* device sends upstream messages to a server that echoes back the message
* using the 'from' address in the message.
*/
private void sendRegistrationIdToBackend() {
// Your implementation here.
String url = "http://192.168.43.112/dist/addregistrationid.php";
SharedPreferences prefUserDetails = getApplicationContext().getSharedPreferences("UserDetails", 0);
String registerNumber = prefUserDetails.getString("registerNumber", null);
List<NameValuePair> params = new ArrayList<NameValuePair>();
params.add(new BasicNameValuePair("regid", regid));
params.add(new BasicNameValuePair("regno", registerNumber));
DefaultHttpClient httpClient = new DefaultHttpClient();
HttpPost httpPost = new HttpPost(url);
try {
httpPost.setEntity(new UrlEncodedFormEntity(params));
}
catch (UnsupportedEncodingException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
try {
HttpResponse httpResponse = httpClient.execute(httpPost);
} catch (ClientProtocolException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/**
* Stores the registration ID and app versionCode in the application's
* {#code SharedPreferences}.
*
* #param context application's context.
* #param regId registration ID
*/
private void storeRegistrationId(Context context, String regId) {
final SharedPreferences prefs = getGCMPreferences(context);
int appVersion = getAppVersion(context);
Log.i(TAG, "Saving regId on app version " + appVersion);
SharedPreferences.Editor editor = prefs.edit();
editor.putString(PROPERTY_REG_ID, regId);
editor.putInt(PROPERTY_APP_VERSION, appVersion);
editor.commit();
}
}
GcmBroadcastReceiver
public class GcmBroadcastReceiver extends WakefulBroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub
ComponentName comp = new ComponentName(context.getPackageName(),GcmIntentService.class.getName());
// Start the service, keeping the device awake while it is launching.
startWakefulService(context, (intent.setComponent(comp)));
setResultCode(Activity.RESULT_OK);
}
}
GcmIntentService
public class GcmIntentService extends IntentService {
Context context;
public static final int NOTIFICATION_ID = 1;
private NotificationManager mNotificationManager;
NotificationCompat.Builder builder;
public static final String TAG = "GCM Demo";
public GcmIntentService() {
super("GcmIntentService");
// TODO Auto-generated constructor stub
}
#Override
protected void onHandleIntent(Intent intent) {
// TODO Auto-generated method stub
Bundle extras = intent.getExtras();
String msg = intent.getStringExtra("message");
GoogleCloudMessaging gcm = GoogleCloudMessaging.getInstance(this);
String messageType = gcm.getMessageType(intent);
if (!extras.isEmpty()) {
if (GoogleCloudMessaging.
MESSAGE_TYPE_SEND_ERROR.equals(messageType)) {
sendNotification("Send error: " + extras.toString());
} else if (GoogleCloudMessaging.
MESSAGE_TYPE_DELETED.equals(messageType)) {
sendNotification("Deleted messages on server: " +
extras.toString());
// If it's a regular GCM message, do some work.
} else if (GoogleCloudMessaging.
MESSAGE_TYPE_MESSAGE.equals(messageType)) {
// This loop represents the service doing some work.
for (int i=0; i<5; i++) {
Log.i(TAG, "Working... " + (i+1)
+ "/5 # " + SystemClock.elapsedRealtime());
try {
Thread.sleep(500);
} catch (InterruptedException e) {
}
}
Log.i(TAG, "Completed work # " + SystemClock.elapsedRealtime());
// Post notification of received message.
//sendNotification("Received: " + extras.toString());
sendNotification(msg);
Log.i(TAG, "Received: " + extras.toString());
}
}
GcmBroadcastReceiver.completeWakefulIntent(intent);
}
private void sendNotification(String msg) {
mNotificationManager = (NotificationManager)
this.getSystemService(Context.NOTIFICATION_SERVICE);
Intent myintent = new Intent(this, ReceiveActivity.class);
myintent.putExtra("message", msg);
PendingIntent contentIntent = PendingIntent.getActivity(this, 0,
myintent, PendingIntent.FLAG_UPDATE_CURRENT);
NotificationCompat.Builder mBuilder =
new NotificationCompat.Builder(this)
// .setSmallIcon(R.drawable.ic_stat_gcm)
.setContentTitle("GCM Notification")
.setStyle(new NotificationCompat.BigTextStyle()
.bigText(msg))
.setContentText(msg);
mBuilder.setContentIntent(contentIntent);
mNotificationManager.notify(NOTIFICATION_ID, mBuilder.build());
}
}
Manifest
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="vitpat.placement"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="11"
android:targetSdkVersion="19" />
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
<permission android:name="vitpat.placement.permission.C2D_MESSAGE"
android:protectionLevel="signature" />
<uses-permission android:name="vitpat.placement.permission.C2D_MESSAGE" />
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity
android:name="vitpat.placement.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="vitpat.placement.Check_User_Authentication"
android:theme="#android:style/Theme.Dialog">
</activity>
<receiver
android:name=".GcmBroadcastReceiver"
android:permission="com.google.android.c2dm.permission.SEND" >
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
<category android:name="vitpat.placement" />
</intent-filter>
</receiver>
<service android:name=".GcmIntentService" />
<meta-data android:name="com.google.android.gms.version"
android:value="#integer/google_play_services_version" />
<activity android:name="vitpat.placement.ReceiveActivity"></activity>
</application>
</manifest>
I found the solution myself. I was using the "android api key" to send the message from my web server (php) to gcm server and that was the problem. Using "browser api" key solved the issue..
Create a new "browser api key" from google console and use it in the php code to send a message from web server to gcm.
If you want to send a message from android device to gcm, try using android key.
Make sure, you create all these keys from the same project under google console.
I had same problem of receiving push messages, even though GCM server replies "Success", because of wifi privacy. When I used my company wifi, I coudn't receive message in mobile, since they were blocked GCM server port . So, even your wifi also could be a one of the reason. check it once { this answer is for others , who may face this}

Notifications and Alarm Manager not working

Hi I've seen many questions about this issue and now here is mine here's my code in onclick, it never seems to work.
if(v.getId() == In){
Intent myIntent = new Intent(HelloAndroidActivity.this , TimeAlarm.class);
AlarmManager alarmManager = (AlarmManager)getSystemService(ALARM_SERVICE);
PendingIntent pi = PendingIntent.getService(HelloAndroidActivity.this, 0, myIntent, 0);
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.HOUR_OF_DAY, 3);
calendar.set(Calendar.MINUTE, 59);
calendar.set(Calendar.SECOND, 00);
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), 24*60*60*1000 , pi);
}
And then here's the other part
public class TimeAlarm extends BroadcastReceiver {
NotificationManager nm;
public void onReceive(Context context, Intent intent) {
nm = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
String from = "Nithin";
String message = "Crazy About Android...";
PendingIntent contentIntent = PendingIntent.getActivity(context, 0, new Intent(), 0);
Notification notif = new Notification(R.drawable.ic_launcher, "Crazy About Android...", System.currentTimeMillis());
notif.setLatestEventInfo(context, from, message, contentIntent);
nm.notify(1, notif);
}
}
Also here's my manifest I hope that I put the receiver in the right place
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.CS340.smokingsurvey"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="10"
android:targetSdkVersion="10" />
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<receiver android:name=".TimeAlarm"></receiver>
<activity
android:name="com.CS340.smokingsurvey.HelloAndroidActivity"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>