diff --git a/kute-android-app/.idea/misc.xml b/kute-android-app/.idea/misc.xml index 7158618b..cc72de32 100644 --- a/kute-android-app/.idea/misc.xml +++ b/kute-android-app/.idea/misc.xml @@ -1,8 +1,5 @@ - - - - - - - - - - - - - - + diff --git a/kute-android-app/app/build.gradle b/kute-android-app/app/build.gradle index be480862..d1278e45 100644 --- a/kute-android-app/app/build.gradle +++ b/kute-android-app/app/build.gradle @@ -33,6 +33,7 @@ dependencies { androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', { exclude group: 'com.android.support', module: 'support-annotations' }) + def htextview_version = "0.1.2" @@ -47,6 +48,9 @@ dependencies { compile 'com.facebook.android:facebook-android-sdk:4.25.0' compile 'com.android.volley:volley:1.0.0' compile 'com.android.support:appcompat-v7:25.1.1' + compile "com.hanks:htextview-base:$htextview_version" // base library + compile "com.hanks:htextview-typer:$htextview_version" // optional + compile "com.hanks:htextview-line:$htextview_version" // optional compile 'com.android.support:design:25.1.1' compile 'de.hdodenhof:circleimageview:2.1.0' compile 'com.android.support.constraint:constraint-layout:1.0.2' diff --git a/kute-android-app/app/src/main/java/com/scorelab/kute/kute/Activity/RegisterActivity.java b/kute-android-app/app/src/main/java/com/scorelab/kute/kute/Activity/RegisterActivity.java index 1f474f7d..c567736a 100644 --- a/kute-android-app/app/src/main/java/com/scorelab/kute/kute/Activity/RegisterActivity.java +++ b/kute-android-app/app/src/main/java/com/scorelab/kute/kute/Activity/RegisterActivity.java @@ -4,13 +4,16 @@ import android.content.Intent; import android.content.SharedPreferences; import android.graphics.Bitmap; -import android.os.AsyncTask; +import android.net.Uri; import android.os.Bundle; +import android.os.CountDownTimer; +import android.os.Handler; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.support.v7.app.AppCompatActivity; import android.util.Log; import android.view.View; +import android.widget.Button; import android.widget.ImageView; import android.widget.Toast; @@ -42,10 +45,17 @@ import com.google.firebase.auth.FirebaseAuth; import com.google.firebase.auth.FirebaseUser; import com.google.firebase.auth.GoogleAuthProvider; +import com.hanks.htextview.line.LineTextView; +import com.hanks.htextview.typer.TyperTextView; +import com.scorelab.kute.kute.Library.TextureVideoView; import com.scorelab.kute.kute.R; import com.scorelab.kute.kute.SplashActivity; import com.scorelab.kute.kute.Util.ImageHandler; +import java.io.IOException; + +import static java.lang.Thread.sleep; + public class RegisterActivity extends AppCompatActivity implements GoogleApiClient.OnConnectionFailedListener, View.OnClickListener{ @@ -55,12 +65,16 @@ public class RegisterActivity extends AppCompatActivity implements private static final int RC_SIGN_IN = 9001; private SignInButton mSignInButton; + LoginButton loginButton; + TyperTextView lineTextView; + String animText = "Kute"; + CountDownTimer timer; private GoogleApiClient mGoogleApiClient; // Firebase instance variables private FirebaseAuth mFirebaseAuth; - + TextureVideoView videoview; // [START declare_auth] private FirebaseAuth mAuth; // [END declare_auth] @@ -68,15 +82,19 @@ public class RegisterActivity extends AppCompatActivity implements private FirebaseAuth.AuthStateListener mAuthListener; private CallbackManager mCallbackManager; //Facebook + Button inG, inFB; @Override public void onClick(View v) { switch (v.getId()) { - case R.id.login_with_google: + case R.id.btn_inG: signIn(); break; + case R.id.btn_inFB: + loginButton.performClick(); + break; } } @@ -150,7 +168,61 @@ protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); try { + setContentView(R.layout.testreg); + videoview = (TextureVideoView) findViewById(R.id.videoview); + Uri myUri = Uri.parse("android.resource://" + getPackageName() + "/" + R.raw.videoview_kute); + videoview.setDataSourceURI(this, myUri); + + videoview.setScaleType(TextureVideoView.ScaleType.CENTER_CROP); + videoview.setLooping(true); + videoview.play(); + lineTextView = (TyperTextView) findViewById(R.id.textView); + inG = (Button) findViewById(R.id.btn_inG); + inFB = (Button) findViewById(R.id.btn_inFB); + inG.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + signIn(); + } + }); + inFB.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + loginButton.performClick(); + } + }); + lineTextView.setSoundEffectsEnabled(false); + lineTextView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + ((TyperTextView)v).animateText(animText); + if (animText.equals("A Commute App for Sri Lanka")){ + animText = "Kute"; + } + else if (animText.equals("Kute")){ + animText = "A Commute App for Sri Lanka"; + } + } + }); + + + timer = new CountDownTimer(5000, 3000) { + + @Override + public void onTick(long millisUntilFinished) { + lineTextView.performClick(); + } + + @Override + public void onFinish() { + try{ + yourMethod(); + }catch(Exception e){ + Log.e("Error", "Error: " + e.toString()); + } + } + }.start(); // Assign fields mSignInButton = (SignInButton) findViewById(R.id.login_with_google); @@ -171,7 +243,6 @@ protected void onCreate(@Nullable Bundle savedInstanceState) { // Initialize FirebaseAuth mFirebaseAuth = FirebaseAuth.getInstance(); - //Facebook mAuth = FirebaseAuth.getInstance(); // [START auth_state_listener] @@ -205,7 +276,7 @@ public void onAuthStateChanged(@NonNull FirebaseAuth firebaseAuth) { }; mCallbackManager = CallbackManager.Factory.create(); - LoginButton loginButton = (LoginButton) findViewById(R.id.connectWithFbButton); + loginButton = (LoginButton) findViewById(R.id.connectWithFbButton); loginButton.setReadPermissions("email", "public_profile","user_friends"); loginButton.registerCallback(mCallbackManager, new FacebookCallback() { @@ -285,19 +356,33 @@ public void onError(FacebookException error) { rq= Volley.newRequestQueue(this); } + void yourMethod(){ + timer.start(); + } @Override protected void onStop() { super.onStop(); + videoview.stop(); if (mAuthListener != null) { mAuth.removeAuthStateListener(mAuthListener); } } + @Override + protected void onDestroy() { + super.onDestroy(); + videoview.stop(); + if (mAuthListener != null) { + mAuth.removeAuthStateListener(mAuthListener); + } + } + @Override protected void onStart() { super.onStart(); + mAuth.addAuthStateListener(mAuthListener); } diff --git a/kute-android-app/app/src/main/java/com/scorelab/kute/kute/Library/TextureVideoView.java b/kute-android-app/app/src/main/java/com/scorelab/kute/kute/Library/TextureVideoView.java new file mode 100644 index 00000000..34d10837 --- /dev/null +++ b/kute-android-app/app/src/main/java/com/scorelab/kute/kute/Library/TextureVideoView.java @@ -0,0 +1,453 @@ +package com.scorelab.kute.kute.Library; + +import android.content.Context; +import android.content.res.AssetFileDescriptor; +import android.graphics.Matrix; +import android.graphics.SurfaceTexture; +import android.media.MediaPlayer; +import android.net.Uri; +import android.util.AttributeSet; +import android.util.Log; +import android.view.Surface; +import android.view.TextureView; +import android.widget.FrameLayout; + +import java.io.IOException; + +/* + * The MIT License (MIT) + * + * Copyright (c) 2014 Danylyk Dmytro + * Copyright (c) 2014 Jacob Tabak + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +public class TextureVideoView extends FrameLayout implements TextureView.SurfaceTextureListener { + + // Indicate if logging is on + public static final boolean LOG_ON = true; + + // Log tag + private static final String TAG = TextureVideoView.class.getName(); + + private MediaPlayer mMediaPlayer; + + private float mVideoHeight; + private float mVideoWidth; + + private boolean mIsDataSourceSet; + private boolean mIsViewAvailable; + private boolean mIsVideoPrepared; + private boolean mIsPlayCalled; + + private ScaleType mScaleType; + private State mState; + private TextureView mTextureView; + + public enum ScaleType { + CENTER_CROP, TOP, BOTTOM + } + + public enum State { + UNINITIALIZED, PLAY, STOP, PAUSE, END + } + + public TextureVideoView(Context context) { + super(context); + if (!isInEditMode()) { + initView(); + } + } + + public TextureVideoView(Context context, AttributeSet attrs) { + super(context, attrs); + if (!isInEditMode()) { + initView(); + } + } + + public TextureVideoView(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + if (!isInEditMode()) { + initView(); + } + } + + private void initView() { + initPlayer(); + mTextureView = new TextureView(getContext()); + removeAllViews(); + addView(mTextureView); + setScaleType(ScaleType.CENTER_CROP); + mTextureView.setSurfaceTextureListener(this); + } + + public void setScaleType(ScaleType scaleType) { + mScaleType = scaleType; + } + + private void updateTextureViewSize() { + float viewWidth = getWidth(); + float viewHeight = getHeight(); + + float scaleX = 1.0f; + float scaleY = 1.0f; + + if (mVideoWidth >= viewWidth && mVideoHeight >= viewHeight) { + scaleX = mVideoWidth / viewWidth; + scaleY = mVideoHeight / viewHeight; + } else if (mVideoWidth <= viewWidth && mVideoHeight <= viewHeight) { + scaleY = viewWidth / mVideoWidth; + scaleX = viewHeight / mVideoHeight; + } else if (viewWidth >= mVideoWidth) { + scaleY = (viewWidth / mVideoWidth) / (viewHeight / mVideoHeight); + } else if (viewHeight >= mVideoHeight) { + scaleX = (viewHeight / mVideoHeight) / (viewWidth / mVideoWidth); + } + + // Calculate pivot points, in our case crop from center + int pivotPointX; + int pivotPointY; + + switch (mScaleType) { + case TOP: + pivotPointX = 0; + pivotPointY = 0; + break; + case BOTTOM: + pivotPointX = (int) (viewWidth); + pivotPointY = (int) (viewHeight); + break; + case CENTER_CROP: + pivotPointX = (int) (viewWidth / 2); + pivotPointY = (int) (viewHeight / 2); + break; + default: + pivotPointX = (int) (viewWidth / 2); + pivotPointY = (int) (viewHeight / 2); + break; + } + + Matrix matrix = new Matrix(); + matrix.setScale(scaleX, scaleY, pivotPointX, pivotPointY); + mTextureView.setTransform(matrix); + } + + private void initPlayer() { + if (mMediaPlayer == null) { + mMediaPlayer = new MediaPlayer(); + } else { + mMediaPlayer.reset(); + } + mIsVideoPrepared = false; + mIsPlayCalled = false; + mState = State.UNINITIALIZED; + } + + public boolean isPlaying() { + if (mMediaPlayer != null) { + return mMediaPlayer.isPlaying(); + } + return false; + } + /** + * @see android.media.MediaPlayer#setDataSource(String) + */ + public void setDataSourceURI(Context c, Uri u) { + initPlayer(); + + try { + mMediaPlayer.setDataSource(c,u); + mIsDataSourceSet = true; + prepare(); + } catch (IOException e) { + Log.d(TAG, e.getMessage()); + } + } + /** + * @see android.media.MediaPlayer#setDataSource(String) + */ + public void setDataSource(String path) { + initPlayer(); + + try { + mMediaPlayer.setDataSource(path); + mIsDataSourceSet = true; + prepare(); + } catch (IOException e) { + Log.d(TAG, e.getMessage()); + } + } + /** + * @see android.media.MediaPlayer#setDataSource(android.content.Context, android.net.Uri) + */ + public void setDataSource(Context context, Uri uri) { + initPlayer(); + + try { + mMediaPlayer.setDataSource(context, uri); + mIsDataSourceSet = true; + prepare(); + } catch (IOException e) { + Log.d(TAG, e.getMessage()); + } + } + + /** + * @see android.media.MediaPlayer#setDataSource(java.io.FileDescriptor) + */ + public void setDataSource(AssetFileDescriptor afd) { + initPlayer(); + + try { + long startOffset = afd.getStartOffset(); + long length = afd.getLength(); + mMediaPlayer.setDataSource(afd.getFileDescriptor(), startOffset, length); + mIsDataSourceSet = true; + prepare(); + } catch (IOException e) { + Log.d(TAG, e.getMessage()); + } + } + + private void prepare() { + try { + mMediaPlayer.setOnVideoSizeChangedListener( + new MediaPlayer.OnVideoSizeChangedListener() { + @Override + public void onVideoSizeChanged(MediaPlayer mp, int width, int height) { + mVideoWidth = width; + mVideoHeight = height; + updateTextureViewSize(); + } + } + ); + mMediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() { + @Override + public void onCompletion(MediaPlayer mp) { + mState = State.END; + log("Video has ended."); + + if (mListener != null) { + mListener.onVideoEnd(); + } + } + }); + + mMediaPlayer.prepareAsync(); + + // Play video when the media source is ready for playback. + mMediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() { + @Override + public void onPrepared(MediaPlayer mediaPlayer) { + mIsVideoPrepared = true; + if (mIsPlayCalled && mIsViewAvailable) { + log("Player is prepared and play() was called."); + play(); + } + + if (mListener != null) { + mListener.onVideoPrepared(); + } + } + }); + + mMediaPlayer.setOnErrorListener(new MediaPlayer.OnErrorListener() { + @Override + public boolean onError(MediaPlayer mediaPlayer, int i, int i2) { + return false; + } + }); + + } catch (IllegalArgumentException e) { + Log.d(TAG, e.getMessage()); + } catch (SecurityException e) { + Log.d(TAG, e.getMessage()); + } catch (IllegalStateException e) { + Log.d(TAG, e.toString()); + } + } + + /** + * Play or resume video. Video will be played as soon as view is available and media player is + * prepared. + * + * If video is stopped or ended and play() method was called, video will start over. + */ + public void play() { + play(0); + } + + public void play(int startPosition) { + if (!mIsDataSourceSet) { + log("play() was called but data source was not set."); + return; + } + + mIsPlayCalled = true; + + if (!mIsVideoPrepared) { + log("play() was called but video is not prepared yet, waiting."); + return; + } + + if (!mIsViewAvailable) { + log("play() was called but view is not available yet, waiting."); + return; + } + + if (mState == State.PLAY) { + log("play() was called but video is already playing."); + return; + } + + if (mState == State.PAUSE) { + log("play() was called but video is paused, resuming."); + mState = State.PLAY; + mMediaPlayer.start(); + return; + } + + mState = State.PLAY; + mMediaPlayer.seekTo(startPosition); + mMediaPlayer.start(); + } + + /** + * Pause video. If video is already paused, stopped or ended nothing will happen. + */ + public void pause() { + if (mState == State.PAUSE) { + log("pause() was called but video already paused."); + return; + } + + if (mState == State.STOP) { + log("pause() was called but video already stopped."); + return; + } + + if (mState == State.END) { + log("pause() was called but video already ended."); + return; + } + + mState = State.PAUSE; + if (mMediaPlayer.isPlaying()) { + mMediaPlayer.pause(); + } + } + + /** + * Stop video (pause and seek to beginning). If video is already stopped or ended nothing will + * happen. + */ + public void stop() { + if (mState == State.STOP) { + log("stop() was called but video already stopped."); + return; + } + + if (mState == State.END) { + log("stop() was called but video already ended."); + return; + } + + mState = State.STOP; + if (mMediaPlayer.isPlaying()) { + mMediaPlayer.pause(); + mMediaPlayer.seekTo(0); + } + } + + /** + * @see android.media.MediaPlayer#setLooping(boolean) + */ + public void setLooping(boolean looping) { + mMediaPlayer.setLooping(looping); + } + + /** + * @see android.media.MediaPlayer#seekTo(int) + */ + public void seekTo(int milliseconds) { + mMediaPlayer.seekTo(milliseconds); + } + + /** + * @see android.media.MediaPlayer#getDuration() + */ + public int getDuration() { + return mMediaPlayer.getDuration(); + } + + /** + * @see android.media.MediaPlayer#getCurrentPosition() + */ + public int getCurrentPosition() { return mMediaPlayer.getCurrentPosition(); } + + static void log(String message) { + if (LOG_ON) { + Log.d(TAG, message); + } + } + + private MediaPlayerListener mListener; + + /** + * Listener trigger 'onVideoPrepared' and `onVideoEnd` events + */ + public void setListener(MediaPlayerListener listener) { + mListener = listener; + } + + public interface MediaPlayerListener { + + public void onVideoPrepared(); + + public void onVideoEnd(); + } + + @Override + public void onSurfaceTextureAvailable(SurfaceTexture surfaceTexture, int width, int height) { + Surface surface = new Surface(surfaceTexture); + mMediaPlayer.setSurface(surface); + mIsViewAvailable = true; + if (mIsDataSourceSet && mIsPlayCalled && mIsVideoPrepared) { + log("View is available and play() was called."); + play(); + } + } + + @Override + public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) { + + } + + @Override + public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) { + return false; + } + + @Override + public void onSurfaceTextureUpdated(SurfaceTexture surface) { + + } +} \ No newline at end of file diff --git a/kute-android-app/app/src/main/java/com/scorelab/kute/kute/SplashActivity.java b/kute-android-app/app/src/main/java/com/scorelab/kute/kute/SplashActivity.java index 3349d730..9a7524f5 100644 --- a/kute-android-app/app/src/main/java/com/scorelab/kute/kute/SplashActivity.java +++ b/kute-android-app/app/src/main/java/com/scorelab/kute/kute/SplashActivity.java @@ -5,20 +5,43 @@ import android.content.SharedPreferences; import android.graphics.Bitmap; import android.os.AsyncTask; +import android.os.Handler; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; +import android.view.View; import com.google.firebase.database.FirebaseDatabase; +import com.hanks.htextview.typer.TyperTextView; import com.scorelab.kute.kute.Activity.RegisterActivity; import com.scorelab.kute.kute.Activity.SwitchPrivatePublicActivity; import com.scorelab.kute.kute.Util.ImageHandler; public class SplashActivity extends AppCompatActivity { static FirebaseDatabase fb; + TyperTextView ttv; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_splash); + ttv = (TyperTextView) findViewById(R.id.ttv); + ttv.setSoundEffectsEnabled(false); + ttv.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + ((TyperTextView)v).animateText("A Commute App for Sri Lanka"); + } + }); + + new Handler().postDelayed(new Runnable() { + @Override + public void run() { + ttv.performClick(); + } + },2500); + + + + new DelayTask().execute(); // This will delay the spalsh scrren and redierct to the login/register screen based //on the ststus of the user. @@ -30,7 +53,7 @@ class DelayTask extends AsyncTask{ @Override protected Void doInBackground(Void... params) { try { - Thread.sleep(4000); + Thread.sleep(5000); } catch (Exception e){ @@ -49,10 +72,12 @@ protected void onPostExecute(Void aVoid) { Intent regIntent =new Intent(SplashActivity.this, RegisterActivity.class); startActivity(regIntent); + finish(); } else{ //User registered in the system. Intent switchIntent =new Intent(SplashActivity.this, SwitchPrivatePublicActivity.class); startActivity(switchIntent); + finish(); } diff --git a/kute-android-app/app/src/main/res/drawable/fb_icon.xml b/kute-android-app/app/src/main/res/drawable/fb_icon.xml new file mode 100644 index 00000000..e2505444 --- /dev/null +++ b/kute-android-app/app/src/main/res/drawable/fb_icon.xml @@ -0,0 +1,13 @@ + + + + + \ No newline at end of file diff --git a/kute-android-app/app/src/main/res/drawable/google_g_logo.xml b/kute-android-app/app/src/main/res/drawable/google_g_logo.xml new file mode 100644 index 00000000..c432cdfa --- /dev/null +++ b/kute-android-app/app/src/main/res/drawable/google_g_logo.xml @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/kute-android-app/app/src/main/res/drawable/score.jpg b/kute-android-app/app/src/main/res/drawable/score.jpg new file mode 100644 index 00000000..579ef296 Binary files /dev/null and b/kute-android-app/app/src/main/res/drawable/score.jpg differ diff --git a/kute-android-app/app/src/main/res/layout/activity_splash.xml b/kute-android-app/app/src/main/res/layout/activity_splash.xml index 9b3e849e..fdcb0038 100644 --- a/kute-android-app/app/src/main/res/layout/activity_splash.xml +++ b/kute-android-app/app/src/main/res/layout/activity_splash.xml @@ -4,24 +4,49 @@ xmlns:tools="http://schemas.android.com/tools" android:id="@+id/activity_splash" android:layout_width="match_parent" + android:background="@android:color/white" tools:context="com.scorelab.kute.kute.SplashActivity" android:layout_height="match_parent"> - - + android:layout_alignParentBottom="true" + android:scaleType="fitCenter" + android:layout_marginTop="440dp" + android:layout_marginBottom="40dp" + android:src="@drawable/score" /> + + + + + + + + + diff --git a/kute-android-app/app/src/main/res/layout/testreg.xml b/kute-android-app/app/src/main/res/layout/testreg.xml index 4b58cb0a..59eef3c4 100644 --- a/kute-android-app/app/src/main/res/layout/testreg.xml +++ b/kute-android-app/app/src/main/res/layout/testreg.xml @@ -1,44 +1,117 @@ - - - - - - - + + android:layout_height="match_parent" + android:paddingLeft="@dimen/activity_horizontal_margin" + android:paddingRight="@dimen/activity_horizontal_margin" + android:paddingTop="@dimen/activity_vertical_margin" + android:paddingBottom="@dimen/activity_vertical_margin" + android:orientation="vertical"> + + + + +