When I open the activity, I request for the directory permission. Once the permission is allowed, I write the name and content of the file and then I press the save button. There is a confirmation dialog before saving the file. I choose YES there and then the following error appears.
2019-07-17 04:29:31.063 17879-17879/com.halimlab.catatanharian E/WindowManager: android.view.WindowLeaked: Activity com.halimlab.catatanharian.InsertAndViewActivity has leaked window DecorView#56fdc15[InsertAndViewActivity] that was originally added here
at android.view.ViewRootImpl.<init>(ViewRootImpl.java:538)
at android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:346)
at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:94)
at android.app.Dialog.show(Dialog.java:329)
at androidx.appcompat.app.AlertDialog$Builder.show(AlertDialog.java:1007)
at com.halimlab.catatanharian.InsertAndViewActivity.konfirmasiSave(InsertAndViewActivity.java:191)
at com.halimlab.catatanharian.InsertAndViewActivity.onBackPressed(InsertAndViewActivity.java:197)
at com.halimlab.catatanharian.InsertAndViewActivity.buatDanUbah(InsertAndViewActivity.java:177)
at com.halimlab.catatanharian.InsertAndViewActivity$1.onClick(InsertAndViewActivity.java:188)
at androidx.appcompat.app.AlertController$ButtonHandler.handleMessage(AlertController.java:167)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:193)
at android.app.ActivityThread.main(ActivityThread.java:6739)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:495)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:859)
Here is my code.
public class InsertAndViewActivity extends AppCompatActivity implements View.OnClickListener {
public static final int REQUEST_CODE_STORAGE = 100;
int eventID = 0;
EditText edtFileName, edtContent;
Button btnSimpan;
boolean isEditable = false;
String fileName = "";
String tempCatatan = "";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_insert_and_view);
// button back
ActionBar menu = getSupportActionBar();
menu.setDisplayShowHomeEnabled(true);
menu.setDisplayHomeAsUpEnabled(true);
// input
edtFileName = findViewById(R.id.editFilename);
edtContent = findViewById(R.id.editContent);
// button
btnSimpan = findViewById(R.id.btnSimpan);
btnSimpan.setOnClickListener(this);
Bundle extras = getIntent().getExtras();
if (extras != null) {
fileName = extras.getString("filename");
edtFileName.setText(fileName);
getSupportActionBar().setTitle("Ubah Catatan");
} else {
getSupportActionBar().setTitle("Tambah Catatan");
}
eventID = 1;
if (Build.VERSION.SDK_INT >= 23) {
if (periksaIzin()) {
bacaFile();
}
} else {
bacaFile();
}
}
#Override
public void onClick(View view) {
switch (view.getId()){
case R.id.btnSimpan :
eventID = 2;
if (!tempCatatan.equals(edtContent.getText().toString())) {
if (Build.VERSION.SDK_INT >= 23) {
konfirmasiSave();
}
} else {
konfirmasiSave();
}
break;
}
}
public boolean periksaIzin() {
if (Build.VERSION.SDK_INT >= 23) {
if (checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) == getPackageManager().PERMISSION_GRANTED) {
return true;
} else {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, REQUEST_CODE_STORAGE);
return false;
}
} else {
return true;
}
}
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
switch (requestCode) {
case REQUEST_CODE_STORAGE :
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
if (eventID == 1) {
bacaFile();
} else {
konfirmasiSave();
}
}
break;
}
}
void bacaFile() {
String path = Environment.getExternalStorageDirectory().toString() + "/halimlab.catatan";
File file = new File(path, edtFileName.getText().toString());
if (file.exists()) {
StringBuilder text = new StringBuilder();
try {
BufferedReader br = new BufferedReader(new FileReader(file));
String line = br.readLine();
while (line != null) {
text.append(line);
line = br.readLine();
}
br.close();
} catch (Exception e) {
System.out.println("ERROR" + e.getMessage());
}
tempCatatan = text.toString();
edtContent.setText(text.toString());
}
}
void buatDanUbah() {
String state = Environment.getExternalStorageState();
if (!Environment.MEDIA_MOUNTED.equals(state)) {
return;
}
String path = Environment.getExternalStorageDirectory().toString() + "/halimlab.catatan";
File parent = new File(path);
if (parent.exists()) {
File file = new File(path, edtFileName.getText().toString());
FileOutputStream outputStream = null;
try {
file.createNewFile();
outputStream = new FileOutputStream(file);
OutputStreamWriter streamWriter = new OutputStreamWriter(outputStream);
streamWriter.append(edtContent.getText());
streamWriter.flush();
streamWriter.close();
streamWriter.flush();
streamWriter.close();
} catch (Exception e) {
e.printStackTrace();
}
} else {
parent.mkdir();
File file = new File(path, edtFileName.getText().toString());
FileOutputStream outputStream = null;
try {
file.createNewFile();
outputStream = new FileOutputStream(file, false);
outputStream.write(edtContent.getText().toString().getBytes());
outputStream.flush();
outputStream.close();
} catch (Exception e) {
e.printStackTrace();
}
}
onBackPressed();
}
void konfirmasiSave () {
new AlertDialog.Builder(this)
.setTitle("Simpan Catatan")
.setMessage("Apakah anda akan menyimpan catatan ini ?")
.setIcon(android.R.drawable.ic_dialog_alert)
.setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
buatDanUbah();
}
})
.setNegativeButton(android.R.string.no, null).show();
}
#Override
public void onBackPressed() {
if (!tempCatatan.equals(edtContent.getText().toString())) {
konfirmasiSave();
}
super.onBackPressed();
}
#Override
public boolean onOptionsItemSelected(#NonNull MenuItem item) {
if (item.getItemId() == R.id.home) {
onBackPressed();
}
return super.onOptionsItemSelected(item);
}
}
I have the necessary permissions in my AndroidManifest.xml.
<uses-permission android:name = "android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name = "android.permission.READ_EXTERNAL_STORAGE"/>
You need to modify the onBackPressed function like the following.
#Override
public void onBackPressed() {
if (!tempCatatan.equals(edtContent.getText().toString()))
konfirmasiSave();
else super.onBackPressed(); // Do that in the else part.
}
Because in the konfirmasiSave function you are opening a dialog which is not being closed or any action is being taken upon it and hence you are calling the super.onBackPressed which is trying to return back to the previous activity and hence causing the window leak error.
And handle the value of the tempCatatan variable before exiting so that your onBackPressed function performs as expected.
Related
I'm using google sheets API with which I am creating new google sheets using sheets API, But this is using the account in which the sheet's API is enabled, If I give my app to another user he cannot create a new sheet using his Gmail. I have the API key, Is it possible to create sheets without selecting Gmail accounts
GoogleAccountCredential mCredential;
private static final String BUTTON_TEXT = "Call Google Sheets API";
private static final String PREF_ACCOUNT_NAME = "accountName";
private static final String[] SCOPES = {SheetsScopes.SPREADSHEETS};
mCredential = GoogleAccountCredential.usingOAuth2(
getApplicationContext(), Arrays.asList(SCOPES))
.setBackOff(new ExponentialBackOff());
private void getResultsFromApi() {
Log.d(TAG, "getResultsFromApi: ");
if (!isGooglePlayServicesAvailable()) {
Log.d(TAG, "getResultsFromApi: 1");
acquireGooglePlayServices();
} else if (mCredential.getSelectedAccountName() == null) {
Log.d(TAG, "getResultsFromApi: 2");
chooseAccount();
} else if (!isDeviceOnline()) {
Log.d(TAG, "getResultsFromApi: No network connection available.");
} else {
// x();
try {
new MakeRequestTask(mCredential).execute();
} catch (IOException e) {
e.printStackTrace();
}
}
}
private boolean isDeviceOnline() {
ConnectivityManager connMgr =
(ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo = connMgr.getActiveNetworkInfo();
return (networkInfo != null && networkInfo.isConnected());
}
#AfterPermissionGranted(REQUEST_PERMISSION_GET_ACCOUNTS)
private void chooseAccount() {
if (EasyPermissions.hasPermissions(
this, Manifest.permission.GET_ACCOUNTS)) {
String accountName = getPreferences(Context.MODE_PRIVATE)
.getString(PREF_ACCOUNT_NAME, null);
if (accountName != null) {
Log.d(TAG, "chooseAccount: 1");
mCredential.setSelectedAccountName(accountName);
getResultsFromApi();
} else {
Log.d(TAG, "chooseAccount: 2");
// Start a dialog from which the user can choose an account
startActivityForResult(
mCredential.newChooseAccountIntent(),
REQUEST_ACCOUNT_PICKER);
}
} else {
// Request the GET_ACCOUNTS permission via a user dialog
EasyPermissions.requestPermissions(
this,
"This app needs to access your Google account (via Contacts).",
REQUEST_PERMISSION_GET_ACCOUNTS,
Manifest.permission.GET_ACCOUNTS);
}
}
private class MakeRequestTask extends AsyncTask<Void, Void, List<String>> {
private com.google.api.services.sheets.v4.Sheets mService = null;
private Exception mLastError = null;
public MakeRequestTask(GoogleAccountCredential credential) throws IOException {
HttpTransport transport = AndroidHttp.newCompatibleTransport();
JsonFactory jsonFactory = JacksonFactory.getDefaultInstance();
mService = new com.google.api.services.sheets.v4.Sheets.Builder(
transport, jsonFactory, credential)
.setApplicationName("Google Sheets API Android Quickstart")
.build();
new Thread() {
#Override
public void run() {
try {
if (consurEtSurname.getText().toString().isEmpty()) {
consurEtSurname.setError("Please provide survey name!");
consurEtSurname.requestFocus();
} else {
Spreadsheet spreadsheet = new Spreadsheet()
.setProperties(new SpreadsheetProperties()
.setTitle(consurEtSurname.getText().toString()));
spreadsheet = mService.spreadsheets().create(spreadsheet)
.setFields("spreadsheetId")
.execute();
Makecolums(mService,spreadsheet.getSpreadsheetId());
upload(spreadsheet.getSpreadsheetId());
Log.d(TAG, "onCreate: " + spreadsheet.getSpreadsheetId());
Log.d(TAG, "run: " + spreadsheet.getSpreadsheetUrl());
}
// writeToSheetUsingApi(mService,spreadsheet.getSpreadsheetId());
} catch (IOException e) {
e.printStackTrace();
} catch (GeneralSecurityException e) {
e.printStackTrace();
}
// catch (GeneralSecurityException e) {
// e.printStackTrace();
// }
}
}.start();
}
//
// #Override
// protected List<String> doInBackground(Void... params) {
// try {
// return getDataFromApi();
// } catch (Exception e) {
// mLastError = e;
// cancel(true);
// return null;
// }
// }
//
//
// private List<String> getDataFromApi() throws IOException {
// String spreadsheetId = "196tcE1k5RuqTdGSBDpTFAI5h3m_dwXR875Q3csmi4ko";
// String range = "A1:X1";
//
// List<String> results = new ArrayList<String>();
// ValueRange response = this.mService.spreadsheets().values()
// .get(spreadsheetId, range)
// .execute();
//
// List<List<Object>> values = response.getValues();
// if (values != null) {
// for (int i = 0; i < values.size(); i++) {
// results.add(values.get(i).get(0) + ", " + values.get(i).get(1));
// }
// }
// return results;
// }
#Override
protected List<String> doInBackground(Void... voids) {
return null;
}
#Override
protected void onPreExecute() {
//mOutputText.setText("");
mProgress.show();
}
#Override
protected void onPostExecute(List<String> output) {
mProgress.hide();
if (output == null || output.size() == 0) {
Log.d(TAG, "\"No results returned.\": ");
} else {
output.add(0, "Data retrieved using the Google Sheets API:");
Log.d(TAG, TextUtils.join("\n", output));
Log.d("TagOutputPost", TextUtils.join("\n", output));
}
}
#Override
protected void onCancelled() {
mProgress.hide();
if (mLastError != null) {
if (mLastError instanceof GooglePlayServicesAvailabilityIOException) {
showGooglePlayServicesAvailabilityErrorDialog(
((GooglePlayServicesAvailabilityIOException) mLastError)
.getConnectionStatusCode());
} else if (mLastError instanceof UserRecoverableAuthIOException) {
startActivityForResult(
((UserRecoverableAuthIOException) mLastError).getIntent(),
REQUEST_AUTHORIZATION);
} else {
Log.d(TAG, "The following error occurred:\n"
+ mLastError.getMessage());
}
} else {
Log.d(TAG, "Request onCancelled: ");
}
}
}
#Override
protected void onActivityResult(
int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch (requestCode) {
case REQUEST_GOOGLE_PLAY_SERVICES:
if (resultCode != RESULT_OK) {
Log.d(TAG, "This app requires Google Play Services. Please install " +
"Google Play Services on your device and relaunch this app.");
} else {
getResultsFromApi();
}
break;
case REQUEST_ACCOUNT_PICKER:
if (resultCode == RESULT_OK && data != null &&
data.getExtras() != null) {
String accountName =
data.getStringExtra(AccountManager.KEY_ACCOUNT_NAME);
if (accountName != null) {
SharedPreferences settings =
getPreferences(Context.MODE_PRIVATE);
SharedPreferences.Editor editor = settings.edit();
editor.putString(PREF_ACCOUNT_NAME, accountName);
editor.apply();
mCredential.setSelectedAccountName(accountName);
getResultsFromApi();
}
}
break;
case REQUEST_AUTHORIZATION:
if (resultCode == RESULT_OK) {
getResultsFromApi();
}
break;
}
}
private boolean isGooglePlayServicesAvailable() {
GoogleApiAvailability apiAvailability =
GoogleApiAvailability.getInstance();
final int connectionStatusCode =
apiAvailability.isGooglePlayServicesAvailable(this);
return connectionStatusCode == ConnectionResult.SUCCESS;
}
private void acquireGooglePlayServices() {
GoogleApiAvailability apiAvailability =
GoogleApiAvailability.getInstance();
final int connectionStatusCode =
apiAvailability.isGooglePlayServicesAvailable(this);
if (apiAvailability.isUserResolvableError(connectionStatusCode)) {
showGooglePlayServicesAvailabilityErrorDialog(connectionStatusCode);
}
}
void showGooglePlayServicesAvailabilityErrorDialog(
final int connectionStatusCode) {
GoogleApiAvailability apiAvailability = GoogleApiAvailability.getInstance();
Dialog dialog = apiAvailability.getErrorDialog(
ConfirmSurvey.this,
connectionStatusCode,
REQUEST_GOOGLE_PLAY_SERVICES);
dialog.show();
}
#Override
public void onPermissionsGranted(int requestCode, List<String> perms) {
}
#Override
public void onPermissionsDenied(int requestCode, List<String> perms) {
}
I have the following Java code which downloads an image from an URL.
I can see the image downloaded in the folder, but the image does not appear in gallery. Only if I restart phone, Samsung S7 with android 7, I can see images in gallery. What can I do to have the images in gallery in real time after I downloaded them?
public class DetailsImgActivity extends AppCompatActivity {
private static final String TAG = "DetailsImgActivity";
private ImageView imageViewPoze;
private Button buttonDownload;
private static final int PERMISSION_REQUEST_CODE = 1;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_details_img);
if (ContextCompat.checkSelfPermission(this,
android.Manifest.permission.WRITE_EXTERNAL_STORAGE) !=
PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, new String[]{android.Manifest.permission.WRITE_EXTERNAL_STORAGE}, PERMISSION_REQUEST_CODE);
}
// image url stored in imageID
final String imageId = getIntent().getStringExtra("ImageId");
imageViewPoze = findViewById(R.id.imageViewPozeC);
Picasso.get().load(imageId).into(imageViewPoze);
buttonDownload = findViewById(R.id.btn_Download_Img);
buttonDownload.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
downloadFile(imageId);
}
});
}
private void downloadFile(String url) {
Retrofit.Builder builder = new Retrofit.Builder().baseUrl("https://firebasestorage.blabla.com/");
Retrofit retrofit = builder.build();
FileDownloadClient fileDownloadClient = retrofit.create(FileDownloadClient.class);
Call<ResponseBody> call = fileDownloadClient.downloadFile(url);
call.enqueue(new Callback<ResponseBody>() {
#Override
public void onResponse(Call<ResponseBody> call, final Response<ResponseBody> response) {
// if (response.isSuccess()) {
Log.d(TAG, "server contacted and has file");
new AsyncTask<Void, Void, Void>() {
#Override
protected Void doInBackground(Void... voids) {
boolean writtenToDisk = writeResponseBodyToDisk(response.body());
return null;
}
}.execute();
//after the image has been downloaded -refresh gallery
**Toast.makeText(getApplicationContext(), "File downloaded with success!", Toast.LENGTH_LONG).show();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT)
{
Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
File f = new File("file://"+ Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES));
Uri contentUri = Uri.fromFile(f);
mediaScanIntent.setData(contentUri);
sendBroadcast(mediaScanIntent);
}
else
{
sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED, Uri.parse("file://" + Environment.getExternalStorageDirectory())));
}**
}
#Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
Log.e(TAG, "error");
}
});
}
private boolean writeResponseBodyToDisk(ResponseBody body) {
try {
String folder_main = Constants.dirName;
File f = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM), folder_main);
if (!f.exists()) {
f.mkdirs();
}
// todo change the file location/name according to your needs
File futureStudioIconFile = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM+"/"+ Constants.dirName)
+ File.separator + UUID.randomUUID()+".jpg");
InputStream inputStream = null;
OutputStream outputStream = null;
try {
byte[] fileReader = new byte[4096];
long fileSize = body.contentLength();
long fileSizeDownloaded = 0;
inputStream = body.byteStream();
outputStream = new FileOutputStream(futureStudioIconFile);
while (true) {
int read = inputStream.read(fileReader);
if (read == -1) {
break;
}
outputStream.write(fileReader, 0, read);
fileSizeDownloaded += read;
Log.d(TAG, "file download: " + fileSizeDownloaded + " of " + fileSize);
}
outputStream.flush();
return true;
} catch (IOException e) {
return false;
} finally {
if (inputStream != null) {
inputStream.close();
}
if (outputStream != null) {
outputStream.close();
}
}
} catch (IOException e) {
return false;
}
}
}
I used the follwing code, but If I don't reboot phone, I can't see the picture in gallery.
**Toast.makeText(getApplicationContext(), "File downloaded with success!", Toast.LENGTH_LONG).show();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT)
{
Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
File f = new File("file://"+ Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES));
Uri contentUri = Uri.fromFile(f);
mediaScanIntent.setData(contentUri);
sendBroadcast(mediaScanIntent);
}
else
{
sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED, Uri.parse("file://" + Environment.getExternalStorageDirectory())));
}**
First, Thank you very much for looking at this!
I've been handed an app someone wrote before Marshmallow. I've fixed the Theme and SSL issues that came with Nougat but I'm having a heck of a time with Write to External Storage Permission or something associated. Debug is lacking or I'm not using it properly. This app creates a file onto the device and adds the ssl cert and login info in a folder called My Documents.
When I open the app it say network timeout right away. That message is from LoginActivity.java . I click ok then I get the Android pop up asking to allow permissions. I allow it. After that I put in the username and password and click login. It instantly gives the network timeout message from LoginActivity.java. LoginActivity.java is the Main Activity. If I click ok it's back to the login screen. All permissions are in the Android Manifest as well.
Maybe it's not from permissions but it works fine in version 22. I've worked on this 12 hours today and thought if you guys could help that'd be great. I'm a network engineer dabbling in Java so please excuse my question if it's "ugly".
I tried to find a line by line debug like I've done with phonegap but wasn't successful.
My Apps Main Activity LoginActivity.java and associated activity is LoginScreen.java and shown below.
LoginActivity.java
public class LoginActivity extends Activity {
private String userName = "";
private static final int PERMS_REQUEST_CODE = 123;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.blackactivity);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
new SSLHandler().execute();
if(Variables.testing)
{
}
if (hasPermissions()){
// our app has permissions.
try {
attemptLogin();
} catch (Exception e) {
GUI.oneOptionDialog(this, e.toString(), "OK", false);
e.printStackTrace();
}
}
else {
//our app doesn't have permissions, So i m requesting permissions.
requestPerms();
}
}
//Begin Permission Methods
#SuppressLint("WrongConstant")
private boolean hasPermissions(){
int res = 0;
//string array of permissions,
String[] permissions = new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE};
for (String perms : permissions){
res = checkCallingOrSelfPermission(perms);
if (!(res == PackageManager.PERMISSION_GRANTED)){
return false;
}
}
return true;
}
private void requestPerms(){
String[] permissions = new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE};
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M){
requestPermissions(permissions,PERMS_REQUEST_CODE);
}
}
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
boolean allowed = true;
switch (requestCode){
case PERMS_REQUEST_CODE:
for (int res : grantResults){
// if user granted all permissions.
allowed = allowed && (res == PackageManager.PERMISSION_GRANTED);
}
break;
default:
// if user not granted permissions.
allowed = false;
break;
}
if (allowed){
//user granted all permissions we can perform our task.
try {
attemptLogin();
} catch (Exception e) {
GUI.oneOptionDialog(this, e.toString(), "OK", false);
e.printStackTrace();
}
}
else {
// we will give warning to user that they haven't granted permissions.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (shouldShowRequestPermissionRationale(Manifest.permission.WRITE_EXTERNAL_STORAGE)){
Toast.makeText(this, "Storage Permissions denied.", Toast.LENGTH_SHORT).show();
}
}
}
}
//End Permission Methods
private void attemptLogin() throws IOException {
String filepath = Variables.fileFolder + "/login.txt";
File tempFile = new File(filepath);
if (!tempFile.exists()) {
startActivity(new Intent(LoginActivity.this, LoginScreen.class));
finish();
}
String username = "";
String passwordHash = "";
String salt = "";
boolean fileExists = false;
BufferedReader reader = null;
FileInputStream fileInputStream = null;
try {
fileInputStream = new FileInputStream(new File(filepath));
InputStreamReader inputStreamReader = new InputStreamReader(
fileInputStream);
reader = new BufferedReader(inputStreamReader);
username = reader.readLine();
passwordHash = reader.readLine();
salt = reader.readLine();
reader.close();
userName = username;
fileInputStream.close();
} catch (Exception e) {
startActivity(new Intent(LoginActivity.this, LoginScreen.class));
finish();
}
fileExists = true;
if (fileExists) {
try {
LoginTask login = new LoginTask();
login.execute(username, passwordHash, salt);
} catch (Exception e) {
}
}
}
private class LoginTask extends AsyncTask<String, Void, Boolean> {
Boolean success = false;
Boolean timedOut = false;
ProgressDialog mProgressDialog;
#Override
protected void onPostExecute(Boolean result) {
try {
mProgressDialog.dismiss();
} catch (Exception e) {
}
if (timedOut) {
AlertDialog.Builder builder = new AlertDialog.Builder(
LoginActivity.this);
builder.setMessage("Network Timed Out").setTitle("Notice");
builder.setPositiveButton("OK",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
dialog.dismiss();
startActivity(new Intent(LoginActivity.this,
LoginScreen.class));
finish();
}
});
AlertDialog dialog = builder.create();
dialog.show();
} else {
if (result) {
Variables.storeTechName(userName, LoginActivity.this);
Variables.assignTechName();
startActivity(new Intent(LoginActivity.this,
MainActivity.class));
finish();
} else {
startActivity(new Intent(LoginActivity.this,
LoginScreen.class));
finish();
}
}
}
#Override
protected void onPreExecute() {
mProgressDialog = ProgressDialog.show(LoginActivity.this,
"Loading...", "Logging you in...");
mProgressDialog.getWindow().setGravity(Gravity.BOTTOM);
}
#Override
protected Boolean doInBackground(String... params) {
try {
URL json = new URL(Variables.urlPrefix + "/Login.svc/input?a="
+ params[0] + "&b=" + params[1] + "&c=" + params[2]);
HttpsURLConnection jc = (HttpsURLConnection) json
.openConnection();
jc.setConnectTimeout(Variables.timeoutTimeLimit);
jc.setSSLSocketFactory(Variables.context.getSocketFactory());
InputStreamReader input = new InputStreamReader(
jc.getInputStream());
BufferedReader reader = new BufferedReader(input);
String line = reader.readLine();
JSONObject jsonResponse = new JSONObject(line);
success = jsonResponse.getBoolean("LoginMethodResult");
jc.disconnect();
reader.close();
} catch (Exception e) {
System.out.println(e.toString());
timedOut = true;
}
return success;
}
}
#Override
protected void onPause() {
super.onPause();
}
}
LoginScreen.java
public class LoginScreen extends Activity {
private String userName;
private static final int PERMS_REQUEST_CODE = 123;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.loginscreen);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
if (!SSLHandler.loaded) {
new SSLHandler().execute();
}
// Creates login and name files and attempts to log in
Button createButton = (Button) findViewById(R.id.createbutton);
createButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
if (((EditText) findViewById(R.id.usernamefield)).getText()
.toString().isEmpty()
|| ((EditText) findViewById(R.id.passwordfield))
.getText().toString().isEmpty()) {
GUI.oneOptionDialog(LoginScreen.this,
"Missing field entries", "OK", false);
} else {
createLoginFile();
((EditText) findViewById(R.id.usernamefield)).setText("");
((EditText) findViewById(R.id.passwordfield)).setText("");
attemptLogin();
}
}
});
}
#SuppressLint("WrongConstant")
private boolean hasPermissions(){
int res = 0;
//string array of permissions,
String[] permissions = new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE};
for (String perms : permissions){
res = checkCallingOrSelfPermission(perms);
if (!(res == PackageManager.PERMISSION_GRANTED)){
return false;
}
}
return true;
}
private void requestPerms(){
String[] permissions = new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE};
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M){
requestPermissions(permissions,PERMS_REQUEST_CODE);
}
}
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
boolean allowed = true;
switch (requestCode){
case PERMS_REQUEST_CODE:
for (int res : grantResults){
// if user granted all permissions.
allowed = allowed && (res == PackageManager.PERMISSION_GRANTED);
}
break;
default:
// if user not granted permissions.
allowed = false;
break;
}
if (allowed){
//user granted all permissions we can perform our task.
createFiles();
}
else {
// we will give warning to user that they haven't granted permissions.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (shouldShowRequestPermissionRationale(Manifest.permission.WRITE_EXTERNAL_STORAGE)){
Toast.makeText(this, "Storage Permissions denied.", Toast.LENGTH_SHORT).show();
}
}
}
}
private void createFiles() {
}
private void attemptLogin() {
String username = "";
String passwordHash = "";
String salt = "";
boolean fileExists = false;
try {
String filepath = Variables.fileFolder + "/login.txt";
FileInputStream fileInputStream = new FileInputStream(new File(
filepath));
InputStreamReader inputStreamReader = new InputStreamReader(
fileInputStream);
BufferedReader reader = new BufferedReader(inputStreamReader);
username = reader.readLine();
passwordHash = reader.readLine();
salt = reader.readLine();
reader.close();
userName = username;
fileInputStream.close();
fileExists = true;
}
catch (Exception e) {
GUI.oneOptionDialog(LoginScreen.this,
"Login file does not exist. Please enter login info.",
"OK", false);
}
if (fileExists) {
try {
LoginTask login = new LoginTask();
login.execute(username, passwordHash, salt);
} catch (Exception e) {
}
}
}
private class LoginTask extends AsyncTask<String, Void, Boolean> {
Boolean timedOut = false;
Boolean success = false;
ProgressDialog mProgressDialog;
#Override
protected void onPostExecute(Boolean result) {
try {
mProgressDialog.dismiss();
} catch (Exception e) {
}
if (timedOut) {
GUI.oneOptionDialog(LoginScreen.this, "Network Timed Out",
"OK", false);
} else {
if (result) {
Variables.storeTechName(userName, LoginScreen.this);
Variables.assignTechName();
startActivity(new Intent(LoginScreen.this,
MainActivity.class));
finish();
} else {
GUI.oneOptionDialog(LoginScreen.this,
"Login Failed. Please try again.", "OK", false);
}
}
}
#Override
protected void onPreExecute() {
mProgressDialog = ProgressDialog.show(LoginScreen.this,
"Loading...", "Logging you in...");
}
#Override
protected Boolean doInBackground(String... params) {
try {
URL json = new URL(Variables.urlPrefix + "/Login.svc/input?a="
+ params[0] + "&b=" + params[1] + "&c=" + params[2]);
HttpsURLConnection jc = (HttpsURLConnection) json
.openConnection();
jc.setConnectTimeout(Variables.timeoutTimeLimit);
jc.setSSLSocketFactory(Variables.context.getSocketFactory());
jc.setConnectTimeout(Variables.timeoutTimeLimit);
InputStreamReader input = new InputStreamReader(
jc.getInputStream());
BufferedReader reader = new BufferedReader(input);
String line = reader.readLine();
JSONObject jsonResponse = new JSONObject(line);
success = jsonResponse.getBoolean("LoginMethodResult");
jc.disconnect();
reader.close();
} catch (Exception e) {
timedOut = true;
}
return success;
}
}
private void createLoginFile() {
try {
File dir = new File(Variables.fileFolder);
if (!dir.isDirectory()) {
dir.mkdirs();
}
String filepath = Variables.fileFolder + "/Login.txt";
String username = ((EditText) findViewById(R.id.usernamefield))
.getText().toString();
String password = ((EditText) findViewById(R.id.passwordfield))
.getText().toString();
String salt = new RandomString(20).nextString();
String passwordHash = Variables.sha256(password + salt);
PrintWriter writer = new PrintWriter(filepath, "UTF-8");
writer.println(username);
writer.println(passwordHash);
writer.println(salt);
writer.close();
} catch (Exception e) {
GUI.oneOptionDialog(LoginScreen.this, e.toString(), "OK", false);
}
}
#Override
protected void onPause() {
super.onPause();
}
}
Hi I am making a chat application however when I try to update the view with the received string I get an CalledFromWrongThreadException, however it worked earlier, and my understanding of the handler is that it is created exactly for calls from another thread.
public class ChatActivity extends ActionBarActivity {
ServerSocket serverSocket;
Thread listenThread;
Thread sendThread;
Socket socket = null;
String strIP = "";
volatile String error;
final static int port = 6000;
TextView chatView;
TextView errorView;
volatile static String rcv = null;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_chat);
if (savedInstanceState == null) {
getSupportFragmentManager().beginTransaction()
.add(R.id.container, new PlaceholderFragment()).commit();
}
if (socket == null) {
try {
this.listenThread = new Thread(new Listener());
this.listenThread.start();
} catch (Exception e) {
}
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.chat, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
} else if (id == R.id.action_connectIP) {
Intent intent = new Intent(this, ConnectActivity.class);
startActivityForResult(intent, 1);
}
return super.onOptionsItemSelected(item);
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode == 1) {
if (requestCode == 1) {
if (data.hasExtra("IP"))
strIP = data.getExtras().getString("IP");
Toast.makeText(this, strIP, Toast.LENGTH_LONG).show();
// luk for at forhindre flere i at forbinde
try {
serverSocket.close();
} catch (IOException e) {
error = e.toString();
Message message = new Message();
message.what = -1;
UpdateHandler.sendMessage(message); }
}
}
}
#Override
protected void onStop() {
super.onStop();
if (listenThread != null)
if (listenThread.isAlive())
try {
serverSocket.close();
} catch (IOException e) {
error = e.toString();
Message message = new Message();
message.what = -1;
UpdateHandler.sendMessage(message);
}
listenThread.interrupt();
if (sendThread != null)
if (sendThread.isAlive())
sendThread.interrupt();
}
Handler UpdateHandler = new Handler() {
public void handleMessage(Message msg) {
this.obtainMessage();
switch (msg.toString()) {
case "0":
// TODO: afbryd forbindelsen
break;
case "-1":
insertError();
break;
default:
InsertChat();
}
}
};
void ThreadHandler() {
}
void InsertChat() {
if(chatView != null)
chatView.setText(rcv);
else
{
chatView = (TextView) findViewById(R.id.txtViewChat);
chatView.setText(rcv);
}
}
void insertError()
{
errorView = (TextView) findViewById(R.id.viewFejl);
errorView.setText(error);
}
public void SendChat(View view) {
// gør det hele asynkront og send beskeder i en tråd for sig.
if(sendThread == null)
sendThread = new Thread(new SendMessage());
if (!sendThread.isAlive()) {
this.sendThread = new Thread(new SendMessage());
this.sendThread.start();
}
}
/**
* A placeholder fragment containing a simple view.
*/
public static class PlaceholderFragment extends Fragment {
public PlaceholderFragment() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_chat, container,
false);
return rootView;
}
}
class Listener implements Runnable {
boolean shouldRun = true;
#Override
public void run() {
Looper.prepare();
// Looper.loop();
BufferedReader reader = null;
if (socket == null) {
try {
serverSocket = new ServerSocket(port);
} catch (IOException e) {
e.printStackTrace();
}
}
Message message = new Message();
rcv = "debug1";
UpdateHandler.sendMessage(message);
try {
if(strIP != "")
socket = new Socket(strIP, port);
else if (socket == null)
socket = serverSocket.accept();
Toast.makeText( getApplicationContext(), socket.getInetAddress().toString()+ " er forbundet", Toast.LENGTH_LONG).show();
while (!Thread.currentThread().isInterrupted() && shouldRun) {
reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
rcv = reader.readLine();
if(rcv == null) //er forbindelsen forsvundet?
shouldRun = false;
else
{
message.what = 0;
UpdateHandler.dispatchMessage(Message.obtain());
}
}
} catch (Exception e) {
error = e.toString();
message.what = -1;
UpdateHandler.dispatchMessage(message);
if(e != null)
e.printStackTrace();
}
try {
if (reader != null)
{
reader.close();
socket.close();
socket = null;
serverSocket.close();
}
} catch (IOException e) {
error = e.toString();
message.what = -1;
UpdateHandler.dispatchMessage(message);
if(e != null)
e.printStackTrace();
}
//Toast.makeText(getApplicationContext(), "lukker", Toast.LENGTH_LONG).show();
}
}
class SendMessage implements Runnable {
#Override
public void run() {
Looper.prepare();
try {
EditText textBox = (EditText) findViewById(R.id.txtChat);
PrintWriter writer = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())));
writer.println(textBox.getText().toString());
writer.flush(); //send før bufferen er fuld
} catch (Exception e) {
e.printStackTrace();
Toast.makeText(getApplicationContext(), "fejl", Toast.LENGTH_LONG).show();
}
}
}
}
I can't figure out how else to update the UI since you can't run sockets on the UI thread.
So i have a registration Android app that in main activity creates a socket connection on create opensocket(). Everything runs perfectly on the first submit, the debugger out put looks great and it sends/recieves data back from my WPF app. Now It goes to a thanks activity which onclick leads back to my mainactivity. Now when i hit submit, it works fine, but is showing its hitting my socket methods twice (only inserts the records once on my WPF app) , and so on as many times i submit. I realize i'm not closing or reusing my socket connection correctly?! I've tried several things, but can't seem to get this to either reuse the same opensocket instance or can't just close and reopen on reload. I'm quite new to android and sockets all together, any help is greatly appreciated!
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
settingsCheck();
openSocket();
sett.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
launchSettings();
}
});
mainLogo.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
RefreshMain();
}
});
btn_register.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
tv_errors.setText("");
errorMsg = "";
nameCheck(et_lName.getText().toString(),et_fName.getText().toString());
emailCheck(et_email.getText().toString());
partnerCheck();
mobileCheck(et_mobile.getText().toString());
if (SocketHandler.SocketConnected){
if(errorMsg == ""){
//tv_errors.setText("");
if(checkForSD() == true){
sendRegistrantInfo(et_fName.getText() + "," + et_lName.getText() + "," + et_email.getText() + "," + et_mobile.getText() + "," + et_partEmail.getText() + "," + cb_terms1.isChecked() + "," + cb_terms2.isChecked() );
}
else{
tv_errors.setText("**Please insert an SD Card.");
}
}
else{
//tv_errors.setText(errorMsg);
}
}
else
{
connectionStatus.setText("Connection Error.");
tv_errors.setText("**Connection lost, please try again.");
//openSocket();
}
}
});
}
public void RefreshMain()
{
Intent intent = new Intent(this, MainActivity.class);
startActivity(intent);
}
public void launchLogin()
{
Intent intent = new Intent(this, LoginActivity.class);
startActivity(intent);
}//end launchLogin
public void launchSettings()
{
Intent intent = new Intent(this, SettingsActivity.class);
startActivity(intent);
}//end launchSettings
public void settingsCheck()
{
SharedPreferences settings = getSharedPreferences("prefs",MODE_PRIVATE);
String currentIP = settings.getString("IPSetting", "");
String currentPort = settings.getString("PORTSetting", "");
currentMem = settings.getString("SDSize", "");
if (currentIP == "" || currentPort == ""){
Intent myIntent = new Intent(this,SettingsActivity.class);
startActivity(myIntent);
}
}//end settingsCheck()
public void launchRingDialog(String id) {
final String idYo = id;
final ProgressDialog ringProgressDialog = ProgressDialog.show(MainActivity.this, "Formatting SD Card","Formatting SD Card, please wait this could take several minutes...", true);
new Thread(new Runnable() {
#Override
public void run() {
try {
fileToSD(idYo);
Thread.sleep(10000);
} catch (Exception e) {
}
ringProgressDialog.dismiss();
}
}).start();
}
public boolean checkForSD()
{
String root = "/storage/removable/sdcard1/";
double memInGigs = round(sizeMatters(root),2);
if(memInGigs >0){
return true;
}
else
{
return false;
}
}
private double sizeMatters(String path)
{
StatFs stat = new StatFs(path);
double availSize = (double)stat.getAvailableBlocks() * (double)stat.getBlockSize();
double ingigs = availSize/ 1073741824;
return ingigs;
}//end sizeMatters()
private void sendRegistrantInfo(String reg){
_sh.sendMessage(reg);
}
private void openSocket(){
_sh = new SocketHandler();
_sh.setSocketHandlerListener(this);
SharedPreferences settings = getSharedPreferences("prefs",MODE_PRIVATE);
String currentIP = settings.getString("IPSetting", "");
String currentPort = settings.getString("PORTSetting", "");
_sh.open(currentIP, currentPort);
}
#Override
protected void onPause() {
super.onPause();
}
#Override
protected void onResume() {
super.onResume();
}
#Override
public void onSocketConnected() {
Log.v(TAG, "onSocketConnected");
connectionStatus.setText("CONNECTED");
}
#Override
public void onSocketData(String msg) {
Log.v(TAG, "onSocketData - " + msg );
int usrID = Integer.parseInt(msg.trim());
if (msg != null & usrID > 0){
launchRingDialog(msg);
Intent intent = new Intent(this, ThanksActivity.class);
startActivity(intent);
}
else if(msg.trim().equals("-2") == true)
{
tv_errors.setText("**This email has already been registered for this event, please click Already Registered button to sign in.");
}
else{
tv_errors.setText("**Error, Please try submitting again.");
errorMsg = "-1";
}
}
#Override
public void onSocketDisconnected() {
Log.v(TAG, "onSocketDisconnected");
connectionStatus.setText("DISCONNECTED");
}
public class SocketHandler {
Socket sc;
public static boolean SocketConnected = false;
private static ClientThread cThread;
public String prefsFile = "prefs";
public String port = "8888";
public String ip = "192.168.1.4";
private String TAG = "SocketHandler";
protected SocketHandlerListener socketHandlerListener;
public interface SocketHandlerListener{
public void onSocketConnected();
public void onSocketData(String msg);
public void onSocketDisconnected();
}
public SocketHandler(){
}
public void setSocketHandlerListener(SocketHandlerListener shl){
socketHandlerListener = shl;
}
public void open(String ip, String port){
this.ip = ip;
this.port = port;
cThread = new ClientThread();
try{
cThread.start();
}catch (Exception ex){
Log.v(TAG, "Error connecting to socket");
}
}
public void close(){
if (cThread != null){
if (cThread.socket != null){
try {
cThread.socket.close();
} catch (Exception e) {
Log.v(TAG, "Error closing socket");
}
cThread.socket = null;
}
}
}
public void sendMessage(String msg){
cThread.sendMessage(msg);
}
public void messageRecieved(String msg){
dispatchSocketData(msg);
}
private void dispatchSocketConnected(){
if (socketHandlerListener != null){
socketHandlerListener.onSocketConnected();
}
}
private void dispatchSocketDisconnected(){
if (socketHandlerListener != null){
socketHandlerListener.onSocketDisconnected();
}
}
private void dispatchSocketData(String msg){
if (socketHandlerListener != null){
socketHandlerListener.onSocketData(msg);
}
}
public class ClientThread extends Thread {
public Socket socket;
public void run() {
try {
InetAddress serverAddr = InetAddress.getByName(ip);
Log.v(TAG, "C: Connecting..." + ip + ":" + port);
socket = new Socket(serverAddr, Integer.parseInt(port));
socket.setSoTimeout(0);
socket.setKeepAlive(true);
SocketConnected = true;
handler.post(new Runnable() {
#Override
public void run() {
dispatchSocketConnected();
}
});
// BLOCKING THE THREAD
while (SocketConnected) {
InputStream in = socket.getInputStream();
byte[] buffer = new byte[4096];
int line = in.read(buffer, 0, 4096);
while (line != -1) {
byte[] tempdata = new byte[line];
System.arraycopy(buffer, 0, tempdata, 0, line);
final String data = new String(tempdata);
handler.post(new Runnable() {
#Override
public void run() {
messageRecieved(data);
SocketConnected = false;
}
});
line = in.read(buffer, 0, 4096);
}
// break;
}
socket.close();
Log.v("Socket", "C: Closed.");
handler.post(new Runnable() {
#Override
public void run() {
dispatchSocketDisconnected();
}
});
SocketConnected = false;
} catch (Exception e) {
Log.v("Socket", "C: Error", e);
handler.post(new Runnable() {
#Override
public void run() {
dispatchSocketDisconnected();
}
});
SocketConnected = false;
}
}
Handler handler = new Handler();
public void sendMessage(String msg){
if (socket != null){
if (socket.isConnected()){
PrintWriter out;
try {
out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())), false);
out.print(msg);
out.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
}