Skip to content

Commit

Permalink
Merge pull request #26 from PyPiSan/dev
Browse files Browse the repository at this point in the history
New functionality added
  • Loading branch information
PyPiSan authored Nov 23, 2024
2 parents 7ccbf04 + 95d5b9e commit 5270ad6
Show file tree
Hide file tree
Showing 29 changed files with 705 additions and 215 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ KinAni is an Android app where you can watch anime, Asian dramas and movies.

## Download
App download Link
<a href="https://github.com/PyPiSan/KinAni/releases/download/v4.11.2-stable/KinAni.apk" target="_blank"><b>Download</b></a>
<a href="https://github.com/PyPiSan/KinAni/releases/download/v4.11.4-stable/KinAni.apk" target="_blank"><b>Download</b></a>

You can also download the latest release version.\
Release lower than 4.10.6 will not work.\
Expand Down
2 changes: 1 addition & 1 deletion app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ plugins {

def versionMajor = 4
def versionMinor = 11
def versionPatch = 3
def versionPatch = 4
def buildType="stable"

android {
Expand Down
2 changes: 1 addition & 1 deletion app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
xmlns:tools="http://schemas.android.com/tools" >

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="com.google.android.gms.permission.AD_ID"/>
<uses-permission android:name="com.google.android.gms.permission.AD_ID" />

<application
android:allowBackup="true"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
package com.pypisan.kinani.adapter;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;

import androidx.annotation.NonNull;
import androidx.cardview.widget.CardView;
import androidx.recyclerview.widget.RecyclerView;

import com.bumptech.glide.Glide;
import com.pypisan.kinani.R;
import com.pypisan.kinani.model.SavedVideosModel;

import java.util.ArrayList;

public class SavedVideosAdapter extends RecyclerView.Adapter<SavedVideosAdapter.SavedVideosViewHolder> {

private final ArrayList<SavedVideosModel> savedVideos;

private final Context context;
private final SelectListener listener;
public SavedVideosAdapter(ArrayList<SavedVideosModel> savedVideos, Context context, SelectListener listener){
this.savedVideos = savedVideos;
this.context = context;
this.listener = listener;

}
@NonNull
@Override
public SavedVideosViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.saved_videos_adapter, parent, false);
return new SavedVideosAdapter.SavedVideosViewHolder(view);
}

@Override
public void onBindViewHolder(@NonNull SavedVideosViewHolder holder, int position) {
ImageView picture = holder.picture;
TextView videoName = holder.videoName;
TextView episode = holder.episode;

// String image = savedVideos.get(position).getImage();
String name = savedVideos.get(position).getTitle();
String episodeNum = savedVideos.get(position).getEpisode();
String showType = savedVideos.get(position).getShowType();

Glide.with(context)
.load("https://gogocdn.net/cover/fairy-tail-100-years-quest.png")
.into(picture);
videoName.setText(name);
episode.setText(String.format("Episode: "+episodeNum));
holder.cardView.setOnClickListener(view -> {
listener.onItemClicked(name, episodeNum,showType);
});

}

@Override
public int getItemCount() {return savedVideos.size();}

public interface SelectListener {
void onItemClicked(String title, String Episode, String showType);
}

public class SavedVideosViewHolder extends RecyclerView.ViewHolder{

ImageView picture;
TextView videoName;
TextView episode;
CardView cardView;
public SavedVideosViewHolder(@NonNull View itemView) {
super(itemView);
this.picture = itemView.findViewById(R.id.Picture);
this.videoName = itemView.findViewById(R.id.video_name);
this.episode = itemView.findViewById(R.id.video_episode);
this.cardView = itemView.findViewById(R.id.videosCard);
}
}
}
28 changes: 28 additions & 0 deletions app/src/main/java/com/pypisan/kinani/model/SavedVideosModel.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package com.pypisan.kinani.model;


public class SavedVideosModel {

private String title, episode,showType;
public SavedVideosModel(String title, String episode, String showType){
this.title = title;
this.episode = episode;
this.showType = showType;
}

public SavedVideosModel(){

}

public String getTitle() {
return title;
}

public String getEpisode() {
return episode;
}

public String getShowType() {
return showType;
}
}
114 changes: 104 additions & 10 deletions app/src/main/java/com/pypisan/kinani/play/VideoPlayer.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import androidx.coordinatorlayout.widget.CoordinatorLayout;

import android.annotation.SuppressLint;
import android.app.DownloadManager;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ActivityInfo;
Expand All @@ -15,6 +16,7 @@
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.view.GestureDetector;
import android.view.LayoutInflater;
import android.view.MotionEvent;
Expand Down Expand Up @@ -52,7 +54,7 @@
import com.pypisan.kinani.model.EpisodeVideoModel;
import com.pypisan.kinani.storage.AnimeManager;
import com.pypisan.kinani.storage.Constant;

import java.io.File;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
Expand All @@ -62,7 +64,9 @@
public class VideoPlayer extends AppCompatActivity implements SessionAvailabilityListener {

private TextView animeTitleView, summaryTextView, videoHead, qualityButton, saveButton,
lockButton, playbackSpeedButton, high, medium, avg, low, qualityText;
lockButton, playbackSpeedButton, high, medium, avg, low, qualityText, highDl,
mediumDl, avgDl, lowDl;

private StyledPlayerView playerView;
private boolean isFullScreen = false;
private ExoPlayer player;
Expand Down Expand Up @@ -139,6 +143,12 @@ protected void onCreate(Bundle savedInstanceState) {
avg = findViewById(R.id.avg);
low = findViewById(R.id.low);

// for Downloading Videos
highDl = findViewById(R.id.high_save);
mediumDl = findViewById(R.id.medium_save);
avgDl = findViewById(R.id.avg_save);
lowDl = findViewById(R.id.low_save);


// DisplayMetrics displayMetrics = new DisplayMetrics();
// getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
Expand Down Expand Up @@ -181,11 +191,13 @@ public void onSlide(@NonNull View bottomSheet, float slideOffset) {
}
});

qualityButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
qualityButton.setOnClickListener(v -> {
if (Constant.loggedInStatus){
bottomSetting.setVisibility(View.GONE);
qualityView.setVisibility(View.VISIBLE);
} else{
bottomSheetBehavior.setState(BottomSheetBehavior.STATE_COLLAPSED);
showCustomToast("Log in to change the quality");
}
});

Expand Down Expand Up @@ -222,12 +234,76 @@ public void onClick(View v) {
showCustomToast(currentSetQuality + " will apply to current video");
});

// For Saving Videos

saveButton.setOnClickListener(v -> {
bottomSetting.setVisibility(View.GONE);
dlView.setVisibility(View.VISIBLE);
if (Constant.loggedInStatus){
boolean isFile= Constant.isFileExists(getApplicationContext(), Constant.formatFileName(title, episode_num, type));
if (isFile){
bottomSheetBehavior.setState(BottomSheetBehavior.STATE_COLLAPSED);
showCustomToast("Content is already available");
} else{
bottomSetting.setVisibility(View.GONE);
dlView.setVisibility(View.VISIBLE);
}
} else{
bottomSheetBehavior.setState(BottomSheetBehavior.STATE_COLLAPSED);
showCustomToast("Log in to save the video");
}
});

highDl.setOnClickListener(v -> {
boolean success = saveVideoMethod(3);
bottomSheetBehavior.setState(BottomSheetBehavior.STATE_COLLAPSED);
dlView.setVisibility(View.GONE);
bottomSetting.setVisibility(View.VISIBLE);
if (success){
showCustomToast("Downloading.......");
} else{
showCustomToast("Content not available to download");
}
});

mediumDl.setOnClickListener(v -> {
boolean success = saveVideoMethod(2);
bottomSheetBehavior.setState(BottomSheetBehavior.STATE_COLLAPSED);
dlView.setVisibility(View.GONE);
bottomSetting.setVisibility(View.VISIBLE);
if (success){
showCustomToast("Downloading........");
}else{
showCustomToast("Content not available to download");
}

});

avgDl.setOnClickListener(v -> {
boolean success = saveVideoMethod(1);
bottomSheetBehavior.setState(BottomSheetBehavior.STATE_COLLAPSED);
dlView.setVisibility(View.GONE);
bottomSetting.setVisibility(View.VISIBLE);
if (success){
showCustomToast("Downloading.......");
}else{
showCustomToast("Content not available to download");
}

});

lowDl.setOnClickListener(v -> {
boolean success = saveVideoMethod(0);
bottomSheetBehavior.setState(BottomSheetBehavior.STATE_COLLAPSED);
dlView.setVisibility(View.GONE);
bottomSetting.setVisibility(View.VISIBLE);
if (success){
showCustomToast("Downloading.......");
}else{
showCustomToast("Content not available to download");
}

});


lockButton.setOnClickListener(v -> {
isFullScreen = checkOrientation();
if (isFullScreen){changeOrientation(true);}
Expand Down Expand Up @@ -302,11 +378,9 @@ public void onClick(View v) {

// Setting Button Click Listener
settingButton.setOnClickListener(v -> {
// settingDialog.show();
if (bottomSheetBehavior.getState() == BottomSheetBehavior.STATE_COLLAPSED) {
// Expand the Bottom Sheet
// Set the quality text

qualityText.setText(String.format("%s %s", getString(R.string.current_quality),
currentSetQuality));
bottomSheetBehavior.setState(BottomSheetBehavior.STATE_EXPANDED);
Expand Down Expand Up @@ -422,7 +496,6 @@ public void onResponse(Call<EpisodeVideoModel> call, Response<EpisodeVideoModel>
public void onFailure(Call<EpisodeVideoModel> call, Throwable t) {
videoLoading.setVisibility(View.GONE);
reloadButton.setVisibility(View.VISIBLE);
Toast.makeText(getApplicationContext(), "Not found, Click Retry", Toast.LENGTH_LONG).show();
showCustomToast("Not found, Click Retry");
}
});
Expand Down Expand Up @@ -659,6 +732,7 @@ private void showCustomToast(String message) {
toastTextView.setText(message);
Toast toast = new Toast(getApplicationContext());
toast.setView(layout);
toast.setDuration(Toast.LENGTH_LONG);
toast.show();
}

Expand All @@ -673,4 +747,24 @@ private void simulateDoubleTapForward(ImageView forwardImage) {
// Hide the TextView after the animation ends
new Handler().postDelayed(() -> forwardImage.setVisibility(View.GONE), 600);
}

private Boolean saveVideoMethod(int index){
String link = videoDownloadLink[index];
if (link != null && !link.equals("")){
DownloadManager downloadmanager = (DownloadManager) getSystemService(Context.DOWNLOAD_SERVICE);
Uri uri = Uri.parse(link);
DownloadManager.Request request = new DownloadManager.Request(uri);
String name = Constant.formatFileName(title, episode_num, type);
request.setTitle(name);
request.setDescription("Downloading");
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
request.setVisibleInDownloadsUi(true);
File file = new File(getExternalFilesDir(Constant.storageLocation), name);
Uri fileUri = Uri.fromFile(file);
request.setDestinationUri(fileUri);
downloadmanager.enqueue(request);
return true;
}
return false;
}
}
30 changes: 30 additions & 0 deletions app/src/main/java/com/pypisan/kinani/storage/Constant.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
package com.pypisan.kinani.storage;

import android.content.Context;
import android.os.Environment;
import com.pypisan.kinani.R;
import java.io.File;

public class Constant {
public static String key;
Expand All @@ -18,10 +21,37 @@ public class Constant {
public static String about;
public static String message;

public static String storageLocation = Environment.DIRECTORY_DOWNLOADS;

public static final Integer[] userIconImage = {R.drawable.user_icon1,R.drawable.user_icon2,
R.drawable.user_icon3, R.drawable.user_icon4,R.drawable.user_icon5,R.drawable.user_icon6,
R.drawable.user_icon7,R.drawable.user_icon8,R.drawable.user_icon9,R.drawable.user_icon10,
R.drawable.user_icon11,R.drawable.user_icon12,R.drawable.user_icon13,R.drawable.user_icon14,
R.drawable.user_icon15,R.drawable.user_icon16,R.drawable.user_icon17,R.drawable.user_icon18,
R.drawable.user_icon19};

public static boolean isFileExists(Context context, String fileName) {
// Get the public Downloads directory
File targetFile = new File(context.getExternalFilesDir(Constant.storageLocation), fileName);
// Check if the file exists
return targetFile.exists();
}

public static String formatFileName(String title, String ep, String type){
if (type==null){
type = "anime";
}
return String.format(title+"_"+ep+"_"+type+".mp4");
}

public static String[] getName(String fileName){
// Remove the file extension
String withoutExtension = fileName.substring(0, fileName.lastIndexOf('.'));
// Split the string by "_"
String[] parts = withoutExtension.split("_");
if (parts.length == 3) {
return parts;
}
return new String[] {""};
}
}
Loading

0 comments on commit 5270ad6

Please sign in to comment.