How to make condition in android? - android

I have a Broadcast receiver in my app and get a url from server response from server response url I split package name and save in shared preference,now scenario is that when any app is added in device it will check that app package name from my saved package name if match then pass intent. problem is that when variable which I declared earlier was empty then how to match new package added with my saved packge.shows me null pointer exception.
here is code:-
public class CAppDownloadReceiver extends BroadcastReceiver {
String url, packageName, s_szDealCode;
CDealBuySharedPreference m_oSharedPreference;
/**
* Get Query String as Key-Value Pair.
*/
public static Map<String, String> getQueryMap(String query) {
Map<String, String> map = new HashMap<>();
String[] queryString = query.split("\\?");
if (queryString.length > 1) {
String[] params = queryString[1].split("&");
for (String param : params) {
String name = param.split("=")[0];
String value = param.split("=")[1];
map.put(name, value);
}
}
return map;
}
#Override
public void onReceive(Context context, Intent intent) {
m_oSharedPreference = new CDealBuySharedPreference(context);
HashMap<String, String> user = m_oSharedPreference.getDealUrlDetails();
try {
if (intent.getAction().equals("android.intent.action.PACKAGE_ADDED")) {
String installAppPackgeName = intent.getData().getSchemeSpecificPart();
url = user.get(CDealBuySharedPreference.s_szDealUrl);// getting mobile from saved preferences..........
packageName = getQueryMap(url).get("id");
System.out.println("Previous package stored :" + packageName);
System.out.println("new Package added" + installAppPackgeName);
if (installAppPackgeName.equals(packageName)) {
// If install app package name is same as url package name then do some task.
// Your app is installed now.
s_szDealCode = user.get(CDealBuySharedPreference.s_szDealCode);
System.out.println("Match...");
System.out.println("Broadcast url..." + url);
System.out.println("Broadcast deal code:-" + s_szDealCode);
} else {
System.out.println("does not match ");
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}

Related

how to compare package name from market url in android?

I am developing an app which contain broadcast receiver and also contain list of app when user click any particular app he will directed to play store and download that app from jsons response I get all app showing in al list url like "https://play.google.com/store/apps/details?id=com.example.launcher" what I have to do is that when app is successfully downloaded in system I will check that app package name of that app from json response url if match then show a toast else error message.
How can I acheive this pls help me Its for a week I am searching.
here is my code for broadcast receiver:-
public class Receiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals("android.intent.action.PACKAGE_ADDED"))
Log.e("Package Added:-", intent.getData().toString());
}
}
#Override
public void onReceive(Context context, Intent intent) {
String installAppPackgeName = intent.getData().getSchemeSpecificPart();
String url = "https://play.google.com/store/apps/details?id=com.example.launcher";
String packageName = getQueryMap(url).get("id");
if(installAppPackgeName.equals(packageName)){
// If install app package name is same as url package name then do some task.
// Your app is installed now.
}
}
/**
* Get Query String as Key-Value Pair.
*/
public static Map<String, String> getQueryMap(String query) {
Map<String, String> map = new HashMap<>();
String[] queryString = query.split("\\?");
if(queryString.length>1){
String[] params = queryString[1].split("&");
for (String param : params) {
String name = param.split("=")[0];
String value = param.split("=")[1];
map.put(name, value);
}
}
return map;
}
extract package name from URL with
String downPack = yourUrl.split("id\\=")[1];
extract package name from file
public String getPackageNameByAPK(String apkPath, Context context) {
String packName = "";
PackageManager packageManager;
PackageInfo packInfo;
try {
if (apkPath == null) return "";
if (context == null) {
return "";
}
packageManager = context.getPackageManager();
packInfo = packageManager.getPackageArchiveInfo(apkPath, 0);
packName = packInfo.packageName;
} catch (Exception e) {
e.printStackTrace();
}
return packName;
}
compare like
boolean matched = downPack.equals(getPackageNameByAPK(apkPath,context));
This may help you..

AmazonSNS - AwsCredentials.properties - NullPointerException

I am new to Android Studio and intelliJ.
I am trying to work with AmazonSNS - Push. I am unable to figure out how to add AwsCredentials.properties file to classpath of the module. I get a NPE at line 57 in the image below(at method getResourceAsStream()). I added the required keys in AwsCredentials.properties file.
Error:
In the questions that i have come across on StackOverflow regarding similar issues, some suggested that the file should be in the root folder, where, src is. I placed it in the same folder as that of src, but still getting the NPE. I also tried placing the file in com/test/ but with no use.
How do i solve this? Are there any other steps involved?
EDIT after starting a bounty - Adding java files
Here is what i did till now..
Create an Android Application called MyApplication. Imported all classes(AndroidMobilePushApp.java, ExternalReceiver.java, MessageReceivingService.java) from the demo application. Added required libs, and ran it and got the registationId as response from Amazon.
In the same application, i created a new module called snspush and imported SNSMobilePush.java file into it. Also imported the AwsCredentials.properties file to the same path as that of SNSMobilePush.java. Added the keys in AwsCredentials.properties file.
Followed the steps in documentation to uncomment necessary funtions.
Project Structure:
Java files:
AndroidMobilePushApp.java:
public class AndroidMobilePushApp extends AppCompatActivity {
private TextView tView;
private SharedPreferences savedValues;
private String numOfMissedMessages;
// Since this activity is SingleTop, there can only ever be one instance. This variable corresponds to this instance.
public static Boolean inBackground = true;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
numOfMissedMessages = getString(R.string.num_of_missed_messages);
setContentView(R.layout.activity_main);
tView = (TextView) findViewById(R.id.tViewId);
tView.setMovementMethod(new ScrollingMovementMethod());
startService(new Intent(this, MessageReceivingService.class));
}
public void onStop(){
super.onStop();
inBackground = true;
}
public void onRestart(){
super.onRestart();
tView.setText("");;
}
public void onResume(){
super.onResume();
inBackground = false;
savedValues = MessageReceivingService.savedValues;
int numOfMissedMessages = 0;
if(savedValues != null){
numOfMissedMessages = savedValues.getInt(this.numOfMissedMessages, 0);
}
String newMessage = getMessage(numOfMissedMessages);
if(newMessage!=""){
Log.i("displaying message", newMessage);
tView.append(newMessage);
}
}
public void onNewIntent(Intent intent){
super.onNewIntent(intent);
setIntent(intent);
}
// If messages have been missed, check the backlog. Otherwise check the current intent for a new message.
private String getMessage(int numOfMissedMessages) {
String message = "";
String linesOfMessageCount = getString(R.string.lines_of_message_count);
if(numOfMissedMessages > 0){
String plural = numOfMissedMessages > 1 ? "s" : "";
Log.i("onResume","missed " + numOfMissedMessages + " message" + plural);
tView.append("You missed " + numOfMissedMessages +" message" + plural + ". Your most recent was:\n");
for(int i = 0; i < savedValues.getInt(linesOfMessageCount, 0); i++){
String line = savedValues.getString("MessageLine"+i, "");
message+= (line + "\n");
}
NotificationManager mNotification = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
mNotification.cancel(R.string.notification_number);
SharedPreferences.Editor editor=savedValues.edit();
editor.putInt(this.numOfMissedMessages, 0);
editor.putInt(linesOfMessageCount, 0);
editor.commit();
}
else{
Log.i("onResume","no missed messages");
Intent intent = getIntent();
if(intent!=null){
Bundle extras = intent.getExtras();
if(extras!=null){
for(String key: extras.keySet()){
message+= key + "=" + extras.getString(key) + "\n";
}
}
}
}
message+="\n";
return message;
}
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;
}
public boolean onOptionsItemSelected(MenuItem item) {
if(item.getItemId() == R.id.menu_clear){
tView.setText("");
return true;
}
else{
return super.onOptionsItemSelected(item);
}
}
}
ExternalReceiver.java
package com.test.awstestapp;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
public class ExternalReceiver extends BroadcastReceiver {
public void onReceive(Context context, Intent intent) {
if(intent!=null){
Bundle extras = intent.getExtras();
if(!AndroidMobilePushApp.inBackground){
MessageReceivingService.sendToApp(extras, context);
}
else{
MessageReceivingService.saveToLog(extras, context);
}
}
}
}
MessageReceivingService.java
public class MessageReceivingService extends Service{
private GoogleCloudMessaging gcm;
public static SharedPreferences savedValues;
public static void sendToApp(Bundle extras, Context context){
Intent newIntent = new Intent();
newIntent.setClass(context, AndroidMobilePushApp.class);
newIntent.putExtras(extras);
newIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(newIntent);
}
public void onCreate(){
super.onCreate();
final String preferences = getString(R.string.preferences);
savedValues = getSharedPreferences(preferences, Context.MODE_PRIVATE);
// In later versions multi_process is no longer the default
if(VERSION.SDK_INT > 9){
savedValues = getSharedPreferences(preferences, Context.MODE_MULTI_PROCESS);
}
gcm = GoogleCloudMessaging.getInstance(getBaseContext());
SharedPreferences savedValues = PreferenceManager.getDefaultSharedPreferences(this);
if(savedValues.getBoolean(getString(R.string.first_launch), true)){
register();
SharedPreferences.Editor editor = savedValues.edit();
editor.putBoolean(getString(R.string.first_launch), false);
editor.commit();
}
// Let AndroidMobilePushApp know we have just initialized and there may be stored messages
sendToApp(new Bundle(), this);
}
protected static void saveToLog(Bundle extras, Context context){
SharedPreferences.Editor editor=savedValues.edit();
String numOfMissedMessages = context.getString(R.string.num_of_missed_messages);
int linesOfMessageCount = 0;
for(String key : extras.keySet()){
String line = String.format("%s=%s", key, extras.getString(key));
editor.putString("MessageLine" + linesOfMessageCount, line);
linesOfMessageCount++;
}
editor.putInt(context.getString(R.string.lines_of_message_count), linesOfMessageCount);
editor.putInt(context.getString(R.string.lines_of_message_count), linesOfMessageCount);
editor.putInt(numOfMissedMessages, savedValues.getInt(numOfMissedMessages, 0) + 1);
editor.commit();
postNotification(new Intent(context, AndroidMobilePushApp.class), context);
}
protected static void postNotification(Intent intentAction, Context context){
final NotificationManager mNotificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
final PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intentAction, Notification.DEFAULT_LIGHTS | Notification.FLAG_AUTO_CANCEL);
final Notification notification = new NotificationCompat.Builder(context).setSmallIcon(R.mipmap.ic_launcher)
.setContentTitle("Message Received!")
.setContentText("")
.setContentIntent(pendingIntent)
.setAutoCancel(true)
.getNotification();
mNotificationManager.notify(R.string.notification_number, notification);
}
private void register() {
new AsyncTask(){
protected Object doInBackground(final Object... params) {
String token;
try {
token = gcm.register(getString(R.string.project_number));
Log.i("registrationId", token);
}
catch (IOException e) {
Log.i("Registration Error", e.getMessage());
}
return true;
}
}.execute(null, null, null);
}
public IBinder onBind(Intent arg0) {
return null;
}
}
SNSMobilePush.java
package com.test;
public class SNSMobilePush {
private AmazonSNSClientWrapper snsClientWrapper;
public SNSMobilePush(AmazonSNS snsClient) {
this.snsClientWrapper = new AmazonSNSClientWrapper(snsClient);
}
public static final Map<Platform, Map<String, MessageAttributeValue>> attributesMap = new HashMap<Platform, Map<String, MessageAttributeValue>>();
static {
attributesMap.put(Platform.ADM, null);
attributesMap.put(Platform.GCM, null);
attributesMap.put(Platform.APNS, null);
attributesMap.put(Platform.APNS_SANDBOX, null);
attributesMap.put(Platform.BAIDU, addBaiduNotificationAttributes());
attributesMap.put(Platform.WNS, addWNSNotificationAttributes());
attributesMap.put(Platform.MPNS, addMPNSNotificationAttributes());
}
public static void main(String[] args) throws IOException {
/*
* TODO: Be sure to fill in your AWS access credentials in the
* AwsCredentials.properties file before you try to run this sample.
* http://aws.amazon.com/security-credentials
*/
AmazonSNS sns = new AmazonSNSClient(new PropertiesCredentials(
SNSMobilePush.class
.getResourceAsStream("AwsCredentials.properties")));
sns.setEndpoint("https://sns.us-west-2.amazonaws.com");
System.out.println("===========================================\n");
System.out.println("Getting Started with Amazon SNS");
System.out.println("===========================================\n");
try {
SNSMobilePush sample = new SNSMobilePush(sns);
/* TODO: Uncomment the services you wish to use. */
sample.demoAndroidAppNotification();
// sample.demoKindleAppNotification();
// sample.demoAppleAppNotification();
// sample.demoAppleSandboxAppNotification();
// sample.demoBaiduAppNotification();
// sample.demoWNSAppNotification();
// sample.demoMPNSAppNotification();
} catch (AmazonServiceException ase) {
System.out
.println("Caught an AmazonServiceException, which means your request made it "
+ "to Amazon SNS, but was rejected with an error response for some reason.");
System.out.println("Error Message: " + ase.getMessage());
System.out.println("HTTP Status Code: " + ase.getStatusCode());
System.out.println("AWS Error Code: " + ase.getErrorCode());
System.out.println("Error Type: " + ase.getErrorType());
System.out.println("Request ID: " + ase.getRequestId());
} catch (AmazonClientException ace) {
System.out
.println("Caught an AmazonClientException, which means the client encountered "
+ "a serious internal problem while trying to communicate with SNS, such as not "
+ "being able to access the network.");
System.out.println("Error Message: " + ace.getMessage());
}
}
public void demoAndroidAppNotification() {
// TODO: Please fill in following values for your application. You can
// also change the notification payload as per your preferences using
// the method
// com.amazonaws.sns.samples.tools.SampleMessageGenerator.getSampleAndroidMessage()
String serverAPIKey = "REPLACED_WITH_SERVER_API_KEY";
String applicationName = "snspushtest";
String registrationId = "REPLACED_WITH_REG_ID_FROM_AMAZON";
snsClientWrapper.demoNotification(Platform.GCM, "", serverAPIKey,
registrationId, applicationName, attributesMap);
}
public void demoKindleAppNotification() {
// TODO: Please fill in following values for your application. You can
// also change the notification payload as per your preferences using
// the method
// com.amazonaws.sns.samples.tools.SampleMessageGenerator.getSampleKindleMessage()
String clientId = "";
String clientSecret = "";
String applicationName = "";
String registrationId = "";
snsClientWrapper.demoNotification(Platform.ADM, clientId, clientSecret,
registrationId, applicationName, attributesMap);
}
public void demoAppleAppNotification() {
// TODO: Please fill in following values for your application. You can
// also change the notification payload as per your preferences using
// the method
// com.amazonaws.sns.samples.tools.SampleMessageGenerator.getSampleAppleMessage()
String certificate = ""; // This should be in pem format with \n at the
// end of each line.
String privateKey = ""; // This should be in pem format with \n at the
// end of each line.
String applicationName = "";
String deviceToken = ""; // This is 64 hex characters.
snsClientWrapper.demoNotification(Platform.APNS, certificate,
privateKey, deviceToken, applicationName, attributesMap);
}
public void demoAppleSandboxAppNotification() {
// TODO: Please fill in following values for your application. You can
// also change the notification payload as per your preferences using
// the method
// com.amazonaws.sns.samples.tools.SampleMessageGenerator.getSampleAppleMessage()
String certificate = ""; // This should be in pem format with \n at the
// end of each line.
String privateKey = ""; // This should be in pem format with \n at the
// end of each line.
String applicationName = "";
String deviceToken = ""; // This is 64 hex characters.
snsClientWrapper.demoNotification(Platform.APNS_SANDBOX, certificate,
privateKey, deviceToken, applicationName, attributesMap);
}
public void demoBaiduAppNotification() {
/*
* TODO: Please fill in the following values for your application. If
* you wish to change the properties of your Baidu notification, you can
* do so by modifying the attribute values in the method
* addBaiduNotificationAttributes() . You can also change the
* notification payload as per your preferences using the method
* com.amazonaws
* .sns.samples.tools.SampleMessageGenerator.getSampleBaiduMessage()
*/
String userId = "";
String channelId = "";
String apiKey = "";
String secretKey = "";
String applicationName = "";
snsClientWrapper.demoNotification(Platform.BAIDU, apiKey, secretKey,
channelId + "|" + userId, applicationName, attributesMap);
}
public void demoWNSAppNotification() {
/*
* TODO: Please fill in the following values for your application. If
* you wish to change the properties of your WNS notification, you can
* do so by modifying the attribute values in the method
* addWNSNotificationAttributes() . You can also change the notification
* payload as per your preferences using the method
* com.amazonaws.sns.samples
* .tools.SampleMessageGenerator.getSampleWNSMessage()
*/
String notificationChannelURI = "";
String packageSecurityIdentifier = "";
String secretKey = "";
String applicationName = "";
snsClientWrapper.demoNotification(Platform.WNS,
packageSecurityIdentifier, secretKey, notificationChannelURI,
applicationName, attributesMap);
}
public void demoMPNSAppNotification() {
/*
* TODO: Please fill in the following values for your application. If
* you wish to change the properties of your MPNS notification, you can
* do so by modifying the attribute values in the method
* addMPNSNotificationAttributes() . You can also change the
* notification payload as per your preferences using the method
* com.amazonaws
* .sns.samples.tools.SampleMessageGenerator.getSampleMPNSMessage ()
*/
String notificationChannelURI = "";
String applicationName = "";
snsClientWrapper.demoNotification(Platform.MPNS, "", "",
notificationChannelURI, applicationName, attributesMap);
}
private static Map<String, MessageAttributeValue> addBaiduNotificationAttributes() {
Map<String, MessageAttributeValue> notificationAttributes = new HashMap<String, MessageAttributeValue>();
notificationAttributes.put("AWS.SNS.MOBILE.BAIDU.DeployStatus",
new MessageAttributeValue().withDataType("String")
.withStringValue("1"));
notificationAttributes.put("AWS.SNS.MOBILE.BAIDU.MessageKey",
new MessageAttributeValue().withDataType("String")
.withStringValue("default-channel-msg-key"));
notificationAttributes.put("AWS.SNS.MOBILE.BAIDU.MessageType",
new MessageAttributeValue().withDataType("String")
.withStringValue("0"));
return notificationAttributes;
}
private static Map<String, MessageAttributeValue> addWNSNotificationAttributes() {
Map<String, MessageAttributeValue> notificationAttributes = new HashMap<String, MessageAttributeValue>();
notificationAttributes.put("AWS.SNS.MOBILE.WNS.CachePolicy",
new MessageAttributeValue().withDataType("String")
.withStringValue("cache"));
notificationAttributes.put("AWS.SNS.MOBILE.WNS.Type",
new MessageAttributeValue().withDataType("String")
.withStringValue("wns/badge"));
return notificationAttributes;
}
private static Map<String, MessageAttributeValue> addMPNSNotificationAttributes() {
Map<String, MessageAttributeValue> notificationAttributes = new HashMap<String, MessageAttributeValue>();
notificationAttributes.put("AWS.SNS.MOBILE.MPNS.Type",
new MessageAttributeValue().withDataType("String")
.withStringValue("token")); // This attribute is required.
notificationAttributes.put("AWS.SNS.MOBILE.MPNS.NotificationClass",
new MessageAttributeValue().withDataType("String")
.withStringValue("realtime")); // This attribute is required.
return notificationAttributes;
}
}
EDIT 2:
EDIT 3:
I changed the following code to:
AmazonSNS sns = new AmazonSNSClient(new PropertiesCredentials(
SNSMobilePush.class
.getResourceAsStream("AwsCredentials.properties")));
to
AmazonSNS sns = new AmazonSNSClient(new BasicAWSCredentials("ACCESS_KEY_REPLACED",
"SECRET_KEY_REPLACED"));
Now, there is a different error: Logcat
===========================================
Getting Started with Amazon SNS
===========================================
Exception in thread "main" java.lang.NoClassDefFoundError: org/xmlpull/v1/XmlPullParserException
at com.amazonaws.services.sns.AmazonSNSClient.invoke(AmazonSNSClient.java:2263)
at com.amazonaws.services.sns.AmazonSNSClient.createPlatformApplication(AmazonSNSClient.java:358)
at com.test.tools.AmazonSNSClientWrapper.createPlatformApplication(AmazonSNSClientWrapper.java:49)
at com.test.tools.AmazonSNSClientWrapper.demoNotification(AmazonSNSClientWrapper.java:119)
at com.test.SNSMobilePush.demoAndroidAppNotification(SNSMobilePush.java:104)
at com.test.SNSMobilePush.main(SNSMobilePush.java:71)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:483)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:140)
Caused by: java.lang.ClassNotFoundException: org.xmlpull.v1.XmlPullParserException
at java.net.URLClassLoader$1.run(URLClassLoader.java:372)
at java.net.URLClassLoader$1.run(URLClassLoader.java:361)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:360)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
... 11 more
Process finished with exit code 1
I'm using sns v2.2.5 :
build.gradle > compile 'com.amazonaws:aws-android-sdk-sns:2.2.5'
Here is my solution for subscribe/unsubscribe:
public class AmazonPushClient {
private static final String TAG = "AmazonPushClient";
private static final String PLATFORM_APPLICATION_ARN = "*****";
private static final String IDENTITY_POOL_ID = "******";
private AmazonSNSClient mClient;
private boolean isUnregistering;
private Application mApp;
private NotifPreferencesHelper mNotifPreferencesHelper;
public AmazonPushClient(Application application) {
try {
mApp = application;
mClient = createPushClient(application);
mNotifPreferencesHelper = new NotifPreferencesHelper(application);
} catch (Exception e) {
LOGE(TAG, "AmazonPushClient", e);
}
}
#Nullable
private String token() {
try {
return InstanceID.getInstance(mApp).getToken(mApp.getString(R.string.gcm_defaultSenderId),
GoogleCloudMessaging.INSTANCE_ID_SCOPE, null);
} catch (Exception e) {
LOGW(TAG, "token", e);
return null;
}
}
private CognitoCachingCredentialsProvider cognitoCachingCredentialsProvider(Application application) {
return new CognitoCachingCredentialsProvider(
application,
IDENTITY_POOL_ID,
Regions.EU_WEST_1 // if your identity_pool_id start with : eu-west-1
);
}
private AmazonSNSClient createPushClient(Application application) {
AmazonSNSClient client = new AmazonSNSClient(cognitoCachingCredentialsProvider(application));
client.setRegion(Region.getRegion(Regions.EU_WEST_1));
client.addRequestHandler(mHandler);
return client;
}
public void pRegister() {
synchronized (TAG) {
LOGD(TAG, "registering");
isUnregistering = true;
String token = token();
if(TextUtils.isEmpty(token)) {
return;
}
mNotifPreferencesHelper.saveNotificationPreferences(true);
CreatePlatformEndpointRequest platformEndpointRequest = new CreatePlatformEndpointRequest();
platformEndpointRequest.setToken(token());
platformEndpointRequest.setPlatformApplicationArn(PLATFORM_APPLICATION_ARN);
CreatePlatformEndpointResult result = mClient.createPlatformEndpoint(platformEndpointRequest);
mNotifPreferencesHelper.storeEndpointArn(result.getEndpointArn());
}
}
public void pUnregister() {
synchronized (TAG) {
LOGD(TAG, "unregistering");
isUnregistering = false;
mNotifPreferencesHelper.saveNotificationPreferences(false);
DeleteEndpointRequest deletePlatformApplicationRequest = new DeleteEndpointRequest();
deletePlatformApplicationRequest.setEndpointArn(mNotifPreferencesHelper.getEndpointArn());
mClient.deleteEndpoint(deletePlatformApplicationRequest);
}
}
private RequestHandler2 mHandler = new RequestHandler2() {
#Override
public void beforeRequest(Request<?> request) {
}
#Override
public void afterResponse(Request<?> request, Response<?> response) {
if (isUnregistering) {
mNotifPreferencesHelper.storeEndpointArn(null);
}
}
#Override
public void afterError(Request<?> request, Response<?> response, Exception e) {
}
};
}
NotifPreferencesHelper is just something to store the EndpointARN. You have to use this class in a background thread
In association you have to implements GcmListenerService etc.. SNS is just for subscribe, not receive.
https://developers.google.com/cloud-messaging/
With respect to the Properties Credentials
A. Are you sure you are exporting the file in the build? Have you made sure you can access the file using regular file I/O outside of the credentials provider? Are you sure the file is formatted correctly (see https://github.com/aws/aws-sdk-android/blob/master/aws-android-sdk-core/src/main/java/com/amazonaws/auth/PropertiesCredentials.java)
accessKey=KEY
secretKey=SECRET
Also looking at the source you should be able to load this file yourself using http://developer.android.com/reference/java/util/Properties.html.
However, I highly recommend not using this credentials provider. It is extremely unsafe in a mobile applications. Anyone could decompile your app and steal your credentials. A much safer approach is to use Amazon Cognito, which there is a plethora of examples. (Bottom of https://docs.aws.amazon.com/mobile/sdkforandroid/developerguide/setup.html , any of the examples here: https://docs.aws.amazon.com/mobile/sdkforandroid/developerguide/getting-started-android.html as well as samples in the GitHub repo https://github.com/awslabs/aws-sdk-android-samples
Cognito requires a little bit of set-up but the guides are tested, and it really doesn't take much more than a few minutes to be much more secure.
Don't think you should import 'SNSMobilePush' to a module of your android application
In the same application, i created a new module called snspush and
imported SNSMobilePush.java file into it. Also imported the
AwsCredentials.properties file to the same path as that of
SNSMobilePush.java. Added the keys in AwsCredentials.properties file.
SNSMobilePush is just a Java app provided by AWS to do tasks like
upload (bulkupload package) several tokens (device tokens or registration IDs) to Amazon SNS or
send a push notification.
You need to register your mobile app with AWS (using AndroidMobilePushApp android app). You should obtain below information (refer this link)
Client ID and client secret
API key
Device token or Registration ID (per device)
Then you can use SNSMobilePush java app or even a AWS SNS console as described here to send push notification to your registered device.
I would suggest you to try out sending push notification from the console instead of java app. You can register tokens from devices that will install your app in the future as described in the one of the options (preferably the last option) as described here

Is it possible to understand notification comes from which client?

I send notification one client to another successfully. With this method:
ParsePush push = new ParsePush();
String yourMessage = "hello world";
push.setChannel("seconddevice");
push.setMessage(yourMessage);
push.sendInBackground();
my application:
public class ParseApplication extends Application {
String YOUR_APPLICATION_ID="xxx",YOUR_CLIENT_KEY="yyy";
#Override
public void onCreate() {
super.onCreate();
// Add your initialization code here
Parse.initialize(this, YOUR_APPLICATION_ID, YOUR_CLIENT_KEY);
ParseUser.enableAutomaticUser();
ParseACL defaultACL = new ParseACL();
// If you would like all objects to be private by default, remove this line.
defaultACL.setPublicReadAccess(true);
ParseACL.setDefaultACL(defaultACL, true);
PushService.subscribe(this, DEVICE_NAME, NotificationBck.class);
}
}
It works. But when I receive message in second device can I have which device send this notification?
From the Parse Android docs:
The Intent object which is passed to the receiver contains an extras Bundle with two useful mappings. The com.parse.Channel key points to a string representing the channel that the message was sent on. The com.parse.Data key points to a string representing the JSON-encoded value of the "data" dictionary that was set in the push notification.
So, in your receiver, you'd be able to check the data (assuming you've set it when pushing):
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
String channel = intent.getExtras().getString("com.parse.Channel");
String encodedJson = intent.getExtras().getString("com.parse.Data");
Log.d(TAG, "got action " + action + " on channel " + channel + " with:");
JSONObject json = decodeJsonObjectFrom(encodedJson);
logContentsOf(json);
}
private JSONObject decodeJsonObjectFrom(String encodedJson) {
try {
return new JSONObject(encodedJson);
} catch (JSONException e) {
return new JSONObject();
}
}
private void logContentsOf(JSONObject json) {
while (json.keys().hasNext()) {
String key = (String) json.keys().next();
Log.d(TAG, "..." + key + " => " + getStringFrom(json, key));
}
}
private String getStringFrom(JSONObject json, String key) {
try {
return (String) json.get(key);
} catch (JSONException e) {
return "";
}
}

How to create nanohttpd server in android?

Actually ,I had searched some questions and go to the github. But I'm new ,I cannot understand the example.
I want to create the http server in android so I can access it in PC browser.
I had instance a class extend nanohttpd, but the server just don't work. I don't know why ,my computer and phone are in the same WIFI,uh.....
public class MyHTTPD extends NanoHTTPD {
/**
* Constructs an HTTP server on given port.
*/
public MyHTTPD()throws IOException {
super(8080);
}
#Override
public Response serve( String uri, Method method,
Map<String, String> header, Map<String, String> parms,
Map<String, String> files )
{
System.out.println( method + " '222" + uri + "' " );
String msg = "<html><body><h1>Hello server</h1>\n";
if ( parms.get("username") == null )
msg +=
"<form action='?' method='get'>\n" +
" <p>Your name: <input type='text' name='username'></p>\n" +
"</form>\n";
else
msg += "<p>Hello, " + parms.get("username") + "!</p>";
msg += "</body></html>\n";
return new NanoHTTPD.Response(msg );
}
public static void main( String[] args )
{
try
{
new MyHTTPD();
}
catch( IOException ioe )
{
System.err.println( "Couldn't start server:\n" + ioe );
System.exit( -1 );
}
System.out.println( "Listening on port 8080. Hit Enter to stop.\n" );
try { System.in.read(); } catch( Throwable t ) {
System.out.println("read error");
};
}
}
Your sample code is missing one small detail - you create the server but you never call the "start()" method which kicks it off to listen for incoming connections. In your main() method, you could write
(new MyHTTPD()).start();
and all would be well, your server would respond the way you hoped it would.
The reason it works that way is twofold: I want the constructor to be a cheap, inexpensive operation, without side-effects. For instance, while unit testing, I call "start()" in the setup and "stop()" in the teardown methods of my jUnit test.
This is the code working for me, but I have different version of NANOHTTPD, I don't have time right now to test out your solution. Here is UploadServer class and Nano class. I return file-upload.htm from sdcard/Discover Control/Web path
public class UploadServer extends NanoHTTPD {
public UploadServer() throws IOException {
super(8080, new File("."));
}
public Response serve( String uri, String method, Properties header, Properties parms, Properties files ) {
File rootsd = Environment.getExternalStorageDirectory();
File path = new File(rootsd.getAbsolutePath() + "/Discover Control/Web");
Response r = super.serveFile("/file-upload.htm", header, path, true);
return r;
}
}
NanoHttpd class
NanoHTTPD.java
FILE UPLOAD
file-upload.htm
Hope this helps and enjoy your work.
Android Activities have a lifecycle and do not use a main() function.
If you want to start and stop the webserver as part of the Activity then you need call start and stop
in onPause and onResume, ie
public class MyActivity extends Activity {
private MyHTTPD mServer;
#Override
protected void onResume() {
super.onResume();
try {
mServer = new MyHTTPD();
mServer.start();
} catch (IOException e) {
e.printStackTrace();
mServer = null;
}
#Override
protected void onPause() {
super.onPause();
if(mServer != null) {
mServer.stop();
mServer = null;
}
}
}
An alternative is to implement the webserver as part of a Service.
In an app I'm working I have a requirement to keep the webserver running even if the user leaves the app. The only way to do this is to start and stop the webserver as part of a long-running Service that is not bound to the Activity. See Vogella's great tutorial on Android Services.
This code working for fine viewing html pages with css class which are in my assesst folders
androidWebServer.start();
this will start the server below code for server functions
public class AndroidWebServer extends NanoHTTPD {
Realm realm;
Map<String, String> parms;
DBHelper db = new DBHelper(OpenRAP.getContext());
boolean isStartedHS = MainActivity.isStartedHS;
private AsyncHttpServer server = new AsyncHttpServer();
private AsyncServer mAsyncServer = new AsyncServer();
private String TAG = "androidwebserver";
Storage storage = new Storage(OpenRAP.getContext());
public AndroidWebServer(int port) {
super(port);
}
public AndroidWebServer(String hostname, int port) {
super(hostname, port);
}
#Override
public String getHostname() {
return super.getHostname();
}
#Override
public Response serve(IHTTPSession session) {
Method method = session.getMethod();
String uri = session.getUri();
Map<String, String> files = new HashMap<>();
SharedPreferences prefs = OpenRAP.getContext().getSharedPreferences(MainActivity.mypreference, MODE_PRIVATE);
OpenRAP app = (OpenRAP) OpenRAP.getContext();
Storage storage = new Storage(OpenRAP.getContext());
String currentpath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/www/";
String temp = Environment.getExternalStorageDirectory().getAbsolutePath() + "/www/temp/";
String ecarpath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/www/ecars_files/";
String xcontent = Environment.getExternalStorageDirectory().getAbsolutePath() + "/www/xcontent/";
String Endpoint = session.getUri();
if (Endpoint.equals("/")) {
String answer = "";
try {
// Open file from SD Card
File root = Environment.getExternalStorageDirectory().getAbsoluteFile();
FileReader index = new FileReader(root +
"/www/openrap/index.html");
BufferedReader reader = new BufferedReader(index);
String line = "";
while ((line = reader.readLine()) != null) {
answer += line;
}
reader.close();
} catch (IOException ioe) {
Log.w("Httpd", ioe.toString());
}
return newFixedLengthResponse(answer);
}

How to handle multiple Authenticator

To authenticate a request, I use Authenticator.setDefault
which is VM wide...
What If I want to separate different webservices
and each one are aware of their authentication credentials.
Do I need to Authenticator.setDefault for each request ?
This may not work if there are concurrent connection with mixed webservices...
Building on Mike's response above I have the following solution, because while I much appreciate the general idea (that's why I've copied it ;-) , I see a few problems with it:
Mike's solution will throw a NullPointerException if the JDK requests the authentication via one of the two static request methods in java.net.Authenticator that do not pass the URL (then getRequestingURL() will return null).
It requires you to pass in an external regex pattern that deconstructs the URL. This is (very) easy to get wrong, and the URL class in the JDK implements this parsing, so I prefer to use that.
It requires that some external class builds the map of PasswordAuthentication objects, and then sets it. It does not implement a registration mechanism that other components in your system can use. I've also turned it into a singleton.
More of a style thing: I don't recommend duplicating class names (Authenticator), so I've renamed it DefaultAuthenticator.
Below solution I think solves these issues.
/**
* Authenticator which keeps credentials to be passed to the requestor based on authority of the requesting URL. The
* authority is <pre>user:password#host:port</pre>, where all parts are optional except the host.
* <p>
* If the configured credentials are not found, the Authenticator will use the credentials embedded in the URL, if
* present. Embedded credentials are in the form of <pre>user:password#host:port</pre>
*
* #author Michael Fortin 2011-09-23
*/
public final class DefaultAuthenticator extends Authenticator {
private static final Logger LOG = Logger.getLogger(DefaultAuthenticator.class.getName());
private static DefaultAuthenticator instance;
private Map<String, PasswordAuthentication> authInfo = new HashMap<String, PasswordAuthentication>();
private DefaultAuthenticator() {
}
public static synchronized DefaultAuthenticator getInstance() {
if (instance == null) {
instance = new DefaultAuthenticator();
Authenticator.setDefault(instance);
}
return instance;
}
// unit testing
static void reset() {
instance = null;
Authenticator.setDefault(null);
}
#Override
protected PasswordAuthentication getPasswordAuthentication() {
String requestorInfo = getRequestorInfo();
LOG.info(getRequestorType() + " at \"" + getRequestingPrompt() + "\" is requesting " + getRequestingScheme()
+ " password authentication for \"" + requestorInfo + "\"");
if (authInfo.containsKey(requestorInfo)) {
return authInfo.get(requestorInfo);
} else {
PasswordAuthentication pa = getEmbeddedCredentials(getRequestingURL());
if (pa == null) {
LOG.warning("No authentication information");
}
return pa;
}
}
/**
* Register the authentication information for a given URL.
*
* #param url - the URL that will request authorization
* #param auth - the {#link PasswordAuthentication} for this URL providing the credentials
*/
public void register(URL url, PasswordAuthentication auth) {
String requestorInfo = getRequestorInfo(url.getHost(), url.getPort());
authInfo.put(requestorInfo, auth);
}
/**
* Get the requestor info based on info provided.
*
* #param host - hostname of requestor
* #param port - TCP/IP port
* #return requestor info string
*/
private String getRequestorInfo(String host, int port) {
String fullHostname;
try {
InetAddress addr = InetAddress.getByName(host);
fullHostname = addr.getCanonicalHostName();
} catch (UnknownHostException e) {
fullHostname = host;
}
if (port == -1) {
return fullHostname;
} else {
return fullHostname + ":" + port;
}
}
/**
* Get the requestor info for the request currently being processed by this Authenticator.
*
* #return requestor info string for current request
*/
private String getRequestorInfo() {
String host;
InetAddress addr = getRequestingSite();
if (addr == null) {
host = getRequestingHost();
} else {
host = addr.getCanonicalHostName();
}
return getRequestorInfo(host, getRequestingPort());
}
/**
* Get the credentials from the requesting URL.
*
* #param url - URL to get the credentials from (can be null, method will return null)
* #return PasswordAuthentication with credentials from URL or null if URL contains no credentials or if URL is
* null itself
*/
PasswordAuthentication getEmbeddedCredentials(URL url) {
if (url == null) {
return null;
}
String userInfo = url.getUserInfo();
int colon = userInfo == null ? -1 : userInfo.indexOf(":");
if (colon == -1) {
return null;
} else {
String userName = userInfo.substring(0, colon);
String pass = userInfo.substring(colon + 1);
return new PasswordAuthentication(userName, pass.toCharArray());
}
}
}
While I'm at it, let me give you my unit tests (JUnit 4).
/**
* #author Paul Balm - May 10 2012
*/
public class DefaultAuthenticatorTest {
private static final Logger LOG = Logger.getLogger(DefaultAuthenticatorTest.class.getName());
#Before
public void setUp() throws Exception {
DefaultAuthenticator.reset();
DefaultAuthenticator.getInstance();
}
#After
public void tearDown() {
DefaultAuthenticator.reset();
}
#Test
public void testRequestAuthenticationFromURL() throws MalformedURLException, UnknownHostException {
Map<String, String[]> urls = generateURLs();
for (String urlStr : urls.keySet()) {
String[] userInfo = urls.get(urlStr);
LOG.info("Testing: " + urlStr);
URL url = new URL(urlStr);
request(userInfo[1], userInfo[2], url, true);
}
}
#Test
public void testRequestAuthenticationRegistered() throws UnknownHostException, MalformedURLException {
Map<String, String[]> urls = generateURLs();
for (String urlStr : urls.keySet()) {
String[] userInfo = urls.get(urlStr);
LOG.info("Testing: " + urlStr);
URL url = new URL(urlStr);
DefaultAuthenticator.reset();
DefaultAuthenticator auth = DefaultAuthenticator.getInstance();
String userName = userInfo[1];
String password = userInfo[2];
if (password != null) {
// You can't register a null password
auth.register(url, new PasswordAuthentication(userName, password.toCharArray()));
}
request(userName, password, url, false);
}
}
/**
* Generate a bunch of URLs mapped to String array. The String array has the following elements:
* - user info part of URL,
* - expected user,
* - expected password
*
* Note that the keys of the maps must be strings and not URL objects, because of the way URL.equals is
* implemented. This method does not consider the credentials.
*
* #throws MalformedURLException
*/
Map<String, String[]> generateURLs() {
String[] hosts = new String[]{ "127.0.0.1", "localhost.localdomain"};
List<String[]> userData = new ArrayList<String[]>();
// normal cases
userData.add(new String[] { "user:pass#", "user", "pass" }); // results in: http://user:pass#[host]
userData.add(new String[] { "", null, null });
// unexpected cases
userData.add(new String[] { "#", null, null });
userData.add(new String[] { ":#", "", "" });
userData.add(new String[] { "user:#", "user", "" });
userData.add(new String[] { ":pass#", "", "pass" });
Map<String, String[]> urls = new HashMap<String, String[]>();
for (String[] userInfo : userData) {
for (String host : hosts) {
String s = "http://" + userInfo[0] + host;
urls.put(s, userInfo);
}
}
LOG.info("" + urls.size() + " URLs prepared");
return urls;
}
private void request(String expectedUser, String expectedPass, URL url, boolean inURL)
throws UnknownHostException {
String host = url.getHost();
InetAddress addr = InetAddress.getAllByName(host)[0];
int port = url.getPort();
String protocol = url.getProtocol();
String prompt = ""; // prompt for the user when asking for the credentials
String scheme = "basic"; // or digest
RequestorType reqType = RequestorType.SERVER;
PasswordAuthentication credentials =
Authenticator.requestPasswordAuthentication(addr, port, protocol, prompt, scheme);
// If the credentials are in the URL, you can't find them using this method because we're not passing the URL
checkCredentials(url, inURL ? null : expectedUser, inURL ? null : expectedPass, credentials);
credentials = Authenticator.requestPasswordAuthentication(host, addr, port, protocol, prompt, scheme);
// If the credentials are in the URL, you can't find them using this method because we're not passing the URL
checkCredentials(url, inURL ? null : expectedUser, inURL ? null : expectedPass, credentials);
credentials = Authenticator.requestPasswordAuthentication(host, addr, port, protocol, prompt, scheme, url, reqType);
checkCredentials(url, expectedUser, expectedPass, credentials);
}
private void checkCredentials(URL url, String expectedUser, String expectedPass, PasswordAuthentication credentials) {
if (expectedUser == null) {
Assert.assertNull(url.toString(), credentials);
} else {
Assert.assertNotNull(url.toString(), credentials);
Assert.assertEquals(url.toString(), expectedUser, credentials.getUserName());
if (expectedPass == null) {
Assert.assertNull(url.toString(), credentials.getPassword());
} else {
Assert.assertArrayEquals(url.toString(), expectedPass.toCharArray(), credentials.getPassword());
}
}
}
}
Here's the solution I've implemented and it works like a charm!
import java.net.*;
import java.util.*;
import java.util.logging.*;
import java.util.regex.*;
/**
* Authenticator which keeps credentials to be passed to the requester
* based on the concatenation of the authority and the URL that requires
* authentication.
*
* If the configured credentials are not found, the Authenticator will
* use the embedded credentials if present.
*
* Embedded credentials are in the form of <pre><b>user</b>:<b>password</b><i>#host:port/<url-path></i></pre>
*
* #author Michael Fortin 2011-09-23
*/
public class Authenticator extends java.net.Authenticator {
private Logger log = Logger.getLogger(this.getClass().getName());
private Map<String, PasswordAuthentication> authInfos;
private Pattern embeddedAuthInfoPattern;
#Override
protected PasswordAuthentication getPasswordAuthentication() {
String requesterInfo = String.format("%s%s", getRequestingURL().getAuthority(), getRequestingURL().getPath());
log.fine(String.format("%s at \"%s\" is requesting %s password authentication for \"%s\"", getRequestorType(), getRequestingPrompt(), getRequestingScheme(), requesterInfo));
PasswordAuthentication pa = null;
if ((pa = authInfos.get(requesterInfo)) == null && (pa = getEmbeddedPA(getRequestingURL().getAuthority())) == null) {
log.warning(String.format("No authentication information for \"%s\"", requesterInfo));
}
return pa;
}
public void setAuthInfos(Map<String, PasswordAuthentication> authInfos) {
this.authInfos = authInfos;
}
public void setEmbeddedAuthInfoPattern(String pattern) {
this.embeddedAuthInfoPattern = Pattern.compile(pattern);
}
private PasswordAuthentication getEmbeddedPA(String authInfo) {
if (authInfo != null) {
Matcher matcher = embeddedAuthInfoPattern.matcher(authInfo);
if (matcher.find()) {
return new PasswordAuthentication(matcher.group(1), matcher.group(2).toCharArray());
}
}
return null;
}
}
Lack of answers tends to mean that nobody knows, which tells me there isn't an answer.
I've been wondering the same thing, and I think the answer is that it can't be done through java.net. I think you either need to limit your http accesses to one server at a time, or look into other packages such as org.apache.http.client.

Categories

Resources