I'm currently starting to develop apps for android but I'm currently stuck with an unknownhostexception.
Here is my code:
...
protected class FetchWeatherTask extends AsyncTask <String, Void, Void>{
private final String LOG_TAG = FetchWeatherTask.class.getSimpleName();
protected Void doInBackground(String... params) {
//initialize Connection and reader
HttpURLConnection urlconnection=null;
BufferedReader reader=null;
String forecastJsonStr =null;
String format = "json";
String units = "metric";
int numDays = 7;
try{
final String BASE_URL = "http://apikey.openweathermap.org/data/2.5/forecast/daily";
final String QUERY_PARAM="zip";
final String FORMAT_PARAM= "mode";
final String UNITS_PARAM= "units";
final String DAYS_PARAM= "cnt";
final String APPID_PARAM="APPID";
//make Connection to the OpenWeatherURL
//IDEA: API-Code for future use as parameter of the method
//String apikey = "&APPID="+BuildConfig.OPEN_WEATHER_MAP_API_KEY;
//String baseUrl="http://apikey.openweathermap.org/data/2.5/forecast/daily?zip=94043&mode=json&units=metric&cnt=7";
//URL url= new URL(baseUrl.concat(apikey));
Uri builtUri = Uri.parse(BASE_URL).buildUpon()
.appendQueryParameter(QUERY_PARAM,params[0])
.appendQueryParameter(FORMAT_PARAM,format)
.appendQueryParameter(UNITS_PARAM,units)
.appendQueryParameter(DAYS_PARAM,Integer.toString(numDays))
.appendQueryParameter(APPID_PARAM,BuildConfig.OPEN_WEATHER_MAP_API_KEY)
.build();
URL url = new URL(builtUri.toString());
//URL url = new URL("http://apikey.openweathermap.org/data/2.5/forecast/daily?zip=94043&mode=json&units=metric&cnt=7&APPID=31d96db6578ca2e94f31714e882118be");
Log.v(LOG_TAG, "Built URI "+ builtUri.toString());
urlconnection= (HttpURLConnection) url.openConnection();
urlconnection.setRequestMethod("GET");
urlconnection.connect();
//Read inputStream into a buffer
InputStream input = urlconnection.getInputStream();
StringBuffer buffer= new StringBuffer();
if(input==null){
return null;
}
reader = new BufferedReader(new InputStreamReader(input));
String line;
while ((line=reader.readLine())!=null){
buffer.append(line+"\n");
}
if (buffer.length()==0){
return null;
}
forecastJsonStr=buffer.toString();
}
catch(IOException e){
Log.e("ForecastFragment","Error",e);
return null;
}finally {
if(urlconnection==null){
urlconnection.disconnect();
}
if(reader!=null){
try{
reader.close();
} catch (IOException e) {
Log.e("ForecastFragment","Error",e);
}
}
return null;
}
}
}
I have granted internet access permissions for this app as well in my android manifest, but it's still causes this exception. Here the manifest.xml for review purpose:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.cc_student.sunshine.app">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity
android:name=".MainActivity"
android:label="#string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
Related
Java code:
public void onClick(View v) {
switch (v.getId()){
case R.id.btn_camera:
if (i==21) {
Toast.makeText(FileUploadActivity.this,R.string.max_file_upload,Toast.LENGTH_SHORT).show();
}
else {
++i;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (ActivityCompat.checkSelfPermission(FileUploadActivity.this, android.Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
requestPermissions(new String[]{android.Manifest.permission.WRITE_EXTERNAL_STORAGE}, MY_PERMISSIONS);
} else if (ActivityCompat.checkSelfPermission(FileUploadActivity.this, android.Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
requestPermissions(new String[]{android.Manifest.permission.CAMERA}, MY_PERMISSIONS);
} else {
openCamera();
}
} else {
openCamera();
}
}
break;
public void openCamera() {
File photoFile = null;
try {
photoFile = createTempFile("Images", "IMG_", ".jpg"); //error
Log.i(TAG, "openCamera: Camera access"+photoFile);
} catch (IOException e) {
e.printStackTrace();
}
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
takePictureIntent.putExtra("PhotoPath", mCameraPhotoPath);
if (photoFile != null) {
mCameraPhotoPath = photoFile.getAbsolutePath();
}else {
Toast.makeText(FileUploadActivity.this,"Unable to open",Toast.LENGTH_LONG).show();
}
// takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(photoFile));
// startActivityForResult(takePictureIntent, SELECT_PICTURE);
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.R) {
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT,Uri.fromFile(photoFile));
} else {
File file = new File(Uri.fromFile(photoFile).getPath());
Uri photoUri = FileProvider.getUriForFile(getApplicationContext(), getApplicationContext().getPackageName() + ".provider", file);
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoUri);
}
takePictureIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
if (takePictureIntent.resolveActivity(getApplicationContext().getPackageManager()) != null) {
startActivityForResult(takePictureIntent, SELECT_PICTURE);
}
}
private File createTempFile(String storage,String fileName,String fileType) throws IOException {
File imageFile = null;
File folder = new File(Environment.getExternalStorageDirectory() +
File.separator + "CTrack" + File.separator + storage);
boolean success = true;
if (!folder.exists()) {
success = folder.mkdirs();
}
if (success) {
String timeStamp = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss").format(new Date());
String imageFileName = fileName + timeStamp + "_";
imageFile = File.createTempFile(imageFileName, fileType, folder);
}
return imageFile;
}
private String encodeImage(String path) {
File imagefile = new File(path);
FileInputStream fis = null;
String encodeResponse="";
try {
fis = new FileInputStream(imagefile);
Bitmap bm = BitmapFactory.decodeStream(fis);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bm.compress(Bitmap.CompressFormat.JPEG, 100, baos);
byte[] b = baos.toByteArray();
encodeResponse=Base64.encodeToString(b, Base64.DEFAULT);
} catch (FileNotFoundException e) {
e.printStackTrace();
encodeResponse="nofile";
}
catch (OutOfMemoryError e) {
e.printStackTrace();
encodeResponse="memory";
}
return encodeResponse;
}
Permissions:
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
error:
2021-05-03 12:52:30.921 9669-9669/com.transasia.ctrack E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.transasia.ctrack, PID: 9669
android.os.FileUriExposedException: file:///storage/emulated/0/CTrack/Images/IMG_2021-05-03T12%3A52%3A30_6074100336714487332.jpg exposed beyond app through ClipData.Item.getUri()
at android.os.StrictMode.onFileUriExposed(StrictMode.java:2083)
at android.net.Uri.checkFileUriExposed(Uri.java:2388)
at android.content.ClipData.prepareToLeaveProcess(ClipData.java:977)
at android.content.Intent.prepareToLeaveProcess(Intent.java:10759)
at android.content.Intent.prepareToLeaveProcess(Intent.java:10744)
at android.app.Instrumentation.execStartActivity(Instrumentation.java:1703)
at android.app.Activity.startActivityForResult(Activity.java:5192)
at androidx.fragment.app.FragmentActivity.startActivityForResult(FragmentActivity.java:675)
at android.app.Activity.startActivityForResult(Activity.java:5150)
App is working in android 9 and below 9 but when it comes to android 10 and 11, app is crashing and getting file error. I thought problem with creating temp file because there it gives me an error.
Thank you,........................................................................Thanks...........................................................................................................
Try this
In Manifest file - add provider inside
<application android:requestLegacyExternalStorage="true">
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="${applicationId}.provider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="#xml/provider_paths" />
</provider>
create provider_path.xml (res -> xml -> provider_path.xml)
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-path
name="external_files"
path="." />
</paths>
Add Camera permission
<uses-permission android:name="android.permission.CAMERA"/>
<uses-feature android:name="android.hardware.camera" />
Specifically I am looking to upload a file with extension .xls
I have a project that tries to do this, but the following error exists
E/AndroidRuntime: FATAL EXCEPTION: Thread-6
Process: com.example.excelpromodel, PID: 12651
java.lang.NoClassDefFoundError: Failed resolution of: Lorg/apache/http/client/methods/HttpPut;
at com.dropbox.client2.DropboxAPI.putFileRequest(DropboxAPI.java:2390)
at com.dropbox.client2.DropboxAPI.putFileOverwriteRequest(DropboxAPI.java:1760)
at com.dropbox.client2.DropboxAPI.putFileOverwrite(DropboxAPI.java:1726)
at com.example.excelpromodel.SQLite2ExcelActivity$4.run(SQLite2ExcelActivity.java:267)
at java.lang.Thread.run(Thread.java:764)
Caused by: java.lang.ClassNotFoundException: Didn't find class "org.apache.http.client.methods.HttpPut" on path: DexPathList[[zip file "/data/app/com.example.excelpromodel-pu6SR7F9dUiyu9bWnHwX8w==/base.apk"],nativeLibraryDirectories=[/data/app/com.example.excelpromodel-pu6SR7F9dUiyu9bWnHwX8w==/lib/arm, /system/lib, /system/vendor/lib]]
at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:134)
at java.lang.ClassLoader.loadClass(ClassLoader.java:379)
at java.lang.ClassLoader.loadClass(ClassLoader.java:312)
at com.dropbox.client2.DropboxAPI.putFileRequest(DropboxAPI.java:2390)
at com.dropbox.client2.DropboxAPI.putFileOverwriteRequest(DropboxAPI.java:1760)
at com.dropbox.client2.DropboxAPI.putFileOverwrite(DropboxAPI.java:1726)
at com.example.excelpromodel.SQLite2ExcelActivity$4.run(SQLite2ExcelActivity.java:267)
at java.lang.Thread.run(Thread.java:764)
My code is:
public class SQLite2ExcelActivity extends AppCompatActivity {
public static Button button1;
public static String path = Environment.getExternalStorageDirectory().getPath() + "/Backup/";
public static File Dir = new File(path);
public void onClickBut1(View v) {
UploadToDropboxFromPath(path + "test.txt", "excel/test.txt");
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_sqlite_2_xl);
button1 = findViewById(R.id.button1);
initViews();
AndroidAuthSession session = buildSession();
dropboxAPI = new DropboxAPI<AndroidAuthSession>(session);
}
static DropboxAPI<AndroidAuthSession> dropboxAPI;
private static final String APP_KEY = "";
private static final String APP_SECRET = "";
private static final String ACCESSTOKEN = "";
private DropboxAPI.UploadRequest request;
private AndroidAuthSession buildSession()
{
AppKeyPair appKeyPair = new AppKeyPair(APP_KEY, APP_SECRET);
AndroidAuthSession session = new AndroidAuthSession(appKeyPair);
session.setOAuth2AccessToken(ACCESSTOKEN);
return session;
}
static final int UploadFromSelectApp = 9501;
static final int UploadFromFilemanager = 9502;
public static String DropboxUploadPathFrom = "";
public static String DropboxUploadName = "";
public static String DropboxDownloadPathFrom = "";
public static String DropboxDownloadPathTo = "";
private void UploadToDropboxFromPath (String uploadPathFrom, String uploadPathTo)
{
Toast.makeText(getApplicationContext(), "Upload file ...", Toast.LENGTH_SHORT).show();
final String uploadPathF = uploadPathFrom;
final String uploadPathT = uploadPathTo;
Thread th = new Thread(new Runnable()
{
public void run()
{
File tmpFile = null;
try
{
tmpFile = new File(uploadPathF);
}
catch (Exception e) {e.printStackTrace();}
FileInputStream fis = null;
try
{
fis = new FileInputStream(tmpFile);
}
catch (FileNotFoundException e) {e.printStackTrace();}
try
{
dropboxAPI.putFileOverwrite(uploadPathT, fis, tmpFile.length(), null);
}
catch (Exception e) {}
getMain().runOnUiThread(new Runnable() {
#Override
public void run() {
Toast.makeText(getApplicationContext(), "File successfully uploaded.", Toast.LENGTH_SHORT).show();
}
});
}
});
th.start();
}
#Override
public void onActivityResult(int requestCode, int resultCode, Intent intent)
{
if (requestCode == UploadFromFilemanager)
{
final Uri currFileURI = intent.getData();
final String pathFrom = currFileURI.getPath();
Toast.makeText(getApplicationContext(), "Upload file ...", Toast.LENGTH_SHORT).show();
Thread th = new Thread(new Runnable()
{
public void run()
{
getMain().runOnUiThread(new Runnable()
{
#Override
public void run()
{
UploadToDropboxFromPath(pathFrom, "/db-test/" + DropboxUploadName + pathFrom.substring(pathFrom.lastIndexOf('.')));
Toast.makeText(getApplicationContext(), "File successfully uploaded.", Toast.LENGTH_SHORT).show();
}
});
}
});
th.start();
}...
}
public String getPath(Context context, Uri contentUri) {
Cursor cursor = null;
try {
String[] proj = { MediaStore.Images.Media.DATA, MediaStore.Video.Media.DATA, MediaStore.Audio.Media.DATA };
cursor = context.getContentResolver().query(contentUri, proj, null, null, null);
int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
cursor.moveToFirst();
String s = cursor.getString(column_index);
if(s!=null) {
cursor.close();
return s;
}
}
catch(Exception e){}
try {
int column_index = cursor.getColumnIndexOrThrow(MediaStore.Video.Media.DATA);
cursor.moveToFirst();
String s = cursor.getString(column_index);
if(s!=null) {
cursor.close();
return s;
}
}
catch(Exception e){}
try {
int column_index = cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.DATA);
cursor.moveToFirst();
String s = cursor.getString(column_index);
cursor.close();
return s;
}
finally {
if (cursor != null) {
cursor.close();
}
}
}
public SQLite2ExcelActivity getMain()
{
return this;
}
AndroidManifest..
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.excelpromodel">
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<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">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name="com.dropbox.client2.android.AuthActivity"
android:configChanges="orientation|keyboard"
android:launchMode="singleTask" >
<intent-filter>
<data android:scheme="db-akg125xzg45a9gc" />
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.BROWSABLE"/>
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<activity
android:name=".SQLite2ExcelActivity"
android:label="#string/app_name"
android:theme="#style/AppTheme" />
<activity
android:name=".Excel2SQLiteActivity"
android:label="#string/app_name"
android:theme="#style/AppTheme" />
</application>
</manifest>
and dependences
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'androidx.appcompat:appcompat:1.0.2'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
implementation 'com.google.android.material:material:1.0.0'
implementation 'com.ajts.androidmads.SQLite2Excel:library:1.0.4'
implementation 'com.ajts.androidmads.sqliteimpex:library:1.0.0'
implementation files('libs/dropbox-android-sdk-1.6.3.jar')
implementation files('libs/json_simple-1.1.jar')
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test:runner:1.2.0'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
get and upload to Dropbox the xls file that is in the "Backup" path with a single button and not from the file manager. Thank you all
I want to get web page source(which is written by me in php) then it shows in textview. However, it returns always null.
I use permisson(INTERNET) but It doesn't work.
When I run this app, TextView shows: "Kaynak Kod: null"
Here is my Activity Codes:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tv = (TextView)findViewById(R.id.textView1);
Button button = (Button)findViewById(R.id.button1);
button.setOnClickListener(new OnClickListener(){
#Override
public void onClick(View v) {
try {
String source = getData("http://www.oeaslan.com/excel/index_.php?gun=1");
tv.setText("Kaynak Kod: "+source);
} catch (Exception e) {
tv.setText("Hata: "+e.getMessage());
}
}
});
}
private String getData(String url){
try{
HttpClient client = new DefaultHttpClient();
HttpGet request = new HttpGet(url);
HttpResponse response = client.execute(request);
String html = "";
InputStream in = response.getEntity().getContent();
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
StringBuilder str = new StringBuilder();
String line = null;
while((line = reader.readLine()) != null)
{
str.append(line);
}
in.close();
html = str.toString();
return html;
}catch(Exception e){
return e.getMessage();
}
}
Manifest:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.omer.text"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="21" />
<uses-permission android:name="android.permission.INTERNET" />
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity
android:name=".MainActivity"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
Regards.
You have a NetworkOnMainThreadException Look in the LogCat to see it. You have to place your code in an AsyncTask or thread.
You can give something like this a try:
HttpGet request = new HttpPost(url);
HttpResponse response = httpclient.execute(request);
String responseBody = EntityUtils.toString(response.getEntity());
All you have to do is include this method in your code :
public static String getSourceCodeOfWebsite(String urlget){
String fetched_data ="";
try {
URL url = null;
url = new URL(urlget);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.connect();
StringBuilder response = new StringBuilder(50000);
InputStream inputStream = connection.getInputStream();
BufferedReader rd = new BufferedReader(new InputStreamReader(inputStream));
int i = 0;
while ((i = rd.read()) > 0) {
response.append((char)i);
}
fetched_data = response.toString();
} catch (Exception e) {
e.printStackTrace();
}
return fetched_data;
}
pass in the URL as parameter and it returns the code
Objective: send a ping to android clients. I have an array of device registration Id's held in my user object.
In GCMIntentService.java, auto created within my app, I get that registration id here
/**
* Called back when a registration token has been received from the Google
* Cloud Messaging service.
*
* #param context
* the Context
*/
#Override
public void onRegistered(Context context, String registration) {
Log.d(TAG, "onRegistered(context, registration), Registration: " + registration);
and then create the DeviceInfo object (also pre defined with app engine) and then add this ID to the user through another endpoint. I have confirmed this works/ see the string held and assume that my device is now registered properly.
When certain things happen in the backend, I have a custom notification class and run this method:
public void sendNotificationPingToUsers(
#Named("userIds") ArrayList<Long> userIds,
ZeppaNotification notification) throws IOException {
Sender sender = new Sender(Constants.SENDER_ID);
PersistenceManager mgr = getPersistenceManager();
try {
ArrayList<String> allDevices = new ArrayList<String>();
for (int i = 0; i < userIds.size(); i++) {
long userId = userIds.get(i);
ZeppaUser zeppaUser = mgr
.getObjectById(ZeppaUser.class, userId);
if (zeppaUser != null) {
ZeppaNotification specificNotification = new ZeppaNotification();
specificNotification.setToUserId(userId);
specificNotification.setFromUserId(notification
.getFromUserId());
specificNotification.setEventId(notification.getEventId());
specificNotification.setExtraMessage(notification
.getExtraMessage());
specificNotification.setNotificationType(notification
.getType());
String extraMessage = specificNotification
.getExtraMessage();
if (extraMessage.length() > 1000) {
extraMessage = extraMessage.substring(0, 1000)
+ "[...]";
}
mgr.makePersistent(specificNotification);
allDevices.addAll(zeppaUser.getDevices());
}
}
if (!allDevices.isEmpty()) {
Message msg = new Message.Builder().collapseKey("sendToSync")
.build();
MulticastResult result = sender.send(msg, allDevices, 5);
result.getTotal();
}
} catch (IOException ex) {
ex.printStackTrace();
} finally {
mgr.close();
}
}
I pass in the other notification so I can recreate it for all users, hold it in the notification table, then ping the device so that it can pull this and any others unseen and create a status bar notification.
This method, again in GCMIntentService:
#Override
public void onMessage(Context context, Intent intent) {
Log.d(TAG, "received message ping");
Is never called and this is where I am trying to handle everything from the device side of things. Can anyone point out what I may be doing wrong or if I am incorrectly interpreting the way this service works?
Thank you
<?xml version="1.0" encoding="utf-8" standalone="no"?>
<uses-sdk
android:minSdkVersion="15"
android:targetSdkVersion="19" />
<permission
android:name="com.minook.zeppa.permission.C2D_MESSAGE"
android:protectionLevel="signature" />
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="android.permission.USE_CREDENTIALS" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="com.minook.zeppa.permission.C2D_MESSAGE" />
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
<uses-permission android:name="android.permission.READ_CONTACTS" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.READ_CALENDAR" />
<uses-permission android:name="android.permission.WRITE_CALENDAR" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<application
android:name=".ZeppaApplication"
android:allowBackup="true"
android:icon="#drawable/zeppa_icon"
android:label="#string/app_name"
android:testOnly="false"
android:theme="#style/ZeppaTheme"
android:uiOptions="none" >
<meta-data
android:name="com.google.android.gms.version"
android:value="#integer/google_play_services_version" />
<activity
android:name=".LoginActivity"
android:label="#string/app_name"
android:logo="#drawable/zeppa_icon"
android:screenOrientation="portrait" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".CreateAccountActivity"
android:label="#string/create_account"
android:logo="#drawable/zeppa_icon" >
</activity>
<activity
android:name=".NewFriendsActivity"
android:label="#string/add_friends"
android:logo="#drawable/zeppa_icon" >
</activity>
<activity
android:name=".MainActivity"
android:label="#string/app_name" >
</activity>
<activity
android:name=".EventViewActivity"
android:label="#string/app_name"
android:logo="#drawable/zeppa_icon" >
</activity>
<activity
android:name=".NewEventActivity"
android:label="#string/app_name"
android:logo="#drawable/zeppa_icon" >
</activity>
<activity
android:name=".UserActivity"
android:label="#string/app_name"
android:logo="#drawable/zeppa_icon" >
</activity>
<activity
android:name=".ZeppaPreferenceActivity"
android:label="#string/event_details"
android:logo="#drawable/zeppa_icon" >
</activity>
<!--
<activity
android:name=".RegisterActivity"
android:launchMode="singleTop" >
</activity>
-->
<service android:name=".GCMIntentService" />
<receiver
android:name="com.google.android.gcm.GCMBroadcastReceiver"
android:permission="com.google.android.c2dm.permission.SEND" >
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
<category android:name="com.minook.zeppa" />
</intent-filter>
<intent-filter>
<action android:name="com.google.android.c2dm.intent.REGISTRATION" />
<category android:name="com.minook.zeppa" />
</intent-filter>
</receiver>
</application>
Another Note: i have tried using the project number and a server key generated by the GAE console with no specified IP. Neither have worked so far.
I just realized I never came back to this.
Turns out that he app-engine created GCM code isn't the ideal way to do it. This is is the essential code in my application with now successfully sends a send-to-sync from the backend and displays a notification in the status bar.
public class ZeppaGCMReceiver extends WakefulBroadcastReceiver {
final private static String TAG = "GCMIntentService";
private static String registrationId = null;
public static void register(final ZeppaApplication application) {
GoogleCloudMessaging gcm = GoogleCloudMessaging.getInstance(application
.getApplicationContext());
try {
registrationId = gcm.register(Constants.PROJECT_NUMBER);
Log.d(TAG, "gcm.register( " + registrationId + " )");
ZeppaUser currentUser = ZeppaUserSingleton.getInstance().getUser();
if (currentUser.getDevices() == null
|| !currentUser.getDevices().contains(registrationId)) {
new AsyncTask<Void, Void, Void>() {
#Override
protected Void doInBackground(Void... params) {
Zeppauserendpoint.Builder endpointBuilder = new Zeppauserendpoint.Builder(
AndroidHttp.newCompatibleTransport(),
new JacksonFactory(),
application.getGoogleAccountCredential());
endpointBuilder = CloudEndpointUtils
.updateBuilder(endpointBuilder);
Zeppauserendpoint userEndpoint = endpointBuilder
.build();
try {
RegisterUserDevice registerTask = userEndpoint
.registerUserDevice(
ZeppaUserSingleton.getInstance().getUserId(),
registrationId);
registerTask.execute();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
}.execute();
} else {
Log.d(TAG, "Already Registered");
}
} catch (IOException e) {
e.printStackTrace();
}
}
public static void unregister(final ZeppaApplication application) {
GoogleCloudMessaging gcm = GoogleCloudMessaging.getInstance(application
.getApplicationContext());
// TODO: registration id in preferences and
try {
gcm.unregister();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
#Override
public void onReceive(Context context, Intent intent) {
Log.d(TAG, "received message ping");
GoogleCloudMessaging gcm = GoogleCloudMessaging.getInstance(context);
String messageType = gcm.getMessageType(intent);
Log.d(TAG, "MessageType: " + messageType);
if (messageType == null) {
Log.d(TAG, "Message is null");
return;
} else if (GoogleCloudMessaging.MESSAGE_TYPE_SEND_ERROR
.equals(messageType)) {
Log.d(TAG, "Error!");
return;
} else if (GoogleCloudMessaging.MESSAGE_TYPE_DELETED
.equals(messageType)) {
Log.d(TAG, "Deleted");
return;
} else if (GoogleCloudMessaging.MESSAGE_TYPE_MESSAGE
.equals(messageType)) {
Log.d(TAG, "Message");
handlePingInAsync(context);
} else {
Log.d(TAG, "WTF are you..? " + intent.toString());
}
}
private void handlePingInAsync(Context context) {
Context[] param = {context};
new AsyncTask<Context, Void, Void>() {
#Override
protected Void doInBackground(Context... params) {
Context context = params[0];
GoogleAccountCredential credential = getCredential(context);
if (credential == null) {
return null;
}
Zeppanotificationendpoint.Builder endpointBuilder = new Zeppanotificationendpoint.Builder(
AndroidHttp.newCompatibleTransport(),
new JacksonFactory(), credential);
endpointBuilder = CloudEndpointUtils
.updateBuilder(endpointBuilder);
Zeppanotificationendpoint notificationEndpoint = endpointBuilder
.build();
try {
SharedPreferences prefs = context.getSharedPreferences(
Constants.SHARED_PREFS, Context.MODE_PRIVATE);
Long userId = prefs.getLong(Constants.USER_ID, -1);
if (userId > 0) {
GetUnseenNotifications getUnseenNotifications = notificationEndpoint
.getUnseenNotifications(userId);
CollectionResponseZeppaNotification collectionResponse = getUnseenNotifications
.execute();
if (collectionResponse == null
|| collectionResponse.getItems() == null) {
} else {
List<ZeppaNotification> notifications = collectionResponse
.getItems();
sendNotificationsForResult(notifications,
context);
try {
NotificationSingleton.getInstance()
.addAllNotifcations(notifications);
} catch (NullPointerException ex) {
ex.printStackTrace();
}
}
} else {
Log.d(TAG, "No Set userId");
}
} catch (IOException ioEx) {
ioEx.printStackTrace();
}
return null;
}
}.execute(param);
}
private GoogleAccountCredential getCredential(Context context) {
GoogleAccountCredential credential = ((ZeppaApplication) context.getApplicationContext())
.getGoogleAccountCredential();
if (credential == null) {
SharedPreferences prefs = context.getSharedPreferences(
Constants.SHARED_PREFS, Context.MODE_PRIVATE);
String email = prefs.getString(Constants.EMAIL_ADDRESS, null);
if (email != null && !email.isEmpty() && Constants.IS_CONNECTED) {
credential = GoogleAccountCredential.usingAudience(context,
Constants.APP_ENGINE_AUDIENCE_CODE);
credential.setSelectedAccountName(email);
return credential;
}
return null;
} else {
return credential;
}
}
#SuppressLint("NewApi")
#SuppressWarnings("deprecation")
private void sendNotificationsForResult(List<ZeppaNotification> resultList,
Context context) {
Log.d(TAG, "trying to send Notifications for result");
Notification.Builder notifBuilder = new Notification.Builder(context);
if (resultList.size() > 1) {
notifBuilder.setContentTitle(resultList.size()
+ " new notifications");
StringBuilder stringBuilder = new StringBuilder();
for (ZeppaNotification notification : resultList) {
stringBuilder.append(notification.getExtraMessage()).append(
'\n');
}
notifBuilder.setContentText(stringBuilder.toString());
Intent intent = new Intent(context, MainActivity.class);
intent.putExtra(Constants.INTENT_NOTIFICATIONS, true);
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0,
intent, 0);
notifBuilder.setContentIntent(pendingIntent);
} else {
ZeppaNotification notification = resultList.get(0);
manageSingleNotification(context, notification, notifBuilder);
notifBuilder.setContentText(notification.getExtraMessage());
}
notifBuilder.setLights(Color.CYAN, 750, 3000);
notifBuilder.setAutoCancel(true);
notifBuilder.setSmallIcon(R.drawable.notif_ic_zeppa);
Notification notification = null;
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN) {
notifBuilder.setPriority(Notification.PRIORITY_DEFAULT);
notification = notifBuilder.build();
} else {
notification = notifBuilder.getNotification();
}
NotificationManager notificationManager = (NotificationManager) context
.getSystemService(Context.NOTIFICATION_SERVICE);
Log.d(TAG, "Notification Should Post");
notificationManager.notify(0, notification);
}
private void manageSingleNotification(Context context,
ZeppaNotification notification, Notification.Builder builder) {
Intent intent = null;
switch (notification.getNotificationOrdinal()) {
case 0:
builder.setContentTitle("New Friend Request");
intent = new Intent(context, NewFriendsActivity.class);
break;
case 1:
builder.setContentTitle("New Connection");
intent = new Intent(context, UserActivity.class);
intent.putExtra(Constants.INTENT_ZEPPA_USER_ID,
notification.getFromUserId());
break;
case 2:
builder.setContentTitle("Event Recommendation");
intent = new Intent(context, EventViewActivity.class);
intent.putExtra(Constants.INTENT_ZEPPA_EVENT_ID,
notification.getEventId());
break;
case 3:
builder.setContentTitle("New Invite");
intent = new Intent(context, EventViewActivity.class);
intent.putExtra(Constants.INTENT_ZEPPA_EVENT_ID,
notification.getEventId());
break;
case 4:
builder.setContentTitle("Event Comment");
intent = new Intent(context, EventViewActivity.class);
intent.putExtra(Constants.INTENT_ZEPPA_EVENT_ID,
notification.getEventId());
break;
case 5:
builder.setContentTitle("Event Canceled");
intent = new Intent(context, MainActivity.class);
intent.putExtra(Constants.INTENT_NOTIFICATIONS, false);
break;
case 6:
builder.setContentTitle("Event Updated");
intent = new Intent(context, EventViewActivity.class);
intent.putExtra(Constants.INTENT_ZEPPA_EVENT_ID,
notification.getEventId());
break;
case 7:
builder.setContentTitle("Friend Joined Event");
intent = new Intent(context, EventViewActivity.class);
intent.putExtra(Constants.INTENT_ZEPPA_EVENT_ID,
notification.getEventId());
break;
case 8:
builder.setContentTitle("Friend Left Event");
intent = new Intent(context, EventViewActivity.class);
intent.putExtra(Constants.INTENT_ZEPPA_EVENT_ID,
notification.getEventId());
break;
case 9:
builder.setContentTitle("Let's Find a Time?");
break;
case 10:
builder.setContentTitle("Time Found!");
break;
case 11:
builder.setContentTitle("Event Reposted");
intent = new Intent(context, EventViewActivity.class);
intent.putExtra(Constants.INTENT_ZEPPA_EVENT_ID,
notification.getEventId());
break;
default: // this shouldnt happen
builder.setContentTitle("New Zeppa Notification");
intent = new Intent(context, MainActivity.class);
intent.putExtra(Constants.INTENT_NOTIFICATIONS, false);
break;
}
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0,
intent, 0);
builder.setContentIntent(pendingIntent);
}
}
And then my Manifest needed:
<permission
android:name="package.permission.C2D_MESSAGE"
android:protectionLevel="signature" />
<uses-permission android:name="package.permission.C2D_MESSAGE" />
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="android.permission.USE_CREDENTIALS" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
<receiver
android:name="package.ZeppaGCMReceiver"
android:exported="true"
android:permission="com.google.android.c2dm.permission.SEND" >
<intent-filter>
<action android:name="com.google.android.c2dm.intent.REGISTRATION" />
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
<category android:name="package.GCMIntentService" />
</intent-filter>
</receiver>
<service
android:name="package.ZeppaGCMService"
android:enabled="true" />
Then, finally, from my endpoints class, when certain things were entered into the database, I determined which users should be notified, and fired this method:
NOTE: getDevices only returns the android device IDS. I got rid of the DeviceInfo class, it didn't seem useful but that should be the improper way of handling this. iOS is handled differently as I am sure you are aware. Will update if I change this/ if people want to see the iOS implementation.
public void sendNotificationPingToUsers(
#Named("userIds") List<Long> userIds,
ZeppaNotification notification) {
Sender sender = new Sender(Constants.SENDER_ID);
PersistenceManager mgr = getPersistenceManager();
try {
List<String> allDevices = new ArrayList<String>();
for (int i = 0; i < userIds.size(); i++) {
long userId = userIds.get(i);
ZeppaUser zeppaUser = mgr
.getObjectById(ZeppaUser.class, userId);
if (zeppaUser != null) {
ZeppaNotification specificNotification = new ZeppaNotification();
specificNotification.setToUserId(userId);
specificNotification.setFromUserId(notification
.getFromUserId());
specificNotification.setEventId(notification.getEventId());
specificNotification.setExtraMessage(notification
.getExtraMessage());
specificNotification.setNotificationType(notification
.getType());
mgr.makePersistent(specificNotification);
allDevices.addAll(zeppaUser.getDevices());
}
}
if (!allDevices.isEmpty()) {
Message msg = new Message.Builder().collapseKey("sendToSync")
.build();
MulticastResult result = sender.send(msg, allDevices, 500);
result.getTotal();
}
} catch (IOException ex) {
ex.printStackTrace();
} finally {
mgr.close();
}
}
I am using oauth-signpost as my OAuth library. When I direct the user to the authorization page, the user logs in and can authorize my application. When that happens, the application is returned to focus and starts the onCreate() method instead of the onResume() method.
My code as follows:
private static final String CONSUMER_KEY = "---";
private static final String CONSUMER_SECRET = "---";
private static String ACCESS_KEY = null;
private static String ACCESS_SECRET = null;
private static final String REQUEST_TOKEN_URL = "https://api.twitter.com/oauth/request_token";
private static final String ACCESS_TOKEN_URL = "https://api.twitter.com/oauth/access_token";
private static final String AUTH_URL = "https://api.twitter.com/oauth/authorize";
private static final String CALLBACK_URL = "myApp://Tweets";
private static CommonsHttpOAuthConsumer consumer = new CommonsHttpOAuthConsumer(CONSUMER_KEY,CONSUMER_SECRET);
private static CommonsHttpOAuthProvider provider = new CommonsHttpOAuthProvider(REQUEST_TOKEN_URL,ACCESS_TOKEN_URL,AUTH_URL);
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
String authUrl = null;
try {
authUrl = provider.retrieveRequestToken(consumer, CALLBACK_URL);
} catch(OAuthMessageSignerException e) {
e.printStackTrace();
} catch(OAuthNotAuthorizedException e) {
e.printStackTrace();
} catch(OAuthExpectationFailedException e) {
e.printStackTrace();
} catch(OAuthCommunicationException e) {
e.printStackTrace();
}
Log.d("OAuthTwitter", "authUrl" + authUrl);
WebView webview = new WebView(this);
webview.getSettings().setJavaScriptEnabled(true);
webview.setVisibility(View.VISIBLE);
setContentView(webview);
webview.loadUrl(authUrl);
}
#Override
public void onResume() {
super.onResume();
Uri uri = this.getIntent().getData();
if (uri != null && uri.toString().startsWith(CALLBACK_URL)) {
Log.d("OAuthTwitter", uri.toString());
String verifier = uri.getQueryParameter(OAuth.OAUTH_VERIFIER);
Log.d("OAuthTwitter", verifier);
try {
provider.retrieveAccessToken(consumer, verifier);
ACCESS_KEY = consumer.getToken();
ACCESS_SECRET = consumer.getTokenSecret();
Log.d("OAuthTwitter", ACCESS_KEY);
Log.d("OAuthTwitter", ACCESS_SECRET);
} catch (OAuthMessageSignerException e) {
e.printStackTrace();
} catch (OAuthNotAuthorizedException e) {
e.printStackTrace();
} catch (OAuthExpectationFailedException e) {
e.printStackTrace();
} catch (OAuthCommunicationException e) {
e.printStackTrace();
}
}
Manifest.xml
<application
android:icon="#drawable/icon"
android:label="#string/app_name">
<activity
android:name=".Tweets"
android:label="#string/app_name">
<intent-filter>
<action
android:name="android.intent.action.MAIN" />
<category
android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<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="myApp"
android:host="Tweets" />
</intent-filter>
</activity>
How do I get my application to call onResume() so that I can then continue with the OAuth process?
In this case, try setting your activity launch mode to singleTask.
See the link for more information: http://developer.android.com/guide/topics/manifest/activity-element.html#lmode