Java Android upload image to sever - java

I have a probleme with sending a photo to server. When I want to upload a photo a see in console:
java.lang.NullPointerException: Attempt to invoke virtual method 'boolean android.graphics.Bitmap.compress(android.graphics.Bitmap$CompressFormat, int, java.io.OutputStream)' on a null object reference
I did this :
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.provider.MediaStore;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.Toast;
import org.apache.commons.codec.binary.Base64;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
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 org.apache.http.util.EntityUtils;
import java.io.ByteArrayOutputStream;
import java.util.ArrayList;
public class MainActivity extends Activity {
Button btpic, btnup;
private Uri fileUri;
String picturePath;
Uri selectedImage;
Bitmap photo;
String ba1;
public static String URL = "Paste your URL here";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btpic = (Button) findViewById(R.id.cpic);
btpic.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
clickpic();
}
});
btnup = (Button) findViewById(R.id.up);
btnup.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
upload();
}
});
}
private void upload() {
// Image location URL
Log.e("path", "----------------" + picturePath);
// Image
Bitmap bm = BitmapFactory.decodeFile(picturePath);
ByteArrayOutputStream bao = new ByteArrayOutputStream();
bm.compress(Bitmap.CompressFormat.JPEG, 90, bao);
byte[] ba = bao.toByteArray();
ba1 = Base64.encodeBase64String(ba);
// Log.e("base64", "-----" + ba1);
// Upload image to server
new uploadToServer().execute();
}
private void clickpic() {
// Check Camera
if (getApplicationContext().getPackageManager().hasSystemFeature(
PackageManager.FEATURE_CAMERA)) {
// Open default camera
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra(MediaStore.EXTRA_OUTPUT, fileUri);
// start the image capture Intent
startActivityForResult(intent, 100);
} else {
Toast.makeText(getApplication(), "Camera not supported", Toast.LENGTH_LONG).show();
}
}
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == 100 && resultCode == RESULT_OK) {
selectedImage = data.getData();
photo = (Bitmap) data.getExtras().get("data");
// Cursor to get image uri to display
String[] filePathColumn = {MediaStore.Images.Media.DATA};
Cursor cursor = getContentResolver().query(selectedImage,
filePathColumn, null, null, null);
cursor.moveToFirst();
int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
picturePath = cursor.getString(columnIndex);
cursor.close();
Bitmap photo = (Bitmap) data.getExtras().get("data");
ImageView imageView = (ImageView) findViewById(R.id.Imageprev);
imageView.setImageBitmap(photo);
}
}
public class uploadToServer extends AsyncTask<Void, Void, String> {
private ProgressDialog pd = new ProgressDialog(MainActivity.this);
protected void onPreExecute() {
super.onPreExecute();
pd.setMessage("Wait image uploading!");
pd.show();
}
#Override
protected String doInBackground(Void... params) {
ArrayList<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
nameValuePairs.add(new BasicNameValuePair("base64", ba1));
nameValuePairs.add(new BasicNameValuePair("ImageName", System.currentTimeMillis() + ".jpg"));
try {
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost(URL);
httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
HttpResponse response = httpclient.execute(httppost);
String st = EntityUtils.toString(response.getEntity());
Log.v("log_tag", "In the try Loop" + st);
} catch (Exception e) {
Log.v("log_tag", "Error in http connection " + e.toString());
}
return "Success";
}
protected void onPostExecute(String result) {
super.onPostExecute(result);
pd.hide();
pd.dismiss();
}
}
}
A log :
08:52:35.199 941-941/com.example.krzysiek.myapplication76 E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.krzysiek.myapplication76, PID: 941
java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String android.net.Uri.toString()' on a null object reference
at com.example.krzysiek.myapplication76.MainActivity.clickpic(MainActivity.java:90)
at com.example.krzysiek.myapplication76.MainActivity.access$000(MainActivity.java:34)
at com.example.krzysiek.myapplication76.MainActivity$1.onClick(MainActivity.java:52)
at android.view.View.performClick(View.java:5697)
at android.widget.TextView.performClick(TextView.java:10826)
at android.view.View$PerformClick.run(View.java:22526)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:158)
at android.app.ActivityThread.main(ActivityThread.java:7224)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1230)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1120)
11-15 08:52:56.003 941-1089/com.example.krzysiek.myapplication76 W/System: ClassLoader referenced unknown path: /data/data/com.example.krzysiek.myapplication76/lib
11-15 08:54:47.258 941-950/com.example.krzysiek.myapplication76 W/art: Suspending all threads took: 12.657ms
My manifest :
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.krzysiek.myapplication76">
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="17" />
<uses-feature android:name="android.hardware.camera" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.INTERNET"/>
<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"
android:theme="#style/AppTheme.NoActionBar">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
</application>
</manifest>

Bitmap bm = BitmapFactory.decodeFile(picturePath); returns null bitmap.
The reason would be need read external storage permission. Make sure you have supporting runtime permissions if you are using Android Operating System version which is above 5.0
Also make sure your picturePath represents a file which has URI scheme image.
Good luck there.
Emre

Related

FileNotFoundException when trying to screenshot

Below is my MainActivity and Manifest file. I am trying to implement a screenshot in my app which then gives the option to open the screenshot using other applications. When I click the button in the main activity nothing is happening. It keeps throwing java.io.FileNotFoundException like so
W/System.err: java.io.FileNotFoundException: /storage/emulated/0/ScreenShooter/2021-02-19_07:45:59.jpg: open failed: ENOENT (No such file or directory)
Is there a way to solve this?
package com.levirs.example.screenshooter;
import android.content.Intent;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Environment;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Date;
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button button = findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
screenshoot();
}
});
}
private void screenshoot() {
Date date = new Date();
CharSequence now = android.text.format.DateFormat.format("yyyy-MM-dd_hh:mm:ss", date);
String filename = Environment.getExternalStorageDirectory() + "/ScreenShooter/" + now + ".jpg";
View root = getWindow().getDecorView();
root.setDrawingCacheEnabled(true);
Bitmap bitmap = Bitmap.createBitmap(root.getDrawingCache());
root.setDrawingCacheEnabled(false);
File file = new File(filename);
file.getParentFile().mkdirs();
try {
FileOutputStream fileOutputStream = new FileOutputStream(file);
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fileOutputStream);
fileOutputStream.flush();
fileOutputStream.close();
Uri uri = Uri.fromFile(file);
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(uri, "image/*");
startActivity(intent);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.levirs.example.screenshooter">
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<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>
</application>
</manifest>
its seems like you are access the directory which not exist make sure its exist if you are using default screenshots folder then replace this line
Environment.getExternalStorageDirectory() + "/ScreenShooter/" + now + ".jpg";
to
Environment.getExternalStorageDirectory() + "/Pictures/Screenshots/" + now + ".jpg";
but this getExternalStorageDirectory is depricated now so use this one
getFilesDir()+ "/Pictures/Screenshots/" + now + ".jpg";
You're trying to instance a file on a path only via string which represents path+fileName.
Instead you should instance a new File with path separated from the fileName.
A similar problem

NFC Tag Reading Activity not receiving intent

I have an activity to read NFC Type A tags (non-NDEF). I am running Android Studio with Android phone in developer mode.
The project launches the application correctly on the developer Android phone with NFC switched on on the phone. When I tap my NFC contactless card on the phone, the phone detects the NFC card but shows an options list of other NFC reader application installed on the phone instead of passing the intent to the foreground application.
How do I get the foreground project's application to receive the NFC intent instead of having a suggestions list popout ?
Here's my AndroidManifest.xml file:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="testtag">
<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=".TapTagActivity">
<intent-filter>
<action android:name="android.nfc.action.TECH_DISCOVERED" />
</intent-filter>
<meta-data
android:name="android.nfc.action.TECH_DISCOVERED"
android:resource="#xml/nfc_tech_filter" />
</activity>
<activity android:name=".ManageTagActivity"></activity>
<activity android:name=".EnquireTagActivity"></activity>
<activity android:name=".SelectTagActionActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".TestActivity" />
</application>
<uses-permission android:name="android.permission.NFC" />
<uses-sdk android:minSdkVersion="10" />
<uses-feature
android:name="android.hardware.nfc"
android:required="true" />
</manifest>
Here's the Activity Java class:
package testtag;
import androidx.appcompat.app.AppCompatActivity;
import android.app.Activity;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.nfc.NfcAdapter;
import android.nfc.NfcManager;
import android.nfc.Tag;
import android.os.Bundle;
import android.util.Log;
public class TapTagActivity extends AppCompatActivity {
private static Class targetActivity = null;
private NfcAdapter nfcAdapter = null;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_tap_tag);
System.out.println("Tap Tag window ready ...");
NfcManager nfcManager = (NfcManager) getSystemService(Context.NFC_SERVICE);
// nfcAdapter = nfcManager.getDefaultAdapter();
nfcAdapter = NfcAdapter.getDefaultAdapter(this);
if (nfcManager != null) {
System.out.println("NFC Manager ready ...");
}
if (nfcAdapter != null) {
System.out.println("NFC Adapter ready ...");
}
}
#Override
protected void onResume() {
super.onResume();
Intent intent = new Intent();
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
PendingIntent nfcPendingIntent = PendingIntent.getActivity(this, 0, intent, 0);
if (nfcAdapter != null) {
nfcAdapter.enableForegroundDispatch(this, nfcPendingIntent, null, null);
}
}
#Override
protected void onPause() {
super.onPause();
if (nfcAdapter != null) {
try {
nfcAdapter.disableForegroundDispatch(this);
} catch (IllegalStateException ex) {
Log.e("ATHTAG","Error disabling NFC foreground dispatch", ex);
}
}
}
#Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
System.out.println("Doing onNewIntent() ...");
// Use NFC to read tag
Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
if (tag != null) {
System.out.println("New tag found !!!");
} else {
System.out.println("No new tag found !!!");
}
}
public static void setTargetRedirectIntent(Class activity) {
targetActivity = activity;
}
}
The console manages to print the:
I/System.out: Tap Tag window ready ...
I/System.out: NFC Manager ready ...
NFC Adapter ready ...
How do I read the NFC card from the foreground without having the suggestions list with installed NFC reader apps appear ?
I figured out that I have to set enableForegroundDispatch() parameters in the onResume() instead of leaving null values.
Working code:
package testtag;
import androidx.appcompat.app.AppCompatActivity;
import android.app.Activity;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.nfc.NfcAdapter;
import android.nfc.NfcManager;
import android.nfc.Tag;
import android.nfc.tech.IsoDep;
import android.nfc.tech.NfcA;
import android.nfc.tech.NfcB;
import android.os.Bundle;
import android.util.Log;
public class TapTagActivity extends AppCompatActivity {
private static Class targetActivity = null;
private NfcAdapter nfcAdapter = null;
private IntentFilter[] intentFiltersArray = null;
private String[][] techListsArray = null;
private PendingIntent pendingIntent = null;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_tap_tag);
System.out.println("Tap Tag window ready ...");
NfcManager nfcManager = (NfcManager) getSystemService(Context.NFC_SERVICE);
// nfcAdapter = nfcManager.getDefaultAdapter();
nfcAdapter = NfcAdapter.getDefaultAdapter(this);
if (nfcManager != null) {
System.out.println("NFC Manager ready ...");
}
if (nfcAdapter != null) {
System.out.println("NFC Adapter ready ...");
}
pendingIntent = PendingIntent.getActivity(
this, 0, new Intent(this, getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0);
intentFiltersArray = new IntentFilter[]{new IntentFilter(NfcAdapter.ACTION_TECH_DISCOVERED)};
techListsArray = new String[][]{new String[]{NfcA.class.getName()}, new String[]{NfcB.class.getName()}, new String[]{IsoDep.class.getName()}};
}
#Override
protected void onResume() {
super.onResume();
Intent intent = new Intent();
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
PendingIntent nfcPendingIntent = PendingIntent.getActivity(this, 0, intent, 0);
if (nfcAdapter != null) {
nfcAdapter.enableForegroundDispatch(this, pendingIntent, intentFiltersArray, techListsArray);
}
}
#Override
protected void onPause() {
super.onPause();
if (nfcAdapter != null) {
try {
nfcAdapter.disableForegroundDispatch(this);
} catch (IllegalStateException ex) {
Log.e("ATHTAG", "Error disabling NFC foreground dispatch", ex);
}
}
}
#Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
System.out.println("Doing onNewIntent() ...");
// Use NFC to read tag
Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
if (tag != null) {
System.out.println("New tag found !!!");
} else {
System.out.println("No new tag found !!!");
}
}
public static void setTargetRedirectIntent(Class activity) {
targetActivity = activity;
}
}

avoid of send null from destroyed activity to restarted service

I want to programing app for data track in background , so I use service .
I want to write a program that monitors all data sent and received by the device, and when the total volume of received or received messages reaches a specified value, the Internet device is turned off.
So I used the following code to monitor the data:
 
mStartRX = TrafficStats.getTotalRxBytes ();
mStartTX = TrafficStats.getTotalTxBytes ();
And I used the services to work on the background in the background.
To specify the download or upload limit from the user with edittext, I requested this limit in mainactivity and send this value to the service.
The problem is when: When I destroy the program, I will restart the service and get the NULL value and the program crashes.
My application code:
Main Activity :
package ir.alexandre9009.service;
import android.app.AlertDialog;
import android.content.Context;
import android.net.TrafficStats;
import android.os.Bundle;
import android.app.Activity;
import android.content.Intent;
import android.os.Handler;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
public class MainActivity extends Activity {
public static Handler mHandler = new Handler();
public static long UPP;
public static long DLL;
Button startService,stopService;
public Context context=this;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (FirstService.mStartRX == TrafficStats.UNSUPPORTED || FirstService.mStartTX == TrafficStats.UNSUPPORTED) {
AlertDialog.Builder alert = new AlertDialog.Builder(this);
alert.setTitle("Uh Oh!");
alert.setMessage("Your device does not support traffic stat monitoring.");
alert.show();
} else {
mHandler.postDelayed(mRunnable, 1000);
}
startService=(Button)findViewById(R.id.startService);
stopService=(Button)findViewById(R.id.stopService);
startService.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
EditText UP = (EditText) findViewById(R.id.UP);
String UPPP = UP.getText().toString();
UPP=Long.parseLong(UPPP);
EditText DL = (EditText) findViewById(R.id.DL);
String DLLL = DL.getText().toString();
DLL=Long.parseLong(DLLL);
Intent intent = new Intent(getApplicationContext(), FirstService.class);
String myString = DLLL;
intent.putExtra("StringName", myString);
startService(intent);
}
});
stopService.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
stopService(new Intent(getBaseContext(),FirstService.class));
}
});
}
public final Runnable mRunnable = new Runnable() {
public void run() {
TextView RX = (TextView)findViewById(R.id.RX);
TextView TX = (TextView)findViewById(R.id.TX);
RX.setText(Long.toString(FirstService.rxBytes));
TX.setText(Long.toString(FirstService.txBytes));
mHandler.postDelayed(mRunnable, 1000);
}
};
}
Service :
package ir.alexandre9009.service;
import android.app.AlertDialog;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.net.TrafficStats;
import android.net.wifi.WifiManager;
import android.os.Handler;
import android.os.IBinder;
import android.widget.TextView;
import android.widget.Toast;
public class FirstService extends Service{
public static long mStartRX ;
public static long mStartTX ;
public static long rxBytes ;
public static long txBytes ;
public long dl=MainActivity.DLL;
Context context=this;
private final Runnable mRunnable = new Runnable() {
public void run() {
rxBytes = (TrafficStats.getTotalRxBytes()- mStartRX)/1048576;
txBytes = (TrafficStats.getTotalTxBytes()- mStartTX)/1048576;
if (rxBytes==2) {
stopService(new Intent(getBaseContext(),FirstService.class));
Intent i = new Intent(context,MainActivity.class);
context.startActivity(i);
// WifiManager wifiManager = (WifiManager)getApplicationContext().getSystemService(Context.WIFI_SERVICE);
// wifiManager.setWifiEnabled(false);
//معرفی توست برای نمایش یک پیام کوتاه به کاربر در هنگام خاموش کردن وای فای
Toast.makeText(FirstService.this, "هشدار", Toast.LENGTH_LONG).show();
}
mHandler.postDelayed(mRunnable, 1000);
}
};
private Handler mHandler = new Handler();
#Override
public IBinder onBind(Intent arg0) {
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Toast.makeText(this,"staart",Toast.LENGTH_LONG).show();
mStartTX=0;
mStartRX=0;
mStartRX = TrafficStats.getTotalRxBytes();
mStartTX = TrafficStats.getTotalTxBytes();
mHandler.postDelayed(mRunnable, 1000);
return Service.START_STICKY;
}
#Override
public void onDestroy() {
TrafficStats.clearThreadStatsTag();
Toast.makeText(this,"FirstService Stoped",Toast.LENGTH_LONG).show();
mStartTX=0;
mStartRX=0;
super.onDestroy();
}
}
AndroidManifest :
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="ir.alexandre9009.service">
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/>
<uses-permission android:name="android.permission.UPDATE_DEVICE_STATS" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<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>
<service android:name=".FirstService"
>
</service>
</application>
</manifest>
please help me ...
The problem is with this line
public long dl=MainActivity.DLL;
You're referring to a variable in the Activity, surly when the Activity is destroyed, this variable is no longer in scope, thus you get Null Exception.
You must get this value using the intent.
The other problem is that you can't prevent any service from being killed by the system except foreground services which need to show a notification to the user. But this is not suitable for your situation.
Therefore, the best approach for you is to check whether intent is null or not. If it is not null, you get the value and save it into Preferences or Database or somewhere, if it is null, you retrieve the value from where you stored it before.

Getting Exception: in android widget

Hi I am trying to make an android widget. In this widget i am trying to update the value of my text view by calling a web service and getting the data from it and displaying it in the text view after a particular tie interval and i am getting an exception.
Exception:java.lang.RuntimeException: Unable to start service com.example.newwidget.UpdateService#40ce9518withIntent{cmp=com.example.newwidget
/.UpdateService (has extras) }: android.view.WindowManager$BadTokenException: Unable to add window -- token null is not for an application
Here is the code which i have tried,
Widget.java
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProvider;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.widget.RemoteViews;
import android.widget.RemoteViews.RemoteView;
import android.widget.Toast;
public class Widget extends AppWidgetProvider {
#Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager,
int[] appWidgetIds) {
Toast.makeText(context, "OnUpdate", Toast.LENGTH_LONG).show();
ComponentName thisWidget = new ComponentName(context,
Widget.class);
int[] allWidgetIds = appWidgetManager.getAppWidgetIds(thisWidget);
Toast.makeText(context, "allWidgetIds", Toast.LENGTH_LONG).show();
// Build the intent to call the service
Intent intent = new Intent(context.getApplicationContext(),
UpdateService.class);
Toast.makeText(context, "call UpdateService", Toast.LENGTH_LONG).show();
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, allWidgetIds);
Toast.makeText(context, "", Toast.LENGTH_LONG).show();
// Update the widgets via the service
context.startService(intent);
}
}
UpdateService.java
import java.io.IOException;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.ResponseHandler;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.BasicResponseHandler;
import org.apache.http.impl.client.DefaultHttpClient;
import android.app.ProgressDialog;
import android.app.Service;
import android.appwidget.AppWidgetManager;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.os.IBinder;
import android.util.Log;
import android.widget.RemoteViews;
import android.widget.Toast;
public class UpdateWidget extends Service {
private RemoteViews views;
private String url;
private String strAPIRender;
private final HttpClient Client = new DefaultHttpClient();
private String Content;
private String Error = null;
private ProgressDialog Dialog = new ProgressDialog(null);
private HttpResponse response;
private HttpEntity httpEntity;
#Override
public void onStart(Intent intent, int startId) {
Log.d("AppWidget.UpdateService", "onStart()");
Toast.makeText(UpdateWidget.this, "Onstart", Toast.LENGTH_LONG).show();
// Build the widget update for today
Toast.makeText(UpdateWidget.this, "Updateviews", Toast.LENGTH_LONG).show();
RemoteViews updateViews = buildUpdate(this);
Log.d("WordWidget.UpdateService", "update built");
Toast.makeText(UpdateWidget.this, "buildupdate finish", Toast.LENGTH_LONG).show();
// Push update for this widget to the home screen
ComponentName thisWidget = new ComponentName(this, WidgetAppActivity.class);
AppWidgetManager manager = AppWidgetManager.getInstance(this);
Toast.makeText(UpdateWidget.this, "final update", Toast.LENGTH_LONG).show();
manager.updateAppWidget(thisWidget, updateViews);
Log.d("WordWidget.UpdateService", "widget updated");
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
public RemoteViews buildUpdate(Context context) {
// Pick out month names from resources
Toast.makeText(UpdateWidget.this, "buildupdate", Toast.LENGTH_LONG).show();
url = "http://www.webservicex.net/currencyconvertor.asmx/ConversionRate?FromCurrency=USD&ToCurrency=INR";
grabURL(url);
Toast.makeText(UpdateWidget.this, "grabURL finish", Toast.LENGTH_LONG).show();
String result = strAPIRender;
views = new RemoteViews(context.getPackageName(), R.layout.activity_widget_app);
views.setTextViewText(R.id.update, result);
return views;
}
public void grabURL(String url) {
Toast.makeText(UpdateWidget.this, "in grabURL method", Toast.LENGTH_LONG).show();
Toast.makeText(null, "execute url", Toast.LENGTH_LONG).show();
try {
HttpGet httpget = new HttpGet(url);
ResponseHandler<String> responseHandler = new BasicResponseHandler();
Content = Client.execute(httpget, responseHandler);
} catch (ClientProtocolException e) {
Error = e.getMessage();
//cancel(true);
} catch (IOException e) {
Error = e.getMessage();
//cancel(true);
}
parseXml(Content);
}
public String parseXml(String content) {
try {
System.out.println(content);
try {
strAPIRender = XMLHandler.GetTagValue("double",content);
} catch (Exception e) {
System.out.println(" catch b");
}
} catch (Exception e) {
System.out.println(" exception in parseXML");
}
return strAPIRender;
}
}
Manifest file
<uses-sdk android:minSdkVersion="8" />
<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" >
<receiver
android:name=".Widget"
android:icon="#drawable/ic_launcher"
android:label="A Widget" >
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>
<meta-data
android:name="android.appwidget.provider"
android:resource="#xml/widget_info" />
</receiver>
<service android:name="com.example.newwidget.UpdateService"></service>
</application>
Remove the following line from UpdateService:
private ProgressDialog Dialog = new ProgressDialog(null);
That "Dialog" doesn't appear (at quick glance of that class) to be used anywhere. If you do intend to use it you can't instantiate it like that (it needs a real Context). That should resolve the specific error you are asking about.
(Even if you fix that error, I'm not sure this code will work as expected. You might also want to consider, just for starters: remove all the toasts for debug purposes and use logging and logcat, and/or a debugger; don't use the main UI thread (which services also use by default) for network I/O (see IntentService for an easy way around that); don't do dialogs/alerts/toasts from a Service; and watch out for non-standard naming conventions like starting member variables in upper case, that makes the code difficult to follow (especially when it's not consistent, even if it doesn't follow the convention).)

Android Could execute method of the activity

I'm building a simple paint app and encountering this error given by the logcat:
I'm using the following code:
This SaveDrawing.java serves as the main activity
package com.example.SaveDrawing;
import com.example.SaveDrawing.drawings.DrawingActivity;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
public class SaveDrawing extends Activity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
public void onClick(View view){
switch (view.getId()){
case R.id.drawBtn:
//Intent drawIntent = new Intent(this, DrawingActivity.class);
//startActivity( drawIntent);
//Toast.makeText(getBaseContext(), "This is the Toast message", Toast.LENGTH_SHORT).show();
Intent nextActivity = new Intent(SaveDrawing.this, DrawingActivity.class);
startActivity(nextActivity);
break;
}
}
}
Then the next activity after clicking the button is DrawingActivity.java
package com.example.SaveDrawing.drawings;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.Paint;
import android.graphics.Path;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.MotionEvent;
import android.view.View;
import android.widget.Button;
import java.io.File;
import java.io.FileOutputStream;
import com.example.SaveDrawing.R;
import com.example.SaveDrawing.R.id;
import com.example.SaveDrawing.R.layout;
public class DrawingActivity extends Activity implements View.OnTouchListener{
private DrawingSurface drawingSurface;
private DrawingPath currentDrawingPath;
private Paint currentPaint;
private Button redoBtn;
private Button undoBtn;
private static File APP_FILE_PATH = new File("/sdcard/TutorialForAndroidDrawings");
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.drawing_activity);
setCurrentPaint();
drawingSurface = (DrawingSurface) findViewById(R.id.drawingSurface);
drawingSurface.setOnTouchListener(this);
redoBtn = (Button) findViewById(R.id.redoBtn);
undoBtn = (Button) findViewById(R.id.undoBtn);
redoBtn.setEnabled(false);
undoBtn.setEnabled(false);
}
private void setCurrentPaint(){
currentPaint = new Paint();
currentPaint.setDither(true);
currentPaint.setColor(0xFFFFFF00);
currentPaint.setStyle(Paint.Style.STROKE);
currentPaint.setStrokeJoin(Paint.Join.ROUND);
currentPaint.setStrokeCap(Paint.Cap.ROUND);
currentPaint.setStrokeWidth(3);
}
public boolean onTouch(View view, MotionEvent motionEvent) {
if(motionEvent.getAction() == MotionEvent.ACTION_DOWN){
currentDrawingPath = new DrawingPath();
currentDrawingPath.paint = currentPaint;
currentDrawingPath.path = new Path();
currentDrawingPath.path.moveTo(motionEvent.getX(), motionEvent.getY());
currentDrawingPath.path.lineTo(motionEvent.getX(), motionEvent.getY());
}else if(motionEvent.getAction() == MotionEvent.ACTION_MOVE){
currentDrawingPath.path.lineTo(motionEvent.getX(), motionEvent.getY());
}else if(motionEvent.getAction() == MotionEvent.ACTION_UP){
currentDrawingPath.path.lineTo(motionEvent.getX(), motionEvent.getY());
drawingSurface.addDrawingPath(currentDrawingPath);
undoBtn.setEnabled(true);
redoBtn.setEnabled(false);
}
return true;
}
public void onClick(View view){
switch (view.getId()){
case R.id.colorRedBtn:
currentPaint = new Paint();
currentPaint.setDither(true);
currentPaint.setColor(0xFFFF0000);
currentPaint.setStyle(Paint.Style.STROKE);
currentPaint.setStrokeJoin(Paint.Join.ROUND);
currentPaint.setStrokeCap(Paint.Cap.ROUND);
currentPaint.setStrokeWidth(3);
break;
case R.id.colorBlueBtn:
currentPaint = new Paint();
currentPaint.setDither(true);
currentPaint.setColor(0xFF00FF00);
currentPaint.setStyle(Paint.Style.STROKE);
currentPaint.setStrokeJoin(Paint.Join.ROUND);
currentPaint.setStrokeCap(Paint.Cap.ROUND);
currentPaint.setStrokeWidth(3);
break;
case R.id.colorGreenBtn:
currentPaint = new Paint();
currentPaint.setDither(true);
currentPaint.setColor(0xFF0000FF);
currentPaint.setStyle(Paint.Style.STROKE);
currentPaint.setStrokeJoin(Paint.Join.ROUND);
currentPaint.setStrokeCap(Paint.Cap.ROUND);
currentPaint.setStrokeWidth(3);
break;
case R.id.undoBtn:
drawingSurface.undo();
if( drawingSurface.hasMoreUndo() == false ){
undoBtn.setEnabled( false );
}
redoBtn.setEnabled( true );
break;
case R.id.redoBtn:
drawingSurface.redo();
if( drawingSurface.hasMoreRedo() == false ){
redoBtn.setEnabled( false );
}
undoBtn.setEnabled( true );
break;
case R.id.saveBtn:
final Activity currentActivity = this;
Handler saveHandler = new Handler(){
#Override
public void handleMessage(Message msg) {
final AlertDialog alertDialog = new AlertDialog.Builder(currentActivity).create();
alertDialog.setTitle("Saved 1");
alertDialog.setMessage("Your drawing had been saved :)");
alertDialog.setButton("OK", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
return;
}
});
alertDialog.show();
}
} ;
new ExportBitmapToFile(this,saveHandler, drawingSurface.getBitmap()).execute();
break;
}
}
private class ExportBitmapToFile extends AsyncTask<Intent,Void,Boolean> {
private Context mContext;
private Handler mHandler;
private Bitmap nBitmap;
public ExportBitmapToFile(Context context,Handler handler,Bitmap bitmap) {
mContext = context;
nBitmap = bitmap;
mHandler = handler;
}
#Override
protected Boolean doInBackground(Intent... arg0) {
try {
if (!APP_FILE_PATH.exists()) {
APP_FILE_PATH.mkdirs();
}
final FileOutputStream out = new FileOutputStream(new File(APP_FILE_PATH + "/myAwesomeDrawing.png"));
nBitmap.compress(Bitmap.CompressFormat.PNG, 90, out);
out.flush();
out.close();
return true;
}catch (Exception e) {
e.printStackTrace();
}
//mHandler.post(completeRunnable);
return false;
}
#Override
protected void onPostExecute(Boolean bool) {
super.onPostExecute(bool);
if ( bool ){
mHandler.sendEmptyMessage(1);
}
}
}
}
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.SaveDrawing"
android:versionCode="1"
android:versionName="1.0">
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-sdk android:minSdkVersion="8" />
<application android:icon="#drawable/icon" android:label="#string/app_name">
<activity android:name=".SaveDrawing"
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=".DrawingActivity" android:screenOrientation="landscape" ></activity>
<activity android:name=".drawings.DrawingActivity"/>
</application>
</manifest>
I have the following in my explorer. I'm not so sure if I got a wrong file structure.
Anyone can help me? I'm kinda new to java and android programming. Many thanks!!! :)
remove <activity android:name=".DrawingActivity" android:screenOrientation="landscape" ></activity> from your manifest as there is no such activity. there is only DrawingActivity in your project structure. Then clean build Run.
Also another possible problem could having an Activity Class name SaveDrawing in the package. You should try to rename the package, update relevant changes to the manifest and try running the app again..
You probably forgot to declare DrawingActivity in your manifest.xml
This is because you attempt to launch com.example.SaveDrawing.drawings/com.example.SaveDrawing.drawings.DrawingActivity,
but actual activity you launch in code is com.example.SaveDrawing/com.example.SaveDrawing.drawings.DrawingActivity
Please change
Intent nextActivity = new Intent(SaveDrawing.this, DrawingActivity.class);
to
Intent nextActivity = new Intent();
nextActivity.setClassName ("com.example.SaveDrawing.drawings", "com.example.SaveDrawing.drawings.DrawingActivity");
It might work.

Categories