Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Android wear support #94

Open
wants to merge 18 commits into
base: master
Choose a base branch
from
Open
1 change: 1 addition & 0 deletions .idea/gradle.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion .idea/misc.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion .idea/modules.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 5 additions & 1 deletion app/app.iml
Original file line number Diff line number Diff line change
Expand Up @@ -111,5 +111,9 @@
<orderEntry type="library" exported="" name="core-3.3.0" level="project" />
<orderEntry type="library" exported="" name="picasso-2.5.2" level="project" />
<orderEntry type="library" exported="" name="gson-2.8.0" level="project" />
<orderEntry type="library" exported="" name="appcompat-v7-20.0.0" level="project" />
<orderEntry type="library" exported="" name="support-annotations-20.0.0" level="project" />
<orderEntry type="library" exported="" name="play-services-5.0.89" level="project" />
<orderEntry type="library" exported="" name="support-v4-20.0.0" level="project" />
</component>
</module>
</module>
5 changes: 5 additions & 0 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,13 @@ dependencies {
compile 'com.google.zxing:core:3.+'
compile 'com.google.code.gson:gson:2.+'
compile 'com.squareup.picasso:picasso:2.+'
wearApp project(':wear')
compile 'com.android.support:appcompat-v7:20.+'
compile 'com.google.android.gms:play-services-wearable:10.0.1'
}



android {
compileSdkVersion 25
buildToolsVersion '25.0.1'
Expand Down
13 changes: 13 additions & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,10 @@
android:label="@string/app_name"
android:theme="@style/AppTheme" >

<meta-data android:name="com.google.android.gms.version"
android:value="@integer/google_play_services_version" />


<activity
android:name=".AboutActivity"
android:theme="@android:style/Theme.Holo.Light.Dialog.NoActionBar"
Expand Down Expand Up @@ -96,5 +100,14 @@
<data android:scheme="otpauth" android:host="hotp" />
</intent-filter>
</activity>

<service android:name=".wear.TokenSyncService">
<intent-filter>
<action android:name="com.google.android.gms.wearable.DATA_CHANGED" />
<action android:name="com.google.android.gms.wearable.PEER_CONNECTED" />
<action android:name="com.google.android.gms.wearable.PEER_DISCONNECTED" />
</intent-filter>
</service>

</application>
</manifest>
131 changes: 131 additions & 0 deletions app/src/main/java/org/fedorahosted/freeotp/GPSActivity.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
package org.fedorahosted.freeotp;

import android.app.Activity;
import android.app.Dialog;
import android.app.DialogFragment;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentSender;
import android.os.Bundle;

import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GooglePlayServicesUtil;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.wearable.Wearable;

/**
* Created by Summers on 9/25/2014.
*/
public abstract class GPSActivity extends Activity implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener {

protected GoogleApiClient mGoogleApiClient;
// Request code to use when launching the resolution activity
private static final int REQUEST_RESOLVE_ERROR = 1001;
// Unique tag for the error dialog fragment
private static final String DIALOG_ERROR = "dialog_error";
// Bool to track whether the app is already resolving an error
private boolean mResolvingError = false;


@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(Wearable.API)
.build();

}

@Override
public void onConnected(Bundle bundle) {

}

@Override
public void onConnectionSuspended(int i) {

}

@Override
public void onConnectionFailed(ConnectionResult result) {
if (mResolvingError) {
// Already attempting to resolve an error.
return;
} else if (result.hasResolution()) {
try {
mResolvingError = true;
result.startResolutionForResult(this, REQUEST_RESOLVE_ERROR);
} catch (IntentSender.SendIntentException e) {
// There was an error with the resolution intent. Try again.
mGoogleApiClient.connect();
}
}
}

/* Creates a dialog for an error message */
private void showErrorDialog(int errorCode) {
// Create a fragment for the error dialog
ErrorDialogFragment dialogFragment = new ErrorDialogFragment();
// Pass the error that should be displayed
Bundle args = new Bundle();
args.putInt(DIALOG_ERROR, errorCode);
dialogFragment.setArguments(args);
dialogFragment.show(getFragmentManager(), "errordialog");
}

/* Called from ErrorDialogFragment when the dialog is dismissed. */
public void onDialogDismissed() {
mResolvingError = false;
}

/* A fragment to display an error dialog */
public static class ErrorDialogFragment extends DialogFragment {
public ErrorDialogFragment() { }

@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
// Get the error code and retrieve the appropriate dialog
int errorCode = this.getArguments().getInt(DIALOG_ERROR);
return GooglePlayServicesUtil.getErrorDialog(errorCode,
this.getActivity(), REQUEST_RESOLVE_ERROR);
}

@Override
public void onDismiss(DialogInterface dialog) {
((MainActivity)getActivity()).onDialogDismissed();
}
}

@Override
protected void onStart() {
super.onStart();

if (!mResolvingError) { // more about this later
mGoogleApiClient.connect();
}
}

@Override
protected void onStop() {
mGoogleApiClient.disconnect();
super.onStop();
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == REQUEST_RESOLVE_ERROR) {
mResolvingError = false;
if (resultCode == RESULT_OK) {
// Make sure the app is not already connected or attempting to connect
if (!mGoogleApiClient.isConnecting() &&
!mGoogleApiClient.isConnected()) {
mGoogleApiClient.connect();
}
}
}
}

}
46 changes: 41 additions & 5 deletions app/src/main/java/org/fedorahosted/freeotp/MainActivity.java
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,10 @@

package org.fedorahosted.freeotp;

import org.fedorahosted.freeotp.add.AddActivity;
import org.fedorahosted.freeotp.add.ScanActivity;

import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.database.DataSetObserver;
import android.net.Uri;
import android.os.Bundle;
Expand All @@ -51,10 +50,20 @@
import android.view.WindowManager.LayoutParams;
import android.widget.GridView;

public class MainActivity extends Activity implements OnMenuItemClickListener {
import org.fedorahosted.freeotp.add.AddActivity;
import org.fedorahosted.freeotp.add.ScanActivity;

public class MainActivity extends GPSActivity implements OnMenuItemClickListener {
private TokenAdapter mTokenAdapter;
private DataSetObserver mDataSetObserver;

private BroadcastReceiver tokenUpdateReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
tokensUpdated();
}
};

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Expand All @@ -78,17 +87,24 @@ public void onChanged() {
}
};
mTokenAdapter.registerDataSetObserver(mDataSetObserver);

}

@Override
protected void onResume() {
super.onResume();
registerReceiver(tokenUpdateReceiver, IntentFilter.create("newData", "vnd.android.wear/token"));
mTokenAdapter.notifyDataSetChanged();
}

@Override
protected void onPause() {
super.onPause();
unregisterReceiver(tokenUpdateReceiver);
mTokenAdapter.notifyDataSetChanged();
}

protected void tokensUpdated() {
mTokenAdapter.notifyDataSetChanged();
}

Expand All @@ -98,6 +114,18 @@ protected void onDestroy() {
mTokenAdapter.unregisterDataSetObserver(mDataSetObserver);
}


@Override
public void onConnected(Bundle bundle) {
mTokenAdapter.setmGoogleClient(mGoogleApiClient);
}

@Override
public void onConnectionSuspended(int i) {
mTokenAdapter.setmGoogleClient(null);
}


@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
Expand Down Expand Up @@ -135,5 +163,13 @@ protected void onNewIntent(Intent intent) {
Uri uri = intent.getData();
if (uri != null)
TokenPersistence.addWithToast(this, uri.toString());
new TokenPersistence(getApplicationContext()).sync(mGoogleApiClient);
}

@Override
protected void onStop() {
mTokenAdapter.setmGoogleClient(null);
super.onStop();
}

}
16 changes: 16 additions & 0 deletions app/src/main/java/org/fedorahosted/freeotp/Token.java
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,10 @@ public static class TokenUriInvalidException extends Exception {
private static final long serialVersionUID = -1108624734612362345L;
}

public static enum WearTokenCategory {
VPN, WORK, GOOGLE, NONE
}

public static enum TokenType {
HOTP, TOTP
}
Expand All @@ -55,6 +59,7 @@ public static enum TokenType {
private int digits;
private long counter;
private int period;
private WearTokenCategory wearTokenCategory = WearTokenCategory.NONE;

private Token(Uri uri, boolean internal) throws TokenUriInvalidException {
if (!uri.getScheme().equals("otpauth"))
Expand Down Expand Up @@ -280,6 +285,17 @@ public Uri toUri() {
return builder.build();
}

public WearTokenCategory getWearTokenCategory() {
return wearTokenCategory;
}

public void setWearTokenCategory(WearTokenCategory wearTokenCategory) {
if (wearTokenCategory == null) {
throw new IllegalArgumentException("Wear token may not be null");
}
this.wearTokenCategory = wearTokenCategory;
}

@Override
public String toString() {
return toUri().toString();
Expand Down
Loading