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

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

Related

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

Android-Image-Cropper Permission READ/WRITE_EXTERNAL_STORAGE issue

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

Logging Of 400 Error Mssage

In Production Environment,When I make Request for my web page.The Request show in apache's access logs,but not in configured my configured web logs.
My logback.xml is
<configuration>
<include resource="org/springframework/boot/logging/logback/base.xml" />
<jmxConfigurator />
<property name="CONSOLE_LOG_PATTERN"
value="%d{yyyy-MM-dd HH:mm:ss.SSS} %5p ${PID:- } --- [%15.15t{14}] %-40.40logger{0} : %m%n" />
<appender name="FILE" class="ch.qos.logback.core.FileAppender">
<file>/var/log/company_name/payments.log</file>
<encoder>
<pattern>${CONSOLE_LOG_PATTERN}</pattern>
</encoder>
</appender>
<appender name="stdout" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>${CONSOLE_LOG_PATTERN}</pattern>
</encoder>
</appender>
<root level="INFO">
<appender-ref ref="FILE" />
</root>
And My controller is
#CrossOrigin
#RestController
#RequestMapping("/my/v1")
public class PaymentApi {
#RequestMapping(value = RestURIConstants.VOID_TRANSACTION,
method = RequestMethod.POST )
public #ResponseBody ResponseEntity<?> voidPayment(#RequestParam("request") String voidRequestJson,
HttpServletRequest httpServletRequest) {
//Code here.
}
#ExceptionHandler
void handleException(Exception e, HttpServletResponse response) throws IOException {
logger.error("Error in Request : " + new ObjectMapper().writeValueAsString(e));
if (e instanceof IllegalArgumentException) {
response.sendError(HttpStatus.BAD_REQUEST.value(), e.getMessage());
return;
}
response.sendError(HttpStatus.INTERNAL_SERVER_ERROR.value(), "an error occured while processing request");
}
}
I am making web Request using below code.
public static <T extends Response,S extends Request> T doPostRequest(S request,
Class<T> responseClass,
String urlString) throws ClientProtocolException, IOException{
RestTemplate restTemplate = new RestTemplate();
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
logger.info("Sending Request " + objectMapper.writeValueAsString(request));
HttpEntity<String> entity = new HttpEntity<String>("request=" + objectMapper.writeValueAsString(request), headers);
ResponseEntity<String> response = null ;
response = restTemplate.exchange(urlString, HttpMethod.POST, entity, String.class);
logger.info("Response recieved " + response.toString());
if (response.getStatusCode() == HttpStatus.OK ||
response.getStatusCode() == HttpStatus.INTERNAL_SERVER_ERROR) {
return objectMapper.readValue(response.getBody(), responseClass) ;
// gson.fromJson(response.getBody(), responseClass) ;
}else{
return objectMapper.readValue(response.getBody(), responseClass) ;
}
}
Same code is working for my local ,But in production it throws 400 Error and also there are no logs in payments.log file.
The Java version in production on my payment server is on 1.8.0_25 and server which is making these request are on 1.8.0_91.
I am unable to identify the reasons as there are no logs are present for this web request in payments.log
their is limit on header size on production.Because of that i am getting this issue and there are no logs in payments.log.

Mixing MVC and Web API Error Handling

We have an MVC 4 web application where we use the web.config file to handle custom errors.
<system.webServer>
<validation validateIntegratedModeConfiguration="false" />
<httpErrors errorMode="Custom" existingResponse="Replace">
<remove statusCode="403" />
<error statusCode="403" responseMode="ExecuteURL" path="/Error/AccessDenied" />
<remove statusCode="404" />
<error statusCode="404" responseMode="ExecuteURL" path="/Error/NotFound" />
<remove statusCode="500" />
<error statusCode="500" responseMode="ExecuteURL" path="/Error/ApplicationError" />
</httpErrors>
</system.webServer>
All ,of which works as expected.
We are now beginning to implement some new features in this project using AngularJS and Web API. In our Web API controller actions, we are consistently returning a HttpResponseMessage to indicate success/failure of the call. For example:
return Request.CreateResponse(HttpStatusCode.BadRequest, result);
The problem (I think!) we are having is that originally MVC error handling is intercepting the BadRequest result (as is reasonable) so that the HttpResponseMessage result data never gets returned to the calling AngularJS method.
What is the best way to handle errors in this mixed (MVC/Web API) environment so that the Web API HttpResponseMessages are not lost?
Thanks.
I am not sure I have found the best solution, but in the end I removed the httpErrors section from the Web.config and built my own error handler in the Global.asax assisted by the following posts:
StackOverflow
PrideParrot
Global.asax
public void Application_Error(Object sender, EventArgs e)
{
var httpContext = ((MvcApplication) sender).Context;
var currentController = "";
var currentAction = "";
var currentRouteData =
RouteTable.Routes.GetRouteData(new HttpContextWrapper(httpContext));
if (currentRouteData != null)
{
if (
!String.IsNullOrEmpty(
currentRouteData.Values["controller"]?.ToString()))
{
currentController = currentRouteData.Values["controller"].ToString();
}
if (!String.IsNullOrEmpty(currentRouteData.Values["action"]?.ToString()))
{
currentAction = currentRouteData.Values["action"].ToString();
}
}
var ex = Server.GetLastError();
var httpEx = ex as HttpException;
var controller = new ErrorController();
var routeData = new RouteData();
var statusCode = httpEx?.GetHttpCode() ?? 500;
string action;
switch (statusCode)
{
case 400:
action = "BadRequest";
break;
case 403:
action = "AccessDenied";
break;
case 404:
action = "NotFound";
break;
default:
action = "Index";
break;
}
httpContext.ClearError();
httpContext.Response.Clear();
httpContext.Response.StatusCode = statusCode;
httpContext.Response.TrySkipIisCustomErrors = true;
if (statusCode >= 500)
{
Server.Transfer("/Error/ServerError.html");
return;
}
routeData.Values["controller"] = "Error";
routeData.Values["action"] = action;
routeData.Values["statusCode"] = statusCode;
controller.ViewData.Model = new HandleErrorInfo(ex, currentController,
currentAction);
((IController) controller).Execute(
new RequestContext(new HttpContextWrapper(httpContext), routeData));
}
My error controller then looked like this:
[AllowAnonymous]
public sealed class ErrorController
: AblController
{
public ActionResult Index(int statusCode)
{
ViewBag.StatusCode = statusCode;
return View("Error");
}
// HTTP 400 - Bad Request
public ActionResult BadRequest()
{
// Now handled by Global.asax - Application_Error
// Response.StatusCode = (int) HttpStatusCode.BadRequest;
// Response.TrySkipIisCustomErrors = true;
if (Request.IsAjaxRequest())
{
return Json(
new
{
error = new ErrorSummary("Bad Request")
});
}
return View();
}
// HTTP 403 - Access Denied
public ActionResult AccessDenied()
{
// Now handled by Global.asax - Application_Error
// Response.StatusCode = (int) HttpStatusCode.Forbidden;
// Response.TrySkipIisCustomErrors = true;
if (Request.IsAjaxRequest())
{
return Json(
new
{
error = new ErrorSummary("Access Denied")
});
}
return View();
}
// HTTP 404 - Not Found
public ActionResult NotFound()
{
// Now handled by Global.asax - Application_Error
// Response.StatusCode = (int) HttpStatusCode.NotFound;
// Response.TrySkipIisCustomErrors = true;
if (Request.IsAjaxRequest())
{
return Json(
new
{
error = new ErrorSummary("Not Found")
});
}
return View();
}
}
}
I also turned the custom error mode off in the Web.config
<customErrors mode="Off" />
This solution needs more testing, but so far it seems to be performing as expected/as required.

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}