添加jellyfin client

This commit is contained in:
sifacaii 2022-08-30 20:58:30 +08:00
parent 9f9e36135e
commit 299595bcad
6 changed files with 373 additions and 119 deletions

2
.idea/misc.xml generated
View File

@ -27,7 +27,7 @@
<entry key="..\:/work/VlcJellyfin/app/src/main/res/layout/activity_main.xml" value="0.2957427536231884" /> <entry key="..\:/work/VlcJellyfin/app/src/main/res/layout/activity_main.xml" value="0.2957427536231884" />
<entry key="..\:/work/VlcJellyfin/app/src/main/res/layout/activity_search.xml" value="0.14791666666666667" /> <entry key="..\:/work/VlcJellyfin/app/src/main/res/layout/activity_search.xml" value="0.14791666666666667" />
<entry key="..\:/work/VlcJellyfin/app/src/main/res/layout/activity_vlc_player.xml" value="0.14895833333333333" /> <entry key="..\:/work/VlcJellyfin/app/src/main/res/layout/activity_vlc_player.xml" value="0.14895833333333333" />
<entry key="..\:/work/VlcJellyfin/app/src/main/res/layout/dialog_login.xml" value="0.2957427536231884" /> <entry key="..\:/work/VlcJellyfin/app/src/main/res/layout/dialog_login.xml" value="0.4" />
<entry key="..\:/work/VlcJellyfin/app/src/main/res/layout/home_horizon_tvrecycler.xml" value="0.14791666666666667" /> <entry key="..\:/work/VlcJellyfin/app/src/main/res/layout/home_horizon_tvrecycler.xml" value="0.14791666666666667" />
<entry key="..\:/work/VlcJellyfin/app/src/main/res/layout/item_h.xml" value="0.14895833333333333" /> <entry key="..\:/work/VlcJellyfin/app/src/main/res/layout/item_h.xml" value="0.14895833333333333" />
<entry key="..\:/work/VlcJellyfin/app/src/main/res/layout/item_title.xml" value="0.14895833333333333" /> <entry key="..\:/work/VlcJellyfin/app/src/main/res/layout/item_title.xml" value="0.14895833333333333" />

View File

@ -20,7 +20,7 @@
android:hardwareAccelerated="true" android:hardwareAccelerated="true"
tools:targetApi="31"> tools:targetApi="31">
<activity <activity
android:name=".MainActivity" android:name=".HomeActivity"
android:exported="true"> android:exported="true">
<intent-filter> <intent-filter>
<action android:name="android.intent.action.MAIN" /> <action android:name="android.intent.action.MAIN" />

View File

@ -0,0 +1,184 @@
package org.sifacai.vlcjellyfin;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import com.owen.tvrecyclerview.widget.V7LinearLayoutManager;
public class HomeActivity extends BaseActivity{
private final String TAG = "HomeActivity";
private LinearLayout tvContiner;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.jellyfin_home);
disableActiveBarBack();
tvContiner = findViewById(R.id.tvItems);
JfClient.init(this);
Log.d(TAG, "onCreate: " + JfClient.config.getJellyfinUrl());
if(JfClient.AccessToken.equals("") ||JfClient.UserId.equals("")){
showLoadingDialog("正在验证服务器地址!");
JfClient.VerityServerUrl(JfClient.config.getJellyfinUrl(),new JfClient.JJCallBack(){
@Override
public void onSuccess(Boolean bool) {
dismissLoadingDialog();
if(bool){
showLoadingDialog("正在验证用户名和密码!");
JfClient.AuthenticateByName(JfClient.config.getUserName(),JfClient.config.getPassWord(),new JfClient.JJCallBack(){
@Override
public void onSuccess(Boolean bool) {
dismissLoadingDialog();
if(bool){
initView(); //加载首页
}else{
showLoginDialog();
}
}
},false);
}else{
ShowToask("服务器地址不正确!");
showLoginDialog();
}
}
});
}else{
initView();
}
}
private void showLoginDialog(){
AlertDialog.Builder builder = new AlertDialog.Builder(this);
AlertDialog alert = builder.setTitle("登录")
.setMessage("请输入登录信息")
.setView(R.layout.dialog_login)
.show();
alert.setCanceledOnTouchOutside(false);
EditText urlbox = alert.findViewById(R.id.dialog_login_url);
EditText unbox = alert.findViewById(R.id.dialog_login_un);
EditText pwbox = alert.findViewById(R.id.dialog_login_pw);
CheckBox saveBox = alert.findViewById(R.id.dialog_login_save);
TextView submit = alert.findViewById(R.id.dialog_login_submit);
TextView cancel = alert.findViewById(R.id.dialog_login_cancel);
urlbox.setText(JfClient.config.getJellyfinUrl());
unbox.setText(JfClient.config.getUserName());
pwbox.setText(JfClient.config.getPassWord());
cancel.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
System.exit(0);
}
});
submit.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
showLoadingDialog("正在验证服务器地址!");
JfClient.VerityServerUrl(urlbox.getText().toString(),new JfClient.JJCallBack(){
@Override
public void onSuccess(Boolean bool) {
dismissLoadingDialog();
if(bool){
showLoadingDialog("正在验证用户名和密码!");
JfClient.AuthenticateByName(unbox.getText().toString(),pwbox.getText().toString(),new JfClient.JJCallBack(){
@Override
public void onSuccess(Boolean bool) {
dismissLoadingDialog();
if(bool){
alert.dismiss();
initView(); //加载首页
}else{
ShowToask("用户名密码不正确!");
}
}
},saveBox.isChecked());
}else{
ShowToask("服务器地址不正确!");
}
}
});
}
});
}
private void initView(){
JfClient.GetViews(new JfClient.JJCallBack(){
@Override
public void onSuccess(JsonArray views) {
showLoadingDialog("正在加载首页…………");
addRowTvRecyclerView("我的媒体", views, true);
dismissLoadingDialog();
}
});
}
/**
* 添加类别行
*/
private void addRowTvRecyclerView(String title, JsonArray data, boolean horizon) {
JRecyclerView tvRecyclerView = (JRecyclerView) LayoutInflater.from(this)
.inflate(R.layout.home_horizon_tvrecycler, null);
((V7LinearLayoutManager) tvRecyclerView.getLayoutManager()).setOrientation(V7LinearLayoutManager.HORIZONTAL);
JAdapter jAdapter = new JAdapter(data, horizon);
jAdapter.setOnItemClickListener(new JAdapter.OnItemClickListener() {
@Override
public void onClick(JsonObject jo) {
String type = Utils.getJsonString(jo, "Type").getAsString();
String itemId = jo.get("Id").getAsString();
Intent intent = null;
if (type.equals("Folder") || type.equals("CollectionFolder")) {
intent = new Intent(mAA, CollectionActivity.class);
} else {
intent = new Intent(mAA, DetailActivity.class);
}
intent.putExtra("itemId", itemId);
mAA.startActivity(intent);
}
});
tvRecyclerView.setAdapter(jAdapter);
TextView titleView = new TextView(tvRecyclerView.getContext());
titleView.setText(title);
tvContiner.addView(titleView);
tvContiner.addView(tvRecyclerView);
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
exit();
return false;
}
return super.onKeyDown(keyCode, event);
}
private long exitTime = 0;
public void exit() {
if ((System.currentTimeMillis() - exitTime) > 2000) {
Toast.makeText(getApplicationContext(), "再按一次退出程序",
Toast.LENGTH_SHORT).show();
exitTime = System.currentTimeMillis();
} else {
finish();
System.exit(0);
}
}
}

View File

@ -1,20 +1,34 @@
package org.sifacai.vlcjellyfin; package org.sifacai.vlcjellyfin;
import android.app.Activity;
import android.app.Application;
import android.content.Context;
import android.util.Log;
import com.google.gson.Gson; import com.google.gson.Gson;
import com.google.gson.JsonArray; import com.google.gson.JsonArray;
import com.google.gson.JsonElement; import com.google.gson.JsonElement;
import com.google.gson.JsonNull;
import com.google.gson.JsonObject; import com.google.gson.JsonObject;
import com.lzy.okgo.OkGo; import com.lzy.okgo.OkGo;
import com.lzy.okgo.cache.CacheEntity;
import com.lzy.okgo.cache.CacheMode;
import com.lzy.okgo.callback.AbsCallback; import com.lzy.okgo.callback.AbsCallback;
import com.lzy.okgo.model.HttpHeaders; import com.lzy.okgo.model.HttpHeaders;
import com.lzy.okgo.model.Response; import com.lzy.okgo.model.Response;
import java.io.IOException;
import java.util.concurrent.TimeUnit;
import okhttp3.OkHttpClient;
public class JfClient { public class JfClient {
public final String XEmbyAuthorization = "MediaBrowser Client=\"Vlc_J_TV\", Device=\"Vlc_J_TV\", DeviceId=\"TW96aWxsYS81LjAgKFdpbmRvd3MgTlQgNi4xOyBXa\", Version=\"10.8.1\""; public static final String TAG = "JellyfinClient";
public HttpHeaders headers; public static final String XEmbyAuthorization = "MediaBrowser Client=\"Vlc_J_TV\", Device=\"Vlc_J_TV\", DeviceId=\"TW96aWxsYS81LjAgKFdpbmRvd3MgTlQgNi4xOyBXa\", Version=\"10.8.1\"";
public String UserId=""; public static HttpHeaders headers;
public String AccessToken=""; public static Config config;
public String serverUrl; public static String UserId = "";
public static String AccessToken = "";
public enum ReportType { public enum ReportType {
playing, playing,
@ -22,23 +36,33 @@ public class JfClient {
stop stop
} }
/**
* 初始化配置
* @param context
*/
public static void init(Context context) {
config = new Config(context);
SetHeaders();
}
/** /**
* 回放报告 * 回放报告
*
* @param type * @param type
* @param id * @param id
* @param PositionTicks * @param PositionTicks
*/ */
public void ReportPlayBackState(ReportType type,String id,long PositionTicks){ public static void ReportPlayBackState(ReportType type, String id, long PositionTicks) {
String url = serverUrl; String url = config.getJellyfinUrl();
if(type == ReportType.playing){ if (type == ReportType.playing) {
url += "/Sessions/Playing"; url += "/Sessions/Playing";
}else if(type == ReportType.Progress){ } else if (type == ReportType.Progress) {
url += "/Sessions/Playing/Progress"; url += "/Sessions/Playing/Progress";
}else if(type == ReportType.stop){ } else if (type == ReportType.stop) {
url += "/Sessions/Playing/Stopped"; url += "/Sessions/Playing/Stopped";
} }
String reqstr = "{\"itemId\":\"" + id + "\",\"PositionTicks\":\"" + PositionTicks * 10000 + "\"}"; String reqstr = "{\"itemId\":\"" + id + "\",\"PositionTicks\":\"" + PositionTicks * 10000 + "\"}";
SendPost(url,reqstr,new JJCallBack(){ SendPost(url, reqstr, new JJCallBack() {
@Override @Override
public void onSuccess(String str) { public void onSuccess(String str) {
//回放报告 //回放报告
@ -48,49 +72,52 @@ public class JfClient {
/** /**
* 获取封面图url * 获取封面图url
*
* @param itemid * @param itemid
* @param tagid * @param tagid
* @return * @return
*/ */
public String GetImgUrl(String itemid, String tagid) { public static String GetImgUrl(String itemid, String tagid) {
String url = serverUrl + "/Items/" + itemid + "/Images/Primary"; String url = config.getJellyfinUrl() + "/Items/" + itemid + "/Images/Primary";
url += "?fillHeight=286&fillWidth=200&quality=96&tag=" + tagid; url += "?fillHeight=286&fillWidth=200&quality=96&tag=" + tagid;
return url; return url;
} }
public String GetImgUrl(JsonObject item) { public static String GetImgUrl(JsonObject item) {
String id = jeFromGson(item,"Id").getAsString(); String id = jeFromGson(item, "Id").getAsString();
String imgid = jeFromGson(jeFromGson(item,"ImageTags").getAsJsonObject(),"Primary").getAsString(); String imgid = jeFromGson(jeFromGson(item, "ImageTags").getAsJsonObject(), "Primary").getAsString();
return GetImgUrl(id,imgid); return GetImgUrl(id, imgid);
} }
/** /**
* 获取播放url * 获取播放url
*
* @param itemid * @param itemid
* @return * @return
*/ */
public String GetPlayUrl(String itemid){ public static String GetPlayUrl(String itemid) {
String playurl = serverUrl + "/videos/" + itemid + "/stream.mp4?static=true&a"; String playurl = config.getJellyfinUrl() + "/videos/" + itemid + "/stream.mp4?static=true&a";
return playurl; return playurl;
} }
/** /**
* 获取剧集 * 获取剧集
*
* @param seriesId 剧ID * @param seriesId 剧ID
* @param seasonId 季ID * @param seasonId 季ID
* @param cb * @param cb
*/ */
public void GetEpisodes(String seriesId,String seasonId,JJCallBack cb){ public static void GetEpisodes(String seriesId, String seasonId, JJCallBack cb) {
String EpisodesUrl = serverUrl + "/Shows/" + seriesId + "/Episodes?seasonId=" + seasonId; String EpisodesUrl = config.getJellyfinUrl() + "/Shows/" + seriesId + "/Episodes?seasonId=" + seasonId;
EpisodesUrl += "&userId=" + UserId; EpisodesUrl += "&userId=" + UserId;
EpisodesUrl += "&Fields=ItemCounts,PrimaryImageAspectRatio,BasicSyncInfo,CanDelete,MediaSourceCount,Overview"; EpisodesUrl += "&Fields=ItemCounts,PrimaryImageAspectRatio,BasicSyncInfo,CanDelete,MediaSourceCount,Overview";
SendGet(EpisodesUrl,new JJCallBack(){ SendGet(EpisodesUrl, new JJCallBack() {
@Override @Override
public void onSuccess(String str) { public void onSuccess(String str) {
JsonObject item = strToGson(str,JsonObject.class); JsonObject item = strToGson(str, JsonObject.class);
if (null != item) { if (null != item) {
JsonArray items = jeFromGson(item,"Items").getAsJsonArray(); JsonArray items = jeFromGson(item, "Items").getAsJsonArray();
cb.onSuccess(items); cb.onSuccess(items);
} }
} }
@ -100,19 +127,20 @@ public class JfClient {
/** /**
* 获取季(Seasons)数据 * 获取季(Seasons)数据
*
* @param seriesId 剧ID * @param seriesId 剧ID
* @param cb * @param cb
*/ */
public void GetSeasons(String seriesId,JJCallBack cb){ public static void GetSeasons(String seriesId, JJCallBack cb) {
String SeasonsUrl = serverUrl + "/Shows/" + seriesId + "/Seasons?userId=" + UserId; String SeasonsUrl = config.getJellyfinUrl() + "/Shows/" + seriesId + "/Seasons?userId=" + UserId;
SeasonsUrl += "&Fields=ItemCounts,PrimaryImageAspectRatio,BasicSyncInfo,MediaSourceCount"; SeasonsUrl += "&Fields=ItemCounts,PrimaryImageAspectRatio,BasicSyncInfo,MediaSourceCount";
SendGet(SeasonsUrl,new JJCallBack(){ SendGet(SeasonsUrl, new JJCallBack() {
@Override @Override
public void onSuccess(String str) { public void onSuccess(String str) {
JsonObject item = strToGson(str,JsonObject.class); JsonObject item = strToGson(str, JsonObject.class);
if(null != item){ if (null != item) {
JsonArray items = jeFromGson(item,"Items").getAsJsonArray(); JsonArray items = jeFromGson(item, "Items").getAsJsonArray();
cb.onSuccess(items); cb.onSuccess(items);
} }
} }
@ -121,19 +149,20 @@ public class JfClient {
/** /**
* 获取合集条目 * 获取合集条目
*
* @param parentId * @param parentId
* @param type 类型 movietvshows * @param type 类型 movietvshows
* @param sortBy 排序条件 评分加入时间 * @param sortBy 排序条件 评分加入时间
* @param sortOrder 排序规则 升序降序 * @param sortOrder 排序规则 升序降序
* @param limit 每页条数 * @param limit 每页条数
* @param page * @param page
* @param cb * @param cb
*/ */
public void GetCollection(String parentId,String type,String sortBy,String sortOrder,int limit,int page,JJCallBack cb){ public static void GetCollection(String parentId, String type, String sortBy, String sortOrder, int limit, int page, JJCallBack cb) {
String itemsUrl = serverUrl + "/Users/" + UserId + "/Items?ParentId=" + parentId + "&Limit=" + limit; String itemsUrl = config.getJellyfinUrl() + "/Users/" + UserId + "/Items?ParentId=" + parentId + "&Limit=" + limit;
itemsUrl += "&Recursive=true&Fields=PrimaryImageAspectRatio,BasicSyncInfo,Seasons,Episodes&ImageTypeLimit=1"; itemsUrl += "&Recursive=true&Fields=PrimaryImageAspectRatio,BasicSyncInfo,Seasons,Episodes&ImageTypeLimit=1";
itemsUrl += "&EnableImageTypes=Primary,Backdrop,Banner,Thumb"; itemsUrl += "&EnableImageTypes=Primary,Backdrop,Banner,Thumb";
itemsUrl += "&SortBy="+sortBy+",SortName,ProductionYear&SortOrder=" + sortOrder; itemsUrl += "&SortBy=" + sortBy + ",SortName,ProductionYear&SortOrder=" + sortOrder;
if (type.equals("tvshows")) { if (type.equals("tvshows")) {
itemsUrl += "&IncludeItemTypes=Series"; itemsUrl += "&IncludeItemTypes=Series";
@ -145,10 +174,10 @@ public class JfClient {
int startIndex = page * limit - limit; int startIndex = page * limit - limit;
itemsUrl += "&StartIndex=" + startIndex; itemsUrl += "&StartIndex=" + startIndex;
SendGet(itemsUrl,new JJCallBack(){ SendGet(itemsUrl, new JJCallBack() {
@Override @Override
public void onSuccess(String str) { public void onSuccess(String str) {
JsonObject items = strToGson(str,JsonObject.class); JsonObject items = strToGson(str, JsonObject.class);
cb.onSuccess(items); cb.onSuccess(items);
} }
}); });
@ -156,20 +185,21 @@ public class JfClient {
/** /**
* 获取最新项目 * 获取最新项目
*
* @param parentId * @param parentId
* @param cb * @param cb
*/ */
public void GetLatest(String parentId,JJCallBack cb){ public static void GetLatest(String parentId, JJCallBack cb) {
String lastestUrl = serverUrl + "/Users/" + UserId + "/Items/Latest?"; String lastestUrl = config.getJellyfinUrl() + "/Users/" + UserId + "/Items/Latest?";
lastestUrl += "Limit=16&Fields=PrimaryImageAspectRatio%2CBasicSyncInfo%2CPath"; lastestUrl += "Limit=16&Fields=PrimaryImageAspectRatio%2CBasicSyncInfo%2CPath";
lastestUrl += "&ImageTypeLimit=1&EnableImageTypes=Primary,Backdrop,Thumb"; lastestUrl += "&ImageTypeLimit=1&EnableImageTypes=Primary,Backdrop,Thumb";
lastestUrl += "&ParentId=" + parentId; lastestUrl += "&ParentId=" + parentId;
SendGet(lastestUrl,new JJCallBack(){ SendGet(lastestUrl, new JJCallBack() {
@Override @Override
public void onSuccess(String str) { public void onSuccess(String str) {
JsonArray latestObj = strToGson(str,JsonArray.class); JsonArray latestObj = strToGson(str, JsonArray.class);
if(null != latestObj) { if (null != latestObj) {
cb.onSuccess(latestObj); cb.onSuccess(latestObj);
} }
} }
@ -178,19 +208,20 @@ public class JfClient {
/** /**
* 获取最近播放 * 获取最近播放
*
* @param cb * @param cb
*/ */
public void GetResume(JJCallBack cb){ public static void GetResume(JJCallBack cb) {
String resumeUrl = serverUrl + "/Users/" + UserId + "/Items/Resume?"; String resumeUrl = config.getJellyfinUrl() + "/Users/" + UserId + "/Items/Resume?";
resumeUrl += "Limit=12&Recursive=true&Fields=PrimaryImageAspectRatio,BasicSyncInfo"; resumeUrl += "Limit=12&Recursive=true&Fields=PrimaryImageAspectRatio,BasicSyncInfo";
resumeUrl += "&ImageTypeLimit=1&EnableImageTypes=Primary,Backdrop,Thumb"; resumeUrl += "&ImageTypeLimit=1&EnableImageTypes=Primary,Backdrop,Thumb";
resumeUrl += "&EnableTotalRecordCount=false&MediaTypes=Video"; resumeUrl += "&EnableTotalRecordCount=false&MediaTypes=Video";
SendGet(resumeUrl,new JJCallBack(){ SendGet(resumeUrl, new JJCallBack() {
@Override @Override
public void onSuccess(String str) { public void onSuccess(String str) {
JsonObject resumeObj = strToGson(str,JsonObject.class); JsonObject resumeObj = strToGson(str, JsonObject.class);
if(null != resumeObj) { if (null != resumeObj) {
JsonArray resumes = jeFromGson(resumeObj, "Items").getAsJsonArray(); JsonArray resumes = jeFromGson(resumeObj, "Items").getAsJsonArray();
cb.onSuccess(resumes); cb.onSuccess(resumes);
} }
@ -200,16 +231,17 @@ public class JfClient {
/** /**
* 获取首页 * 获取首页
*
* @param cb * @param cb
*/ */
public void GetViews(JJCallBack cb){ public static void GetViews(JJCallBack cb) {
String viewsUrl = serverUrl + "/Users/" + UserId + "/Views"; String viewsUrl = config.getJellyfinUrl() + "/Users/" + UserId + "/Views";
SendGet(viewsUrl,new JJCallBack(){ SendGet(viewsUrl, new JJCallBack() {
@Override @Override
public void onSuccess(String str) { public void onSuccess(String str) {
JsonObject viewsObj = strToGson(str,JsonObject.class); JsonObject viewsObj = strToGson(str, JsonObject.class);
if(null!=viewsObj){ if (null != viewsObj) {
JsonArray views = jeFromGson(viewsObj,"Items").getAsJsonArray(); JsonArray views = jeFromGson(viewsObj, "Items").getAsJsonArray();
cb.onSuccess(views); cb.onSuccess(views);
} }
} }
@ -218,16 +250,17 @@ public class JfClient {
/** /**
* 获取项目详情 * 获取项目详情
*
* @param itemid * @param itemid
* @param cb * @param cb
*/ */
public void GetItemInfo(String itemid,JJCallBack cb){ public static void GetItemInfo(String itemid, JJCallBack cb) {
String url = serverUrl + "/Users/" + UserId + "/Items/" + itemid; String url = config.getJellyfinUrl() + "/Users/" + UserId + "/Items/" + itemid;
SendGet(url,new JJCallBack(){ SendGet(url, new JJCallBack() {
@Override @Override
public void onSuccess(String str) { public void onSuccess(String str) {
JsonObject item = strToGson(str,JsonObject.class); JsonObject item = strToGson(str, JsonObject.class);
if(null != item){ if (null != item) {
cb.onSuccess(item); cb.onSuccess(item);
} }
} }
@ -236,29 +269,34 @@ public class JfClient {
/** /**
* 验证用户名密码 * 验证用户名密码
*
* @param username * @param username
* @param password * @param password
* @param cb * @param cb
*/ */
public void authenticateByName(String username,String password,JJCallBack cb){ public static void AuthenticateByName(String username, String password, JJCallBack cb, boolean saveUser) {
String url = serverUrl + "/Users/authenticatebyname"; String url = config.getJellyfinUrl() + "/Users/authenticatebyname";
String reqjson = "{\"Username\":\"" + username + "\",\"Pw\":\"" + password + "\"}"; String reqjson = "{\"Username\":\"" + username + "\",\"Pw\":\"" + password + "\"}";
SendPost(url,reqjson,new JJCallBack(){ SendPost(url, reqjson, new JJCallBack() {
@Override @Override
public void onSuccess(String str) { public void onSuccess(String str) {
JsonObject userObj = strToGson(str, JsonObject.class); JsonObject userObj = strToGson(str, JsonObject.class);
if (userObj != null) { if (userObj != null) {
String userId = jeFromGson(jeFromGson(userObj, "User").getAsJsonObject(),"Id").getAsString(); String userId = jeFromGson(jeFromGson(userObj, "User").getAsJsonObject(), "Id").getAsString();
String Token = jeFromGson(userObj,"AccessToken").getAsString(); String Token = jeFromGson(userObj, "AccessToken").getAsString();
if (!Token.equals("")) { if (!Token.equals("")) {
UserId = userId; UserId = userId;
AccessToken = Token; AccessToken = Token;
if (saveUser) {
config.setUserName(username);
config.setPassWord(password);
}
SetHeaders(); SetHeaders();
cb.onSuccess(true); cb.onSuccess(true);
}else { } else {
cb.onSuccess(false); cb.onSuccess(false);
} }
}else { } else {
cb.onSuccess(false); cb.onSuccess(false);
} }
} }
@ -267,14 +305,15 @@ public class JfClient {
/** /**
* 获取用户列表 * 获取用户列表
* @param cb *
* @param cb
*/ */
public void GetUsers(JJCallBack cb){ public static void GetUsers(JJCallBack cb) {
String url = serverUrl + "/users/public"; String url = config.getJellyfinUrl() + "/users/public";
SendGet(url,new JJCallBack(){ SendGet(url, new JJCallBack() {
@Override @Override
public void onSuccess(String str) { public void onSuccess(String str) {
JsonArray users = strToGson(str,JsonArray.class); JsonArray users = strToGson(str, JsonArray.class);
cb.onSuccess(users); cb.onSuccess(users);
} }
}); });
@ -282,34 +321,41 @@ public class JfClient {
/** /**
* 验证服务器地址 * 验证服务器地址
*
* @param url * @param url
* @param cb * @param cb
*/ */
public void VerityServerUrl(String url,JJCallBack cb){ public static void VerityServerUrl(String url, JJCallBack cb) {
SendGet(url + "/system/info/public",new JJCallBack(){ if (url.length() > 0) {
@Override if (url.startsWith("http://") || url.startsWith("https://")) {
public void onSuccess(String str) {
JsonObject serverInfo = strToGson(str,JsonObject.class); SendGet(url + "/system/info/public", new JJCallBack() {
if (serverInfo != null) { @Override
String ServerId = jeFromGson(serverInfo,"Id").getAsString(); public void onSuccess(String str) {
if (ServerId == null || ServerId.length() == 0) { JsonObject serverInfo = strToGson(str, JsonObject.class);
cb.onSuccess(false); String ServerId = jeFromGson(serverInfo, "Id") == null ? null : jeFromGson(serverInfo, "Id").getAsString();
} else { if (ServerId == null || ServerId.length() == 0) {
serverUrl = url; cb.onSuccess(false);
cb.onSuccess(true); } else {
config.setJellyfinUrl(url);
cb.onSuccess(true);
}
} }
} });
} }
}); }else{
cb.onSuccess(false);
}
} }
/** /**
* 设置请求头 * 设置请求头
*/ */
public void SetHeaders(){ public static void SetHeaders() {
headers = new HttpHeaders(); headers = new HttpHeaders();
String xea = XEmbyAuthorization; String xea = XEmbyAuthorization;
if(null != AccessToken && AccessToken.length() > 0){ if (null != AccessToken && AccessToken.length() > 0) {
xea += ", Token=\"" + AccessToken + "\""; xea += ", Token=\"" + AccessToken + "\"";
} }
headers.put("Accept", "application/json"); headers.put("Accept", "application/json");
@ -319,39 +365,46 @@ public class JfClient {
/** /**
* Get * Get
*
* @param url * @param url
* @param cb * @param cb
*/ */
public void SendGet(String url, JJCallBack cb){ public static void SendGet(String url, JJCallBack cb) {
OkGo.<String>get(url).headers(headers).execute(new AbsCallback<String>() { OkGo.<String>get(url).headers(headers).execute(new AbsCallback<String>() {
@Override @Override
public String convertResponse(okhttp3.Response response) throws Throwable { public String convertResponse(okhttp3.Response response) throws IOException {
String result = ""; String result = "";
if(null != response.body()){ if (null != response.body()) {
result = response.body().string(); result = response.body().string();
}
return result;
} }
return result;
}
@Override @Override
public void onSuccess(Response<String> response) { public void onSuccess(Response<String> response) {
cb.onSuccess(response.body()); cb.onSuccess(response.body());
} }
});
@Override
public void onError(Response<String> response) {
cb.onSuccess("");
}
});
} }
/** /**
* Post * Post
*
* @param url * @param url
* @param jsonStr * @param jsonStr
* @param cb * @param cb
*/ */
public void SendPost(String url, String jsonStr, JJCallBack cb){ public static void SendPost(String url, String jsonStr, JJCallBack cb) {
OkGo.<String>post(url).headers(headers).upJson(jsonStr).execute(new AbsCallback<String>() { OkGo.<String>post(url).headers(headers).upJson(jsonStr).execute(new AbsCallback<String>() {
@Override @Override
public String convertResponse(okhttp3.Response response) throws Throwable { public String convertResponse(okhttp3.Response response) throws Throwable {
String result = ""; String result = "";
if(null != response.body()){ if (null != response.body()) {
result = response.body().string(); result = response.body().string();
} }
return result; return result;
@ -361,11 +414,17 @@ public class JfClient {
public void onSuccess(Response<String> response) { public void onSuccess(Response<String> response) {
cb.onSuccess(response.body()); cb.onSuccess(response.body());
} }
@Override
public void onError(Response<String> response) {
cb.onSuccess("");
}
}); });
} }
/** /**
* Json字符串转Gson对象 * Json字符串转Gson对象
*
* @param jsonStr * @param jsonStr
* @param tClass * @param tClass
* @param <T> * @param <T>
@ -384,19 +443,20 @@ public class JfClient {
/** /**
* 按key获取JsonElement * 按key获取JsonElement
*
* @param obj * @param obj
* @param key * @param key
* @return * @return
*/ */
public static JsonElement jeFromGson(JsonObject obj,String key){ public static JsonElement jeFromGson(JsonObject obj, String key) {
JsonElement je = new Gson().fromJson("",JsonElement.class); JsonElement jo = null;
if(obj.has(key)){ if (obj != null && obj.has(key)) {
je = obj.get(key); jo = obj.get(key).getAsJsonObject();
} }
return je; return jo;
} }
public class JJCallBack implements JCallBack{ public static class JJCallBack implements JCallBack {
@Override @Override
public void onSuccess(String str) { public void onSuccess(String str) {
@ -419,10 +479,13 @@ public class JfClient {
} }
} }
public interface JCallBack{ public interface JCallBack {
void onSuccess(String str); void onSuccess(String str);
void onSuccess(Boolean bool); void onSuccess(Boolean bool);
void onSuccess(JsonObject jsonObject); void onSuccess(JsonObject jsonObject);
void onSuccess(JsonArray jsonArray); void onSuccess(JsonArray jsonArray);
} }
} }

View File

@ -3,43 +3,48 @@
android:orientation="vertical" android:orientation="vertical"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:padding="@dimen/padding_border" > android:padding="@dimen/padding_border"
android:paddingTop="0dp">
<EditText <EditText
android:id="@+id/dialog_login_url" android:id="@+id/dialog_login_url"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="@dimen/dialog_text_height"
android:inputType="text" android:inputType="text"
android:lines="1" android:lines="1"
android:nextFocusDown="@id/dialog_login_un"
android:hint="服务器地址"/> android:hint="服务器地址"/>
<EditText <EditText
android:id="@+id/dialog_login_un" android:id="@+id/dialog_login_un"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="@dimen/dialog_text_height"
android:inputType="text" android:inputType="text"
android:lines="1" android:lines="1"
android:nextFocusDown="@id/dialog_login_pw"
android:hint="用户名"/> android:hint="用户名"/>
<EditText <EditText
android:id="@+id/dialog_login_pw" android:id="@+id/dialog_login_pw"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="@dimen/dialog_text_height"
android:inputType="text" android:inputType="text"
android:lines="1" android:lines="1"
android:nextFocusDown="@id/dialog_login_save"
android:hint="密码"/> android:hint="密码"/>
<CheckBox <CheckBox
android:id="@+id/dialog_login_save" android:id="@+id/dialog_login_save"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="@dimen/dialog_text_height"
android:focusable="true" android:focusable="true"
android:background="@drawable/shape_user_focus" android:background="@drawable/shape_user_focus"
android:nextFocusDown="@id/dialog_login_submit"
android:text="保存用户" /> android:text="保存用户" />
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="@dimen/dialog_text_height"
android:orientation="horizontal"> android:orientation="horizontal">
<TextView <TextView

View File

@ -24,6 +24,8 @@
<dimen name="drawable_padding_s">6dp</dimen> <dimen name="drawable_padding_s">6dp</dimen>
<dimen name="drawable_padding_b">12dp</dimen> <dimen name="drawable_padding_b">12dp</dimen>
<!-- 登录框 -->
<dimen name="dialog_text_height">48dp</dimen>
<!-- 播放控制器 --> <!-- 播放控制器 -->
<dimen name="time_text_size">26dp</dimen> <dimen name="time_text_size">26dp</dimen>