mirror of
https://github.com/M66B/FairEmail.git
synced 2026-03-29 13:24:52 +02:00
Added downloading Outlook contacts
This commit is contained in:
@@ -54,6 +54,7 @@ import android.widget.CompoundButton;
|
||||
import android.widget.ImageButton;
|
||||
import android.widget.ScrollView;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
@@ -70,7 +71,31 @@ import androidx.lifecycle.Observer;
|
||||
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
|
||||
import androidx.preference.PreferenceManager;
|
||||
|
||||
import net.openid.appauth.AppAuthConfiguration;
|
||||
import net.openid.appauth.AuthState;
|
||||
import net.openid.appauth.AuthorizationException;
|
||||
import net.openid.appauth.AuthorizationRequest;
|
||||
import net.openid.appauth.AuthorizationResponse;
|
||||
import net.openid.appauth.AuthorizationService;
|
||||
import net.openid.appauth.AuthorizationServiceConfiguration;
|
||||
import net.openid.appauth.ClientAuthentication;
|
||||
import net.openid.appauth.ClientSecretPost;
|
||||
import net.openid.appauth.GrantTypeValues;
|
||||
import net.openid.appauth.NoClientAuthentication;
|
||||
import net.openid.appauth.ResponseTypeValues;
|
||||
import net.openid.appauth.TokenRequest;
|
||||
import net.openid.appauth.TokenResponse;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
public class FragmentSetup extends FragmentBase implements SharedPreferences.OnSharedPreferenceChangeListener {
|
||||
@@ -107,6 +132,7 @@ public class FragmentSetup extends FragmentBase implements SharedPreferences.OnS
|
||||
private Button btnPermissions;
|
||||
private TextView tvPermissionsWhy;
|
||||
private TextView tvImportContacts;
|
||||
private Button btnGraphContacts;
|
||||
|
||||
private TextView tvDozeDone;
|
||||
private Button btnDoze;
|
||||
@@ -146,6 +172,8 @@ public class FragmentSetup extends FragmentBase implements SharedPreferences.OnS
|
||||
|
||||
private boolean manual = false;
|
||||
|
||||
private static final String GRAPH_SCOPE_READ_CONTACTS = "https://graph.microsoft.com/Contacts.Read";
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
|
||||
@@ -195,6 +223,7 @@ public class FragmentSetup extends FragmentBase implements SharedPreferences.OnS
|
||||
btnPermissions = view.findViewById(R.id.btnPermissions);
|
||||
tvPermissionsWhy = view.findViewById(R.id.tvPermissionsWhy);
|
||||
tvImportContacts = view.findViewById(R.id.tvImportContacts);
|
||||
btnGraphContacts = view.findViewById(R.id.btnGraphContacts);
|
||||
|
||||
tvDozeDone = view.findViewById(R.id.tvDozeDone);
|
||||
btnDoze = view.findViewById(R.id.btnDoze);
|
||||
@@ -564,6 +593,20 @@ public class FragmentSetup extends FragmentBase implements SharedPreferences.OnS
|
||||
}
|
||||
});
|
||||
|
||||
btnGraphContacts.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
Bundle args = new Bundle();
|
||||
args.putInt("type", EntityAccount.TYPE_IMAP);
|
||||
args.putString("filter", "outlook");
|
||||
|
||||
FragmentDialogSelectAccount fragment = new FragmentDialogSelectAccount();
|
||||
fragment.setArguments(args);
|
||||
fragment.setTargetFragment(FragmentSetup.this, ActivitySetup.REQUEST_GRAPH_CONTACTS);
|
||||
fragment.show(getParentFragmentManager(), "account:contacts");
|
||||
}
|
||||
});
|
||||
|
||||
btnDoze.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
@SuppressLint("BatteryLife")
|
||||
@@ -1073,6 +1116,14 @@ public class FragmentSetup extends FragmentBase implements SharedPreferences.OnS
|
||||
if (resultCode == RESULT_OK && data != null)
|
||||
onDeleteAccount(data.getBundleExtra("args"));
|
||||
break;
|
||||
case ActivitySetup.REQUEST_GRAPH_CONTACTS:
|
||||
if (resultCode == RESULT_OK && data != null)
|
||||
handleImportGraphContacts(data.getBundleExtra("args"));
|
||||
break;
|
||||
case ActivitySetup.REQUEST_GRAPH_CONTACTS_OAUTH:
|
||||
if (resultCode == RESULT_OK && data != null)
|
||||
onHandleGraphContactsOAuth(data);
|
||||
break;
|
||||
}
|
||||
} catch (Throwable ex) {
|
||||
Log.e(ex);
|
||||
@@ -1213,6 +1264,132 @@ public class FragmentSetup extends FragmentBase implements SharedPreferences.OnS
|
||||
.show();
|
||||
}
|
||||
|
||||
private void handleImportGraphContacts(Bundle args) {
|
||||
try {
|
||||
final Context context = getContext();
|
||||
long account = args.getLong("account");
|
||||
String user = args.getString("user");
|
||||
EmailProvider provider = EmailProvider.getProvider(context, "outlookgraph");
|
||||
|
||||
AppAuthConfiguration appAuthConfig = new AppAuthConfiguration.Builder()
|
||||
.build();
|
||||
AuthorizationService authService = new AuthorizationService(context, appAuthConfig);
|
||||
|
||||
AuthorizationServiceConfiguration serviceConfig = new AuthorizationServiceConfiguration(
|
||||
Uri.parse(provider.graph.authorizationEndpoint),
|
||||
Uri.parse(provider.graph.tokenEndpoint));
|
||||
|
||||
AuthorizationRequest.Builder authRequestBuilder =
|
||||
new AuthorizationRequest.Builder(
|
||||
serviceConfig,
|
||||
provider.graph.clientId,
|
||||
ResponseTypeValues.CODE,
|
||||
Uri.parse(provider.graph.redirectUri))
|
||||
.setScopes(GRAPH_SCOPE_READ_CONTACTS)
|
||||
.setState(provider.id + ":" + account)
|
||||
.setLoginHint(user);
|
||||
|
||||
if (!TextUtils.isEmpty(provider.graph.prompt))
|
||||
authRequestBuilder.setPrompt(provider.graph.prompt);
|
||||
|
||||
Intent authIntent = authService.getAuthorizationRequestIntent(authRequestBuilder.build());
|
||||
Log.i("Graph/contacts intent=" + authIntent);
|
||||
startActivityForResult(authIntent, ActivitySetup.REQUEST_GRAPH_CONTACTS_OAUTH);
|
||||
} catch (Throwable ex) {
|
||||
Log.unexpectedError(getParentFragmentManager(), ex);
|
||||
}
|
||||
}
|
||||
|
||||
private void onHandleGraphContactsOAuth(@NonNull Intent data) {
|
||||
try {
|
||||
Log.i("Graph/contacts authorized");
|
||||
|
||||
AuthorizationResponse auth = AuthorizationResponse.fromIntent(data);
|
||||
if (auth == null) {
|
||||
AuthorizationException ex = AuthorizationException.fromIntent(data);
|
||||
if (ex == null)
|
||||
throw new IllegalArgumentException("No response data");
|
||||
else
|
||||
throw ex;
|
||||
}
|
||||
|
||||
final Context context = getContext();
|
||||
final EmailProvider provider = EmailProvider.getProvider(context, "outlookgraph");
|
||||
|
||||
AuthorizationService authService = new AuthorizationService(context);
|
||||
|
||||
ClientAuthentication clientAuth;
|
||||
if (provider.graph.clientSecret == null)
|
||||
clientAuth = NoClientAuthentication.INSTANCE;
|
||||
else
|
||||
clientAuth = new ClientSecretPost(provider.graph.clientSecret);
|
||||
|
||||
TokenRequest.Builder builder = new TokenRequest.Builder(
|
||||
auth.request.configuration,
|
||||
auth.request.clientId)
|
||||
.setGrantType(GrantTypeValues.AUTHORIZATION_CODE)
|
||||
.setRedirectUri(auth.request.redirectUri)
|
||||
.setCodeVerifier(auth.request.codeVerifier)
|
||||
.setAuthorizationCode(auth.authorizationCode)
|
||||
.setNonce(auth.request.nonce);
|
||||
|
||||
if (provider.graph.tokenScopes)
|
||||
builder.setScope(GRAPH_SCOPE_READ_CONTACTS);
|
||||
|
||||
authService.performTokenRequest(
|
||||
builder.build(),
|
||||
clientAuth,
|
||||
new AuthorizationService.TokenResponseCallback() {
|
||||
@Override
|
||||
public void onTokenRequestCompleted(TokenResponse access, AuthorizationException error) {
|
||||
try {
|
||||
if (error != null)
|
||||
throw error;
|
||||
|
||||
if (access == null || access.accessToken == null)
|
||||
throw new IllegalStateException("No access token");
|
||||
|
||||
Log.i("Graph/contacts got token");
|
||||
|
||||
int semi = auth.request.state.lastIndexOf(':');
|
||||
long account = Long.parseLong(auth.request.state.substring(semi + 1));
|
||||
|
||||
Bundle args = new Bundle();
|
||||
args.putLong("account", account);
|
||||
args.putString("accessToken", access.accessToken);
|
||||
|
||||
new SimpleTask<Void>() {
|
||||
@Override
|
||||
protected Void onExecute(Context context, Bundle args) throws Throwable {
|
||||
long account = args.getLong("account");
|
||||
String accessToken = args.getString("accessToken");
|
||||
|
||||
MicrosoftGraph.downloadContacts(context, account, accessToken);
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onExecuted(Bundle args, Void data) {
|
||||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
prefs.edit().putBoolean("suggest_sent", true).apply();
|
||||
ToastEx.makeText(context, R.string.title_completed, Toast.LENGTH_LONG).show();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onException(Bundle args, Throwable ex) {
|
||||
Log.unexpectedError(getParentFragmentManager(), ex);
|
||||
}
|
||||
}.execute(FragmentSetup.this, args, "graph:contacts");
|
||||
} catch (Throwable ex) {
|
||||
Log.unexpectedError(getParentFragmentManager(), ex);
|
||||
}
|
||||
}
|
||||
});
|
||||
} catch (Throwable ex) {
|
||||
Log.unexpectedError(getParentFragmentManager(), ex);
|
||||
}
|
||||
}
|
||||
|
||||
private ConnectivityManager.NetworkCallback networkCallback = new ConnectivityManager.NetworkCallback() {
|
||||
@Override
|
||||
public void onAvailable(Network network) {
|
||||
|
||||
Reference in New Issue
Block a user