I have a project, controlling a jetski from a far with a android application using Bluetooth.
I have made 2 files:
Here is the "Peripherique.java" (the Bluetooth thing):
package com.example.btjetski;
import androidx.appcompat.app.AppCompatActivity;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
import java.util.ArrayList;
import java.util.Set;
public class Peripherique extends AppCompatActivity {
Button btnPaired;
ListView devicelist;
private BluetoothAdapter myBluetooth;
private Set<BluetoothDevice> pairedDevices;
public static String EXTRA_ADDRESS = "device_address";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btnPaired = findViewById(R.id.button);
devicelist = findViewById(R.id.listView);
myBluetooth = BluetoothAdapter.getDefaultAdapter();
if (myBluetooth == null) {
Toast.makeText(getApplicationContext(), "Périphérique Bluetooth non disponible", Toast.LENGTH_LONG).show();
finish();
} else if (!myBluetooth.isEnabled()) {
Intent turnBTon = new
Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(turnBTon, 1);
}
btnPaired.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
list();
}
});
}
private void list() { // écouter les périphériques BT
pairedDevices = myBluetooth.getBondedDevices();
ArrayList list = new ArrayList();
if (pairedDevices.size() > 0) {
for (BluetoothDevice bt : pairedDevices) {
list.add(bt.getName() + "\n" + bt.getAddress());
}
} else {
Toast.makeText(getApplicationContext(), "Aucun des appareils trouvés", Toast.LENGTH_LONG).show();
}
ArrayAdapter adapter = new ArrayAdapter(this, android.R.layout.simple_list_item_1, list);
devicelist.setAdapter(adapter);
}
public void onItemClick(AdapterView<?> av, View v, int arg2, long arg3)
{
String info = ((TextView) v).getText().toString();
String address = info.substring(info.length() - 17);
Intent i = new Intent(Peripherique.this, jetControl.class);
i.putExtra(EXTRA_ADDRESS, address);
startActivity(i);
}
}
Here is jetControl.java
package com.example.btjetski;
import android.app.ProgressDialog;
import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothSocket;
import android.content.Intent;
import android.view.View;
import android.widget.Button;
import java.io.IOException;
import java.util.UUID;
public class jetControl extends AppCompatActivity {
Button buttonON1, buttonOFF1;
String address = null;
private ProgressDialog progress;
BluetoothAdapter myBluetooth = null;
BluetoothSocket btSocket = null;
private boolean isBtConnected = false;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Intent newint = getIntent();
address = newint.getStringExtra(Peripherique.EXTRA_ADDRESS); //recevoir l'adresse du périphérique BT
setContentView(R.layout.activity_jet_control);
//WIDGETS
Button buttonON1 = findViewById(R.id.buttonON1);
Button buttonOFF1 = findViewById(R.id.buttonOFF1);
setOnClickListener();
}
private void setOnClickListener() {
buttonON1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
AllumerJetski1();
}
});
buttonOFF1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
EteindreJetski1();
}
});
}
private void AllumerJetski1() {
if (btSocket != null) {
try {
btSocket.getOutputStream().write("A".toString().getBytes());
} catch (IOException e) {
}
}
}
private void EteindreJetski1() {
if (btSocket != null) {
try {
btSocket.getOutputStream().write("a".toString().getBytes());
} catch (IOException e) {
}
}
}
}
When the app starts, i can connect to my ESP32 but nothing happens, i should have an overlay that shows up with two buttons "ON/OFF" but nothing seems to work properly.
I thank you so much for your help.
I am trying to retrieve step counts from a smartwatch and push it to API. I was able to retrieve and push the data when I open the app. But once it is not activated, then it will not send any data. I am trying to use the android service to run the app in the background so that it will send the data continuously. I have given all the permissions and enabled them.
This is MainActivity.java
package com.example.stepcounter;
import androidx.appcompat.app.AppCompatActivity;
import android.content.Intent;
import android.os.Bundle;
public class MainActivity extends AppCompatActivity{
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
protected void onResume() {
super.onResume();
}
protected void onPause() {
super.onPause();
}
protected void onDestroy() {
super.onDestroy();
}
public void onPressStartService(View v){
Intent intent = new Intent(this, MyService.class);
startService(intent);
}
public void onPressStopService(View v){
stopService(new Intent(getApplicationContext(), MyService.class));
}
}
And this is MyService.java
package com.example.stepcounter;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.os.IBinder;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.widget.TextView;
import androidx.annotation.Nullable;
import com.android.volley.Request;
import com.android.volley.RequestQueue;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.JsonObjectRequest;
import com.android.volley.toolbox.Volley;
import org.json.JSONException;
import org.json.JSONObject;
public class MyService extends Service implements SensorEventListener {
private SensorManager mSensorManager;
private Sensor mSensor;
private String HelloData;
private TextView mTextView;
private boolean isSensorPresent;
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
mSensorManager = (SensorManager)this.getSystemService(Context.SENSOR_SERVICE);
if(mSensorManager.getDefaultSensor(Sensor.TYPE_HEART_RATE) != null) {
mSensor = mSensorManager.getDefaultSensor(69680);
isSensorPresent = true;
} else {
isSensorPresent = false;
}
mSensorManager.registerListener(this, mSensor, SensorManager.SENSOR_DELAY_NORMAL);
return START_STICKY;
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onSensorChanged(SensorEvent event) {
mTextView.setText("Heart Rate: " + String.valueOf(event.values[0]));
HelloData = (String) String.valueOf(event.values[0]);
if(!HelloData.contains("0.0")){
postDataUsingVolley(HelloData);
}
}
#Override
public void onAccuracyChanged(Sensor sensor, int i) {
}
private void postDataUsingVolley(String ranData) {
String url = "https://test.com";
RequestQueue queue = Volley.newRequestQueue(this);
JSONObject postData = new JSONObject();
try {
postData.put("data", ranData);
} catch (JSONException e) {
e.printStackTrace();
}
JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(Request.Method.POST, url, postData, new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
System.out.println(response);
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
error.printStackTrace();
}
});
queue.add(jsonObjectRequest);
}
}
I have also added the following in AndroidManifest.xml
<service
android:name=".MyService"
android:enabled="true"
android:exported="true"></service>
It works for 30 seconds, send the data and once the watch goes inactive, it stops sending data. Any idea what is wrong with this?
You need to unregister your Sensor during onPause:
#Override
protected void onPause() {
super.onPause();
sensorManager.unregisterListener(this);
}
Also, if you unregister, you need to use your boolean activityRunning.
package com.example.fitness;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.content.ContextCompat;
import androidx.biometric.BiometricPrompt;
import android.os.Bundle;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
import java.util.concurrent.Executor;
public class MainActivity extends AppCompatActivity {
Button auth_button;
TextView status;
private BiometricPrompt biometricPrompt;
private BiometricPrompt.PromptInfo promptInfo;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
auth_button = findViewById(R.id.btn2);
status = findViewById(R.id.status);
Executor executor = ContextCompat.getMainExecutor(this);
biometricPrompt = new BiometricPrompt(MainActivity.this, executor, new
BiometricPrompt.AuthenticationCallback() {
#Override
public void onAuthenticationError(int errorCode, #NonNull CharSequence errString) {
super.onAuthenticationError(errorCode, errString);
Toast.makeText(MainActivity.this,"Error:"+errString,
Toast.LENGTH_SHORT).show();
}
#Override
public void onAuthenticationSucceeded(#NonNull
BiometricPrompt.AuthenticationResult result) {
super.onAuthenticationSucceeded(result);
Toast.makeText(MainActivity.this,"Authorized", Toast.LENGTH_SHORT).show();
}
#Override
public void onAuthenticationFailed() {
super.onAuthenticationFailed();
Toast.makeText(MainActivity.this,"failed to authorize",
Toast.LENGTH_SHORT).show();
}
});
promptInfo = new BiometricPrompt.PromptInfo.Builder().setTitle("Biometric
Authorization").setSubtitle("login using Finger print")
.setNegativeButtonText("Cancel").build();
auth_button.setOnClickListener(v -> biometricPrompt.authenticate(promptInfo));
}
}
I want the function to go to the new layout if the authentication is successful.
But whenever I try using intent with looping statements the code breaks and goes in an infinite
loop.
How do I overcome this problem such that the code reaches the next layout like on successful authentication.
I am newbie to the android studio, with the help of the developer guide I created this exoplayer activity but it's not playing video instead it's showing an empty screen. I created a button in my MainActivity, when I click that button it should open this player activity and play my hls streaming. Please help
MY Player activity.java
package com.example.mystream;
import androidx.appcompat.app.AppCompatActivity;
import android.net.Uri;
import android.os.Bundle;
import android.view.WindowManager;
import com.google.android.exoplayer2.ExoPlayerFactory;
import com.google.android.exoplayer2.SimpleExoPlayer;
import com.google.android.exoplayer2.source.hls.HlsMediaSource;
import com.google.android.exoplayer2.ui.PlayerView;
import com.google.android.exoplayer2.upstream.DataSource;
import com.google.android.exoplayer2.upstream.DefaultHttpDataSourceFactory;
import com.google.android.exoplayer2.util.Util;
public class playlive extends AppCompatActivity {
private SimpleExoPlayer player;
private PlayerView playerView;
private Uri uri;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_playlive);
this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON, WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
try {
this.getSupportActionBar().hide();
} catch (Exception e) {
}
}
private void play() {
SimpleExoPlayer player = ExoPlayerFactory.newSimpleInstance(this);
playerView = findViewById(R.id.player_view);
playerView.setPlayer(player);
uri = Uri.parse("http://localhost:1935/live/mystream/index.m3u8");
DataSource.Factory dataSourceFactory =
new DefaultHttpDataSourceFactory(Util.getUserAgent(this, "app-name"));
// Create a HLS media source pointing to a playlist uri.
HlsMediaSource hlsMediaSource =
new HlsMediaSource.Factory(dataSourceFactory).createMediaSource(uri);
player.prepare(hlsMediaSource);
player.setPlayWhenReady(true);
}
public void onStart(){
super.onStart();
play();
}
public void onStop(){
super.onStop();
onBackPressed();
player.release();
}
public void onDestroy(){
super.onDestroy();
onBackPressed();
player.release();
}
}
My playlive .xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".playlive">
<com.google.android.exoplayer2.ui.PlayerView
android:id="#+id/exo_buffering"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:focusable="true"
app:resize_mode="fill"
/>
</androidx.constraintlayout.widget.ConstraintLayout>
Main activity
package com.example.mystream;
import androidx.appcompat.app.AppCompatActivity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.view.WindowManager;
import android.widget.Button;
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN);
try {
this.getSupportActionBar().hide();
}catch (Exception e){
}
Button button = findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent activity2Intent = new Intent(getApplicationContext(), playlive.class);
startActivity(activity2Intent);
}
});
}
}
The issue seems in these two line
HlsMediaSource hlsMediaSource =new HlsMediaSource.Factory(dataSourceFactory).createMediaSource(uri);
uri= Uri.parse("http://localhost:1935/live/mystream/index.m3u8");
You are trying to pass uri before initializing which is causing the issue.
try initializing before as below
uri= Uri.parse("http://localhost:1935/live/mystream/index.m3u8");
and then use it
HlsMediaSource hlsMediaSource =new HlsMediaSource.Factory(dataSourceFactory).createMediaSource(uri);
This should solve your issue.
Here is the detailed desc of your requirement.
Method to Check Net Connection
private boolean checkConnection(Context context)
{
final ConnectivityManager mConnMngr= (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
if (mConnMngr!= null) {
NetworkInfo mNetworkInfo = mConnMngr.getActiveNetworkInfo();
if (mNetworkInfo != null) {
if ((mNetworkInfo .getType() == ConnectivityManager.TYPE_WIFI) {
return true;
} else return mNetworkInfo.getType() == ConnectivityManager.TYPE_MOBILE;
}
}
return false;
}
Permissions
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
Usage
if (checkConnection(context)) {
play();
} else {
Toast.makeText(context,"No internet available!",Toast.LENGTH_LONG).show()
}
I am a newbie here and this project is my first android project.
I'm trying to display the device's call log on the FragmentCalls.java.
App crashes on the device even after I requesting run-time permission.
Actually, app crashes on launch. Please, help!
This is my error log.
java.lang.SecurityException: Permission Denial: opening provider com.android.providers.contacts.CallLogProvider from ProcessRecord{7d3e3e4 30945:package.name.google/u0a200} (pid=30945, uid=10200) requires android.permission.READ_CALL_LOG or android.permission.WRITE_CALL_LOG
at package.name.google.fragments.FragmentCalls.getCallLogs(FragmentCalls.java:68)
at package.name.google.fragments.FragmentCalls.onCreateView(FragmentCalls.java:46)
FragmentCalls.java
package package.name.google.fragments;
import android.Manifest;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.os.Bundle;
import android.provider.CallLog;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.ActivityCompat;
import android.support.v4.app.Fragment;
import android.support.v7.widget.DividerItemDecoration;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import site.mobilesocial.google.R;
import site.mobilesocial.google.adapters.CallsRvAdapter;
import site.mobilesocial.google.models.ModelCalls;
#SuppressWarnings("WeakerAccess,FieldCanBeLocal")
public class FragmentCalls extends Fragment {
private View v;
private RecyclerView recyclerView;
public FragmentCalls() {
}
#SuppressWarnings("UnnecessaryLocalVariable")
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, Bundle savedInstanceState) {
v = inflater.inflate(R.layout.frag_calls, container, false);
recyclerView = v.findViewById(R.id.rv_calls);
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getContext());
RecyclerView.LayoutManager layoutManager = linearLayoutManager;
recyclerView.setLayoutManager(layoutManager);
**/*This is line 46*/ CallsRvAdapter adapter = new CallsRvAdapter(getContext(), getCallLogs()); //This is line 46**
DividerItemDecoration dividerItemDecoration = new DividerItemDecoration(recyclerView.getContext(), linearLayoutManager.getOrientation());
recyclerView.setAdapter(adapter);
recyclerView.addItemDecoration(dividerItemDecoration);
recyclerView.setHasFixedSize(true);
return v;
}
#SuppressWarnings("LogNotTimber")
private List<ModelCalls> getCallLogs() {
List<ModelCalls> list = new ArrayList<>();
if (ActivityCompat.checkSelfPermission(getContext(), Manifest.permission.READ_CALL_LOG) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(getActivity(), new String[] {Manifest.permission.READ_CALL_LOG}, 1);
}
/*This is line 68*/ **Cursor cursor = getContext().getContentResolver().query(CallLog.Calls.CONTENT_URI, null, null, null, CallLog.Calls.DATE + " DESC");** //This is line 68
assert cursor != null;
int number = cursor.getColumnIndex(CallLog.Calls.NUMBER);
int date = cursor.getColumnIndex(CallLog.Calls.DATE);
// int info = cursor.getColumnIndex(CallLog.Calls.TYPE);
cursor.moveToNext();
while (cursor.moveToNext()) {
Date date1 = new Date(Long.valueOf(cursor.getString(date)));
list.add(new ModelCalls(cursor.getString(number), date1.toLocaleString()));// cursor.getString(info)));
Log.d("MiC:: ", cursor.getString(number));
}
return list;
}
}
MainActivity.java
package package.name.google;
import android.Manifest;
import android.app.ProgressDialog;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.Color;
import android.os.Handler;
import android.support.annotation.NonNull;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.Toolbar;
import android.view.Gravity;
import android.view.View;
import android.view.WindowManager;
import android.widget.Toast;
import com.mikepenz.fontawesome_typeface_library.FontAwesome;
import com.mikepenz.materialdrawer.AccountHeader;
import com.mikepenz.materialdrawer.AccountHeaderBuilder;
import com.mikepenz.materialdrawer.Drawer;
import com.mikepenz.materialdrawer.DrawerBuilder;
import com.mikepenz.materialdrawer.holder.BadgeStyle;
import com.mikepenz.materialdrawer.model.PrimaryDrawerItem;
import com.mikepenz.materialdrawer.model.ProfileDrawerItem;
import com.mikepenz.materialdrawer.model.SecondaryDrawerItem;
import com.mikepenz.materialdrawer.model.SectionDrawerItem;
import com.mikepenz.materialdrawer.model.interfaces.IDrawerItem;
import com.mikepenz.materialdrawer.model.interfaces.IProfile;
import java.util.HashMap;
import java.util.Objects;
import site.mobilesocial.google.adapters.ViewPagerAdapter;
import site.mobilesocial.google.fragments.FragmentCalls;
import site.mobilesocial.google.helper.DatabaseHandler;
import site.mobilesocial.google.helper.Functions;
import site.mobilesocial.google.helper.SessionManager;
#SuppressWarnings("FieldCanBeLocal")
public class MainActivity extends AppCompatActivity {
private static final String TAG = MainActivity.class.getSimpleName();
private SessionManager session;
private DatabaseHandler db;
private AccountHeader headerResult = null;
private Drawer result = null;
private Toast toast = null;
private ViewPager viewPager;
private ProgressDialog pDialog;
private HashMap<String,String> user = new HashMap<>();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
viewPager = findViewById(R.id.viewpager);
ViewPagerAdapter adapter = new ViewPagerAdapter(getSupportFragmentManager());
adapter.addFragment(new FragmentCalls(), "Calls");
viewPager.setAdapter(adapter);
// Progress dialog
pDialog = new ProgressDialog(this);
pDialog.setCancelable(false);
db = new DatabaseHandler(getApplicationContext());
user = db.getUserDetails();
// session manager
session = new SessionManager(getApplicationContext());
if (!session.isLoggedIn()) {
logoutUser();
}
// Hide Keyboard
getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);
Toolbar toolbar = findViewById(R.id.toolbar);
toolbar.setBackground(ContextCompat.getDrawable(getBaseContext(), R.color.md_black_1000));
// toolbar.setLogo(R.drawable.toolbarlogo);
setSupportActionBar(toolbar);
Objects.requireNonNull(getSupportActionBar()).setTitle(null);
createAccountHeader();
result = new DrawerBuilder(this)
.withToolbar(toolbar)
.withAccountHeader(headerResult)
.withTranslucentStatusBar(true)
.withActionBarDrawerToggle(true)
.withActionBarDrawerToggleAnimated(true)
.withInnerShadow(true)
.withSliderBackgroundColor(Color.WHITE)
.withActionBarDrawerToggle(true)
.withTranslucentNavigationBar(true)
.withOnDrawerListener(new Drawer.OnDrawerListener() {
#Override
public void onDrawerOpened(View drawerView) {
Functions.hideSoftKeyboard(MainActivity.this);
}
#Override
public void onDrawerClosed(View drawerView) {
}
#Override
public void onDrawerSlide(View drawerView, float slideOffset) {
}
})
.addDrawerItems(initDrawerItems())
.withSavedInstance(savedInstanceState)
.withDrawerGravity(Gravity.START)
.addStickyDrawerItems(new SecondaryDrawerItem().withIdentifier(7).withName(R.string.logout).withIcon(FontAwesome.Icon.faw_lock).withSelectable(false))
.withOnDrawerItemClickListener(new Drawer.OnDrawerItemClickListener() {
#Override
public boolean onItemClick(View view, int position, IDrawerItem drawerItem) {
if (drawerItem != null) {
switch ((int) drawerItem.getIdentifier()) {
case 7:
logoutUser();
}
}
return false;
}
})
.build();
result.getActionBarDrawerToggle().setDrawerIndicatorEnabled(true);
askPermissions();
}
private void askPermissions() {
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.READ_CALL_LOG)
!= PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this,new String[]{Manifest.permission.READ_CONTACTS}, 1);
ActivityCompat.requestPermissions(this,new String[]{Manifest.permission.READ_CALL_LOG}, 1);
} else {
finish();
}
}
private void createAccountHeader() {
user.get("name");
user.get("email");
headerResult = new AccountHeaderBuilder()
.withActivity(this)
.withTextColorRes(R.color.material_drawer_dark_header_selection_text)
.addProfiles(
new ProfileDrawerItem().withIdentifier(8).withName(user.get("name")).withEmail(user.get("email"))
)
.withOnAccountHeaderListener(new AccountHeader.OnAccountHeaderListener() {
#Override
public boolean onProfileChanged(View view, IProfile profile, boolean current) {
profileClick(profile);
return false;
}
})
.build();
}
private void profileClick(IProfile profile) {
switch ((int) profile.getIdentifier()) {
case 8:
toast = Toast.makeText(getApplicationContext(),
user.get("name"),
Toast.LENGTH_SHORT);
toast.setGravity(Gravity.CENTER, 0, 0);
toast.show();
break;
}
}
#NonNull
private IDrawerItem[] initDrawerItems() {
return new IDrawerItem[]{new PrimaryDrawerItem().withIdentifier(0).withName(R.string.drawer_item_home).withIcon(FontAwesome.Icon.faw_home),
new PrimaryDrawerItem().withIdentifier(1).withName("test").withIcon(FontAwesome.Icon.faw_user_plus).withSetSelected(true),
new PrimaryDrawerItem().withIdentifier(2).withName("test2").withIcon(FontAwesome.Icon.faw_eye).withBadge("19").withSelectable(false).withBadgeStyle(new BadgeStyle().withTextColor(Color.WHITE).withColorRes(R.color.md_red_700)),
new SectionDrawerItem().withIdentifier(3).withName("test3"),
new SecondaryDrawerItem().withIdentifier(4).withName("test4").withIcon(FontAwesome.Icon.faw_cogs).withSelectable(false),
new SecondaryDrawerItem().withIdentifier(5).withName("test5").withIcon(FontAwesome.Icon.faw_asterisk).withSelectable(false),
new SecondaryDrawerItem().withIdentifier(6).withName("test6").withIcon(FontAwesome.Icon.faw_question_circle).withSelectable(false)
};
}
#Override
public void onSaveInstanceState(Bundle outState) {
outState = result.saveInstanceState(outState);
super.onSaveInstanceState(outState);
}
boolean doubleBackToExitPressedOnce = false;
#Override
public void onBackPressed() {
if (result != null && result.isDrawerOpen()) {
result.closeDrawer();
} else {
if (doubleBackToExitPressedOnce)
super.onBackPressed();
this.doubleBackToExitPressedOnce = true;
Toast.makeText(this, "한번 더 누르면 종료됩니다", Toast.LENGTH_SHORT).show();
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
doubleBackToExitPressedOnce=false;
}
}, 2000);
}
}
private void logoutUser() {
session.setLogin(false);
// Launching the login activity
Functions logout = new Functions();
logout.logoutUser(getApplicationContext());
Intent intent = new Intent(MainActivity.this, LoginActivity.class);
startActivity(intent);
finish();
}
}
Result of permissions request is asynchronous. You should return the function after requesting the permissions and perform the required operations inside the method onRequestPermissionsResult.
if (ActivityCompat.checkSelfPermission(getContext(), Manifest.permission.READ_CALL_LOG) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(getActivity(), new String[] {Manifest.permission.READ_CALL_LOG}, 1);
return;
}
#Override
public void onRequestPermissionsResult(int requestCode, String[] permissions,
int[] grantResults) {
// check if permission has been granted and do your operations.
}
Also don't request permissions from a method which is supposed to return something. Make sure you already have permissions before accessing the call logs or other critical information.
You can find a lot of tutorials and documentations about run-time permissions online. The official one is here.
Add these permissions in manifest if target version is less then 23
<uses-permission android:name="android.permission.read_contacts" />
<uses-permission android:name="android.permission.read_phone_state" />
<uses-permission android:name="android.permission.GET_TASKS" />
<uses-permission android:name="android.permission.READ_CALL_LOG" />
also check manifest intent filter for launcher activity, it should be present
<intent-filter> <action android:name="android.intent.action.MAIN" /> </intent-filter>
I found a solution
Removed askPermission() from my MainActivity and changed FragmentCalls.java like this and this is worked
FragmentCalls.java
package site.mobilesocial.google.fragments;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.os.Bundle;
import android.provider.CallLog;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.ActivityCompat;
import android.support.v4.app.Fragment;
import android.support.v4.content.ContextCompat;
import android.support.v7.widget.DividerItemDecoration;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Toast;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import site.mobilesocial.google.R;
import site.mobilesocial.google.adapters.CallsRvAdapter;
import site.mobilesocial.google.models.ModelCalls;
import static android.Manifest.permission.READ_CALL_LOG;
#SuppressWarnings("WeakerAccess,FieldCanBeLocal")
public class FragmentCalls extends Fragment {
private View v;
private RecyclerView recyclerView;
private static final int REQUEST_PERMISSION_CONTACTS = 1;
public FragmentCalls() {
}
#SuppressWarnings("UnnecessaryLocalVariable")
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, Bundle savedInstanceState) {
v = inflater.inflate(R.layout.frag_calls, container, false);
recyclerView = v.findViewById(R.id.rv_calls);
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getContext());
RecyclerView.LayoutManager layoutManager = linearLayoutManager;
recyclerView.setLayoutManager(layoutManager);
if (ContextCompat.checkSelfPermission(getActivity(), READ_CALL_LOG) == PackageManager.PERMISSION_GRANTED) {
// We have access. Life is good.
CallsRvAdapter adapter = new CallsRvAdapter(getContext(), getCallLogs());
DividerItemDecoration dividerItemDecoration = new DividerItemDecoration(recyclerView.getContext(), linearLayoutManager.getOrientation());
recyclerView.setAdapter(adapter);
recyclerView.addItemDecoration(dividerItemDecoration);
recyclerView.setHasFixedSize(true);
} else if (ActivityCompat.shouldShowRequestPermissionRationale(getActivity(), READ_CALL_LOG)) {
// We've been denied once before. Explain why we need the permission, then ask again.
Toast.makeText(getContext(), "Permission is needed", Toast.LENGTH_SHORT).show();
requestPermissions(new String[]{READ_CALL_LOG}, REQUEST_PERMISSION_CONTACTS);
} else {
// We've never asked. Just do it.
requestPermissions(new String[]{READ_CALL_LOG}, REQUEST_PERMISSION_CONTACTS);
}
return v;
}
#Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
if (requestCode == REQUEST_PERMISSION_CONTACTS && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
CallsRvAdapter adapter = new CallsRvAdapter(getContext(), getCallLogs());
} else {
// We were not granted permission this time, so don't try to show the contact picker
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
}
#SuppressWarnings("LogNotTimber")
private List<ModelCalls> getCallLogs() {
List<ModelCalls> list = new ArrayList<>();
Cursor cursor = getContext().getContentResolver().query(CallLog.Calls.CONTENT_URI, null, null, null, CallLog.Calls.DATE + " DESC");
assert cursor != null;
int number = cursor.getColumnIndex(CallLog.Calls.NUMBER);
int date = cursor.getColumnIndex(CallLog.Calls.DATE);
// int info = cursor.getColumnIndex(CallLog.Calls.TYPE);
cursor.moveToNext();
while (cursor.moveToNext()) {
Date date1 = new Date(Long.valueOf(cursor.getString(date)));
list.add(new ModelCalls(cursor.getString(number), date1.toLocaleString()));// cursor.getString(info)));
Log.d("MiC:: ", cursor.getString(number));
}
return list;
}
}
Thats it thanks.
I would also suggest you to try out this library.
Dexter is an Android library that simplifies the process of requesting permissions at runtime.
https://github.com/Karumi/Dexter
Sample permission request:
Dexter.withActivity(this)
.withPermission(Manifest.permission.CAMERA)
.withListener(new PermissionListener() {
#Override public void onPermissionGranted(PermissionGrantedResponse response) {/* ... */}
#Override public void onPermissionDenied(PermissionDeniedResponse response) {/* ... */}
#Override public void onPermissionRationaleShouldBeShown(PermissionRequest permission, PermissionToken token) {/* ... */}
}).check();